iOS部分小技巧 持续更新中

  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顺序也不定。此为分割效果

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值