2015-12-01 40 views
12

Swift 2有API availability checking爲什麼objective-c沒有API可用性檢查?

使用API​​太新了您的 最低目標OS

爲什麼不能Objective-C的編譯器做等價時,編譯器會給你一個錯誤?

我GOOGLE了客觀C API可用性檢查,只有迅速2個結果出來了,所以我假設編譯器爲目標C不能做到這一點。

+0

雨燕設計時考慮了這個功能,因此蘋果可能不會產生不兼容或阻礙了語言的能力,通常添加該功能。 Objective-C是非常動態的,並且很難在編譯時告訴運行時可用或不可用的內容。 – Avi

+0

看看https://developer.apple.com/library/ios/documentation/DeveloperTools/Conceptual/cross_development/Configuring/configuring.html 你基本上可以通過擺弄你的Base SDK和部署目標來達到同樣的效果但它更麻煩。 – pvg

+1

您可以使用'respondsToSelector:@selector(methodName)'來檢查它的可用性,因爲沒有像swift這樣的其他專用機制。 –

回答

19

警告(斯威夫特它是一個錯誤)只是沒有在鏘編譯器多年來一直實施的,但它不是一個固有的Objective-C的限制(雖然由於其動態特性,你將不能夠抓住所有情況),也不是Swift術語。

蘋果宏(例如,NS_CLASS_AVAILABLE)和源屬性(__attribute__((visibility(...)))__attribute__((availability(...))))註釋與可用性信息標題已經存在了多年,並在蘋果公司的軟件開發工具包它們被廣泛使用。所述宏是在FoundationNSObjCRuntime.h定義,Availability.h/AvailabilityMacros.h系統頭,並且編譯器可以(並且不會)讀取它們。

在2015年年初,-Wpartial-availability警告has been added到鏘的master分支,但這次提交/警告沒有作出它的方式成蘋果版鏘,直到(含)的Xcode 7.2。將警告標誌添加到Xcode 7中的項目時,您將得到一個unknown warning option日誌。2,但該標誌在Xcode 7.3中可用。目前沒有預定義的設置,但可以在構建設置下將標記添加到Other Warning Flags

還有其他工具使用LLVM庫來檢測部分可用的API,例如Deploymate。對於我的畢業論文,我開發了一個直接集成到Xcode中的工具,並基於對Clang編譯器的修改。該代碼仍然是online,但我沒有跟上一般的Clang開發,所以除了學習目的外,它沒有什麼用處。然而,「官方」的代碼(上面鏈接)更清潔,更好。

編輯:從Xcode 9開始,可用性檢查也適用於Objective-C(和C)。除了使用上述警告標誌(它不支持暫時/本地地提升部署目標並因此導致大量誤報)之外,還有-Wunguarded-availabilityif (@available(iOS 11, *)) {...}來檢查並提高下面的代碼塊的部署目標。它默認關閉,但-Wunguarded-availability-new默認開啓,並開始檢查iOS/tvOS 11,watchOS 4和High Sierra以外的任何內容。有關詳情,請參閱Xcode 9 beta release notes,該帳戶目前需要使用開發者帳戶登錄。

+0

感謝您鏈接部署和您的論文。它看起來很有趣。 – okysabeni

+0

@hagi。感謝關於部分可用性標誌的觀點。我能夠用Xcode 7.2連接最新的clang並獲得警告。 https://gist.github.com/vigneshr89/befe6a99e7979772e449 – Vignesh

+1

Xcode 7.3 beta版似乎帶有一個Clang版本,它支持開箱即用的標誌:) – hagi

-3

當然,您將在Objective-C代碼中看到錯誤。但是,如果您使用爲Swift定義的術語,則無法在Objective-C的Google中找到結果,因爲如果搜索德語單詞,您將無法在Google中找到kisuaheli網站。 ;-)

您將獲得針對太舊SDK聯的Objective-C代碼中的錯誤。這僅僅是因爲在該SDK的頭文件中未定義使用的方法或類或$ whatever。當然,再次。

這是蘋果的典型斯威夫特營銷:由於雨燕的無能,他們必須擴展語言得到的東西,這是在Objective-C很容易。與其澄清這是Swift的糟糕結果,他們告訴你這是Swift的一個重要特性。這就像切割你的手指,然後說:「我們有偉大的石膏特徵!!!!!!!!」而且你必須等待幾天,然後用Q來解決問題:「爲什麼Objective-C沒有很好的石膏特徵???????」簡單的回答:它不會割傷你的手指。

問題是產生的誤差。問題是所有版本都有一個源代碼,因此您可以簡單地更改SDK版本並獲取新代碼(或錯誤)。你需要這個以便於維護。

在Objective-C,你可以簡單地使用應答這裏找到: Conditionally Hide Code from the Compiler或者你可以這樣做,在作爲註釋到Q.提到的(但是,這本質上是一個問題的不同的解決方案,運行時間,因爲它一個動態的方法,而不是像Swift那樣的靜態方法。)

在Swift中使用語言功能的原因是Swift沒有預處理器,所以Objective-C解決方案在Swift中不起作用。因此,條件代碼在Swift中是不可能的,他們必須添加石膏,呃語言特徵。

3

Objective C沒有可用性檢查作爲語言的一部分,因爲通過Objective C預處理器可以得到相同的結果。這是C語言中的「傳統」方法。

想知道如果在調試模式下編譯?

#ifdef DEBUG 
    // code which will be inserted only if compiled in debug mode 
#endif 

想要在編譯時檢查最低版本嗎? 使用iOS中的Availability.h頭文件和Mac OS X中的類似頭文件。

此文件駐留在/ usr/include目錄中。

只是測試__IPHONE_OS_VERSION_MAX_ALLOWED與預處理,例如:

#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000 
      if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) { 
       [[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert) categories:nil]]; 
      }else{ 
       [[UIApplication sharedApplication] registerForRemoteNotificationTypes: (UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert)]; 
      } 
#else 
      [[UIApplication sharedApplication] registerUserNotificationSettings: (UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert)]; 
#endif 

隨着斯威夫特沒有一個預處理器,他們不得不發明了語言本身做這幾樣檢查的一種方式。

如果你想在運行時檢查方法的有效性,請注意適當的方法是使用方法respondsToSelector:,或instancesRespondToSelector:(後者在類級別)。

您通常需要將兩種方法,編譯時條件編譯和運行時檢查結合起來。目標C方法存在驗證,例如,在類級別:

if ([UIImagePickerController instancesRespondToSelector: 
       @selector (availableCaptureModesForCameraDevice:)]) { 
    // Method is available for use. 
    // Your code can check if video capture is available and, 
    // if it is, offer that option. 
} else { 
    // Method is not available. 
    // Alternate code to use only still image capture. 
} 

如果你想測試一個C函數在運行時存在,那麼就更簡單了:如果存在,函數本身是不爲空。

您無法在兩種語言中使用相同的方法。

37

Xcode 9。0帶來的運行可用性檢查從斯威夫特語法的Objective-C:

if (@available(macOS 10.9, *)) 
{ 
// call 10.9+ API 
} 
else 
{ 
// fallback code 
} 

這個來完全與警告,呼籲那些比你的部署目標更新(如果這些電話沒有在檢查包裹)的API。

最後;)

+0

它是運行時檢查嗎? – Itachi

+0

是它的運行時檢查 – user1259710

相關問題