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
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,837評論 18 139
  • 發現 關注 消息 iOS 第三方庫、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,188評論 4 61
  • iOS網絡架構討論梳理整理中。。。 其實如果沒有APIManager這一層是沒法使用delegate的,畢竟多個單...
    yhtang閱讀 5,237評論 1 23
  • 禪與 Objective-C 編程藝術 (Zen and the Art of the Objective-C C...
    GrayLand閱讀 1,643評論 1 10
  • 沒有錢,不能生活。 沒有詩和遠方,如同茍且。 詩和遠方召喚著我,錢在眼前氣勢洶洶。 我是一只短腿的螞蟻,遠方那么遠...
    又新閱讀 153評論 0 0