WWDC2017-- What's New in LLV

2017-08-15  本文已影响71人  程序媛coco

Objective - C 可用性检查

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

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

应用指定方法:在方法实现里无需再加@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
if (__builtin_available(iOS 11, macOS 10.13, *)) { 
    CFNewAPIOniOS11();
}
#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的一些错误比较方式
@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
上一篇 下一篇

猜你喜欢

热点阅读