iOS部分小技巧 持续更新中

来源:互联网 发布:四级网络课程哪个好 编辑:程序博客网 时间:2024/05/16 15:35
  1. 可以在viewWillDisappear中判断下一个页面是pop、push还是present的
  2. 画圆的三种方式
  3. 获取当前控制器
  4. 消除警告
  5. UIButton中的TitleEdgeInsets使用
  6. 定位后的反编译和地区中文首字母缩写
  7. 更改 UINavigationBar 的返回键文字(同时保留右滑返回)
  8. NSDictionary/NSArray 转 JSON字符串
  9. KeyChain 保存密码
  10. 退出到最外层
  11. 关于 dispatch_barrier_async 的使用

1、可以在viewWillDisappear中判断下一个页面是pop、push还是present的

    NSArray *viewControllers = self.navigationController.viewControllers;    if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) {        // View is disappearing because a new view controller was pushed onto the stack        NSLog(@"New view controller was pushed");    } else if ([viewControllers indexOfObject:self] == NSNotFound) {        // View is disappearing because it was popped from the stack        NSLog(@"View controller was popped");    }    else if (viewControllers.count <= 1) {        NSLog(@"View controller was present");    }

2、画圆的三种方式

1. 贝塞尔曲线画范围,Context上下文截取
    - (UIImage *)makeRoundImage:(UIImage *)image {        CGFloat imageWidth = image.size.width;        CGFloat imageHeight = image.size.height;        UIGraphicsBeginImageContextWithOptions(CGSizeMake(imageWidth, imageHeight), NO, 0.0);        UIGraphicsGetCurrentContext();        CGFloat radius = (imageWidth < imageHeight?imageHeight:imageHeight)*0.5;        UIBezierPath    *Bezier =   [UIBezierPath bezierPathWithArcCenter:CGPointMake(imageWidth*0.5, imageHeight*0.5) radius:radius startAngle:0 endAngle:M_PI*2 clockwise:YES];        [Bezier stroke];        [Bezier addClip];        [image drawInRect:CGRectMake(0, 0, imageWidth, imageHeight)];        UIImage *resultImage = UIGraphicsGetImageFromCurrentImageContext();        UIGraphicsEndImageContext();        return resultImage;    }
2. layer.cornerRadius设置为高度的一半,前提是宽高相同
        UIImageView *imageView  =   [UIImageView new];        imageView.layer.masksToBounds   = YES;        imageView.layer.cornerRadius    =   CGRectGetWidth(imageView.bounds)/2.0;
3. 直接通过sb跟xib设置,不过需要设置成固定值    http://www.360doc.com/content/15/0128/17/20918780_444509231.shtml

3、获取当前控制器

+ (UIViewController *)getCurrentVC{    UIViewController *result = nil;    UIWindow * window = [[UIApplication sharedApplication] keyWindow];    //app默认windowLevel是UIWindowLevelNormal,如果不是,找到UIWindowLevelNormal的    if (window.windowLevel != UIWindowLevelNormal)    {        NSArray *windows = [[UIApplication sharedApplication] windows];        for(UIWindow * tmpWin in windows)        {            if (tmpWin.windowLevel == UIWindowLevelNormal)            {                window = tmpWin;                break;            }        }    }    id  nextResponder = nil;    UIViewController *appRootVC=window.rootViewController;    //    如果是present上来的appRootVC.presentedViewController 不为nil    if (appRootVC.presentedViewController) {        nextResponder = appRootVC.presentedViewController;    }else{        UIView *frontView = [[window subviews] objectAtIndex:0];        nextResponder = [frontView nextResponder];    }    if ([nextResponder isKindOfClass:[UITabBarController class]]){        UITabBarController * tabbar = (UITabBarController *)nextResponder;        UINavigationController * nav = (UINavigationController *)tabbar.viewControllers[tabbar.selectedIndex];        //        UINavigationController * nav = tabbar.selectedViewController ; 上下两种写法都行        result=nav.childViewControllers.lastObject;    }else if ([nextResponder isKindOfClass:[UINavigationController class]]){        UIViewController * nav = (UIViewController *)nextResponder;        result = nav.childViewControllers.lastObject;    }else{        result = nextResponder;    }    return result;}

4、消除警告

http://www.jianshu.com/p/eb03e20f7b1c

5、UIButton中的TitleEdgeInsets使用

UIButton中的ImageEdgeInsets与TitleEdgeInsets都是针对当前位置生效的,即设置UIEdgeInsetsMake(a, b, c, d)则意味着向上偏移a、向左偏移b、向下偏移c、向右偏移d

6、定位后的反编译和地区中文首字母缩写

  CLLocation  *location   =   locations.lastObject;    CLGeocoder *revGeo = [[CLGeocoder alloc] init];    [revGeo reverseGeocodeLocation:location completionHandler:^(NSArray<CLPlacemark *> * _Nullable placemarks, NSError * _Nullable error) {        NSDictionary *dict =    [[placemarks objectAtIndex:0] addressDictionary];        NSString    *state  =   dict[@"State"];        NSMutableString *str = [NSMutableString stringWithString:state];        CFStringTransform((CFMutableStringRef) str, NULL, kCFStringTransformMandarinLatin, NO);        CFStringTransform((CFMutableStringRef)str, NULL, kCFStringTransformStripDiacritics, NO);        NSString *pinYin = [str capitalizedString];        NSArray *pinyinArr  =   [pinYin componentsSeparatedByString:@" "];        NSMutableString *totalString    =   [NSMutableString string];        for (int i=0; i<pinyinArr.count; i++) {            if (i != pinyinArr.count-1 || (![pinyinArr[i] isEqualToString:@"Sheng"] && [pinyinArr[i] isEqualToString:@"Shi"])) {                NSString    *nowState   =   pinyinArr[i];                [totalString appendString:[nowState substringToIndex:1]];            }        }        NSLog(@"%@",totalString);    }];

7、更改 UINavigationBar 的返回键文字(同时保留右滑返回)

目前为止,查到了许多种做法,然而实验之后发现,可行的暂且是有一种

self.navigationItem.backBarButtonItem   =   [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleDone target:self action:nil];

这里更改的是下一个 Push 过去的控制器的返回键的文字,图案的样式保留。

8、NSDictionary/NSArray 转 JSON字符串

+ (NSString *)jsonStringFormDict:(NSDictionary *)dict {    NSMutableString *jsonString = [NSMutableString string];    [jsonString appendString:@"{"];    [dict enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {        if (jsonString.length > 1) {            [jsonString appendString:@","];        }        [jsonString appendFormat:@"\"%@\":",key];        if ([obj isKindOfClass:[NSArray class]]) {            [jsonString appendString:[self jsonStringFormArray:obj]];        }        else {            if ([obj isKindOfClass:[NSDictionary class]]) {                [jsonString appendString:[self jsonStringFormDict:obj]];            }            else {                [jsonString appendFormat:@"\"%@\"",obj];            }        }    }];    [jsonString appendString:@"}"];    return jsonString;}+ (NSString *)jsonStringFormArray:(NSArray *)array {    NSMutableString *jsonString = [NSMutableString string];    [jsonString appendString:@"["];    for (int i=0; i<array.count; i++) {        if (i != 0) {            [jsonString appendString:@","];        }        if ([array[i] isKindOfClass:[NSDictionary class]]) {            [jsonString appendString:[self jsonStringFormDict:array[i]]];        }        else {            if ([array[i] isKindOfClass:[NSArray class]]) {                [jsonString appendString:[self jsonStringFormArray:array[i]]];            }            else {                [jsonString appendFormat:@"\"%@\"",array[i]];            }        }    }    [jsonString appendString:@"]"];    return jsonString;}

9、KeyChain 保存密码

  1. 打开 Capabilities 中的 Keychain Sharing 开关,否则在 iOS10 中会崩溃。
  2. 导入 Security.framework
  3. 编写 KeyChain 文件
////  XWSDKeyChain.h//  XWSDCarLoan////  Created by chenjintian on 17/2/13.//  Copyright © 2017年 CJT. All rights reserved.//#import <Foundation/Foundation.h>@interface XWSDKeyChain : NSObject+ (void)save:(NSString *)service data:(id)data;+ (id)load:(NSString *)service;+ (void)delete:(NSString *)service;@end////  XWSDKeyChain.m//  XWSDCarLoan////  Created by chenjintian on 17/2/13.//  Copyright © 2017年 CJT. All rights reserved.//#import "XWSDKeyChain.h"#import <Security/Security.h>@implementation XWSDKeyChain+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service {    return [NSMutableDictionary dictionaryWithObjectsAndKeys:            (id)kSecClassGenericPassword,(id)kSecClass,            service, (id)kSecAttrService,            service, (id)kSecAttrAccount,            (id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,            nil];}+ (void)save:(NSString *)service data:(id)data {    //Get search dictionary    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];    //Delete old item before add new item    SecItemDelete((CFDictionaryRef)keychainQuery);    //Add new object to search dictionary(Attention:the data format)    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];    //Add item to keychain with the search dictionary    SecItemAdd((CFDictionaryRef)keychainQuery, NULL);}+ (id)load:(NSString *)service {    id ret = nil;    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];    //Configure the search setting    //Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue    [keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];    [keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];    CFDataRef keyData = NULL;    if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {        @try {            ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];        } @catch (NSException *e) {            NSLog(@"Unarchive of %@ failed: %@", service, e);        } @finally {        }    }    if (keyData)        CFRelease(keyData);    return ret;}+ (void)delete:(NSString *)service {    NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];    SecItemDelete((CFDictionaryRef)keychainQuery);}@end

10、退出到最外层

presentingViewController:

UIViewController *vc = self;while (vc.presentingViewController) {    vc = vc.presentingViewController;}[vc dismissViewControllerAnimated:YES completion:nil];

pushViewController:

[self.navigationController popToRootViewControllerAnimated:YES];

11、关于 dispatch_barrier_async 的使用

dispatch_queue_t concurrentQueue = dispatch_queue_create("my.concurrent.queue", DISPATCH_QUEUE_CONCURRENT);    dispatch_async(concurrentQueue, ^(){        NSLog(@"dispatch-1");    });    dispatch_async(concurrentQueue, ^(){        NSLog(@"dispatch-2");    });    dispatch_barrier_async(concurrentQueue, ^(){        NSLog(@"dispatch-barrier");     });    dispatch_async(concurrentQueue, ^(){        NSLog(@"dispatch-3");    });    dispatch_async(concurrentQueue, ^(){        NSLog(@"dispatch-4");    });

代码是拷贝的,理解是自己的。

barrier 的翻译是栅栏,在代码中的意思就是用来分割、确定线程,在上面的输出中,前面两个输出1、2顺序不定,第三个一定为dispatch-barrier,第四五个输出3、4顺序也不定。此为分割效果

也可以放在最后,作为一个前面的线程都处理完毕的标记。

0 0