WWDC2017-- What's New in LLVM

Objective - C 可用性检查

场景:
由于iOS系统每年都会有新的功能新的API发布,我们希望能够把这些新API在我们的App里使用,但是你仍然要支持旧的系统,你不可能要求安装你App的用户的手机系统都是最新的,这些新的API在旧系统中无法使用;
但是在iOS系统里支持反向配置,可以设置build setting最低支持版本;
但是这样并不安全,如果你在iOS9的设备上调用了iOS11的方法,你的App就很有可能会Crash或出现其他意外情况;
下面就来说可用性检查怎么帮助用户安全配置App到旧的系统中?

以前的做法:
  • 查询OC运行时,来确定API是否适用,但是这样很容易出错或者忘记判断直接执行,如果出错很难测试定位问题,而且它需要不同的语法来检查每项全局变量、函数、类、实例方法和类方法;
  • 在Swift 2.0 已经支持使用语法关键字#available,在运行时查询API的可用性;编译器在编译时能捕捉缺失的可用性,相关的可以具体到WWDC 2015 <Swift in Practice>
现在的做法:
  • 在iOS11中把Swift的可用性检查引入到Objective - C
  • 如果直接调用新的API,编译器会报如下警告:
image.png
  • 使用@available查询API可用性,来处理警告

image.png

注:当当前是iOS11,@available结构返回值为真,这种情况下调用API很安全,如果当前系统不适合,则可以在else函数处理

  • if (@available(iOS 11, *)) 在iOS11或者更新的系统里返回真,* 号表明在其它所有平台上查询为真(比如macOS)
  • 可用性针对新系统定制的一套功能很方便

应用指定方法:在方法实现里无需再加@available检查可用性,但调用该方法的人需要使用,否则会收到警告

@interface MyAlbumController : UIViewController
- (void)showFaces API_AVAILABLE(ios(11.0)); 
@end

应用到指定类:

API_AVAILABLE(ios(11.0))
@interface MyAlbumController : UIViewController
- (void)showFaces; 
@end
C/C++的用性检查API
  • __builtin_available
if (__builtin_available(iOS 11, macOS 10.13, *)) { 
    CFNewAPIOniOS11();
}
  • API_AVAILABLE宏需要包含<os/availability.h>
#include <os/availability.h>
// 修饰方法
void myFunctionForiOS11OrNewer(int i) API_AVAILABLE(ios(11.0), macos(10.13));

// 修饰类
class API_AVAILABLE(ios(11.0), macos(10.13)) MyClassForiOS11OrNewer;

建议:对于现有项目,不建议直接使用新的API,需要使用@available或者API_AVAILABLE检查新API的可用性


对于查找定位bug,以下介绍一些Xcode的新功能,如静态分析新功能和编译器警告~

Analyzer 静态分析新功能

Analyzer擅长捕捉难以重现的极端的bug,下面介绍新加入Analyzer的三种情况:

对于 NSNumberCFNumberRef的一些错误比较方式
  • 错误一:NSNumber指针值直接和0比,这个操作实际上是将指针值和nil相比较
@property NSNumber *photoCount; 
- (BOOL)hasPhotos {
    return self.photoCount > 0;  // X 错误:不能用NSNumber直接和0比较
}
image.png
@property NSNumber *photoCount;
- (BOOL)hasPhotos {
return self.photoCount.integerValue > 0; // 正确: compare integer value to integer value
}
  • 错误二:布尔运算的隐式变换的歧义
@property NSNumber *faceCount;
- (void)identifyFaces { 
  if (self.faceCount)  // 歧义:这里`faceCount`是为nil还是0的时候return?
    return;
    // Expensive Processing
}
image.png

明确的和nil做比较!

@property NSNumber *faceCount;
- (void)identifyFaces {
    if (self.faceCount) != nil)
    return;
    // Expensive Processing
}

在Xcode设置检查选项:


image.png
函数 dispatch_once()的使用注意

这个函数它保证这个代码块会被调用一次并且只有一次,常用于初始化共享全局状态;
确保代码块只执行一次,第一个参数必须是global 或则 static的变量

image.png
image.png

解决方案:使用NSLock 确保初始化只执行一次

@implementation Album { 
NSLock *photosLock;
}
[photosLock lock];
if (self.photos == nil) { 
  self.photos = [self loadPhotos];
}
[photosLock unlock];
关于NSMutable类的copy 属性的检查

定义一个可变类型的propertycopy修饰时,一般会在该属性的Setter方法里对属性进行 -copy操作,这样会导致该可变类型变成不可变类型

会有如下问题:

image.png

Analyzer 中的提示信息:


image.png

解决方案:在Setter方法明确的执行 -mutableCopy,确保属性是可变的

image.png

相关WWDC议题:Finding Bugs Using Xcode Runtime Tools

编译器警告

Xcode9新加了100多个错误和警告,来帮助我们调试和处理问题,下面有两个很重要的错误警告:

在ARC的Block里捕获参数:

一般来说,在ARC的Block里捕获大多数的参数都很安全

请找出下面代码会出问题的地方:

- (BOOL)validateDictionary:(NSDictionary *)dict usingChecker:(Checker *)checker error:(NSError **)error {
    __block BOOL isValid = YES;
    [dict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
      if ([checker checkObject:obj forKey:key]) return; 
        *stop = YES;    
        isValid = NO;
      if (error) *error = [NSError errorWithDomain:...]; // 在 Block里分配参数是很不安全的
      // if (error) *error = [[[NSError errorWithDomain:...] retain] autorelease]; //默认会加上`__autoreleasing`
    }];
    return isValid; 
}

注意:

  1. 在 Block里分配参数是很不安全的,在ARC Block的外部参数会隐式的被加上__autoreleasing
  2. enumerateKeysAndObjectsUsingBlock这个block 内部默认有autoreleasepool

具体警告如下:


image.png

解决方案:使用__strong修饰输出参数,确保输出时对象存在,没有被销毁

image.png
声明没有参数的方法

在iOS9,需要明确指定无参为void, 不然会报如下警告:

image.png

明确设置函数的无参void 后,对该函数传递参数会直接报错:

image.png

在 Build Setting里配置:


image.png

(LTO:Link-Time Optimization)链接时间优化更新

相关WWDC 2016:What's New in LLVM


相关 Sessions

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,066评论 4 62
  • iOS网络架构讨论梳理整理中。。。 其实如果没有APIManager这一层是没法使用delegate的,毕竟多个单...
    yhtang阅读 5,174评论 1 23
  • 禅与 Objective-C 编程艺术 (Zen and the Art of the Objective-C C...
    GrayLand阅读 1,607评论 1 10
  • 没有钱,不能生活。 没有诗和远方,如同苟且。 诗和远方召唤着我,钱在眼前气势汹汹。 我是一只短腿的蚂蚁,远方那么远...
    又新阅读 146评论 0 0