Objective-C 的現代語法和新特性
Swift的確是一個很強大的語言,各種特性使用起來非常簡潔強大,但是目前來說,感覺成熟度還是不夠,所以商業專案中使用OC來說是比較穩健的行為。看來一下WWDC 2015的 Swift and Objective-C Interoperability session,視訊前半部分主要是講解swift和OC之間的互動的規則,後面則講到OC的一部分新的語言特性,這幾個特性,Apple的開發人員在WWDC上說的那樣,對程式碼的可讀性提升非常大,所以從swift中把這個特性引入到OC中,個人感覺也是為後續向swift的遷移提供支撐,最主要的是這些特性在iOS SDK中以及全面採用並且相容低版本,所以可以在當前工作中引入這些特性。
instancetype
這個方面可以參考我之前總結的一篇部落格,關於 id、NSObject *、id<NSObject>、instancetype的區別 : http://blog.csdn.net/colorapp/article/details/45317347
Properties
使用Properties來代替例項變數有很多優勢:
- Auto synthesized getters and setters. 使用@property宣告的屬效能自動生成getter與setter方法。
- Better declaration of intent of a set of methods. 比為屬性宣告一系列方法程式碼上要清晰很多。
- Property keywords that express additional information about behavior. Property使用其他的一些關鍵子可以表達一些例項變數無法表達的資訊,比如 assign, weak, atomic等等。
Property方法有一個非常簡明的命名規範,getter方法的名稱是property的名稱,setter方法的名稱是在property名稱之前新增set字首(駝峰法)。通過還可以通過getter關鍵字指定getter的名稱。
在宣告一個Property的時候,需要記住下面這些不能是properties的:
- init method
- copy method, mutableCopy method
- A class factory method
- 初始化一個action並返回一個BOOL結果的方法
- A method that explicitly changes internal state as a side effect of a getter
Enumration Marcos
使用NS_ENUM來定義列舉,使用NS_OPTIONS來定義options。這兩個巨集可以改善Xcode中的程式碼補全,明確指出列舉和options的型別和大小。
Object Initialization
可能是為了相容swift,OC中新增了 designated initializer 初始化方法和 convenience initializers 初始化方法:
- designated initializer : 負責呼叫superclass的初始化方法以及初始化自己的例項變數的初始化方法
- convenience initializers : 非designated initializer都被稱為designated initializer。這些initializer內部實現一般都是呼叫另外一個initializer,然而最終一系列鏈式呼叫之後,最終都會呼叫某一個designated initializer 方法來進行初始化行為。
實現一個designated initializer方法很簡單,通過NS_DESIGNATED_INITIALIZER巨集即可實現,但是使用designated initializer的時候,會有一些限制規則,跟swift中的這些規則非常類似。詳情可以參考:https://developer.apple.com/library/ios/releasenotes/ObjectiveC/ModernizationObjC/AdoptingModernObjective-C/AdoptingModernObjective-C.html
=======================================WWDC 2015===========================================
Nullability
Nullability特性用來指明 Objective-C/C 指標是否可以為nil。顯然,使用這個特性更能清晰表達API的意圖,同時可以提升編譯器的static checking,還有一點就可以提高這些API在swift中的可用性。如果使用Xcode 7的話,可能注意到在iOS SDK中這個特性已經被大量採用了。下面這種截圖說明了Nullability的用法。
OC是如何引入這個特性,並且又讓低版本的iOS支援的呢?Apple稱之為 Audited Regions,也就是下面這兩個巨集之間的區域,NS_ASSUME_NONNULL_BEGIN … NS_ASSUME_NONNULL_END。
Audited Regions對其中的指標做了一些預設的假設,Single-level指標被認為是nonnull的,NSError**指標被認為在各個指標level上面都是nullable的。所以我們在Audited Regions內只需要指明那些 nullable 或者 null_unspecified的場景。
在C指標中使用 Nullability 的話,與OC中不同的地方在於,使用的nullability qualifier需要在前面新增雙下劃線,並且要將nullability qualifier寫在指標後面。例如下面:
Lightweight Generics
這個輕量級泛型,一方面會提高程式碼可讀性,讓API變得更加清晰。另外一方面,還能使編譯器會幫助我們做一些型別檢查,找到一些潛在的錯誤,達到 Type Safety的效果。
日常主要的用法是針對兩個集合類的,NSArray與NSDictionary,詳細用法可以參考官方SDK中的使用。同時,我們也可以在我們自己的程式碼來使用這個輕量級泛型,在自定義類,category,extension等等。
自定義類中的使用語法:
Category / Extension的使用語法:
WWDC中還強調了一點是,Lightweight Generics 是向前相容的,不會更改OC的runtime,同時也不會對生成的程式碼造成任何影響。
__kindof
在OC中,我們的程式碼中會大量使用id這個特性,這個特性用起來會帶來很多很方便的特性,但是它有個缺陷,我們經常需要進行強制型別轉換。Xcode 7中有個新特性,__kindof,“Kindof” types express “some kind of X”,用__kind修飾的變數表示是某個類或者這個類的子類。
當我們把這個類或者子類的其他變數賦值給這個變數時,編譯器會預設幫我們進行型別轉換以及型別檢查工作,這樣就不需要我們寫一些強制型別轉換這樣的程式碼了。最簡單的一個例子是在UITableView的應用,cellForRowAtIndexPath:返回的變數使用這個修飾之後,我們就不再需要寫任何強制型別轉換了,例如,CustomCell *cell = [tableview cellForRowAtIndexPath:indexPath];
同時,我們可以將Kindof types和lightweight generics結合在一起,比如官方提供的特性:
關於id型別
看了上面這些新特性之後,你會發現在平時開發中,你真的還需要那麼多id嗎?大多數情況下,我們都可以使用一個更加精確的型別表示,這樣能避免一些例如 type safety的問題,同時也能讓程式碼更加清晰。下面看一下官方指明的替代id的情景:
- 在返回 “self” 的方法中,使用instancetype來代替id
- 大多數 Collections 都可以變成 Typed Collections 來代替id
- __kindof X * 來表示 “some subclass of X”,而不再使用id,可以減少型別強制轉換之類的程式碼
- id<SomeProtocol> 表示conforms to SomeProtocol的任意型別
那什麼情況下使用id呢?只有那些你確認要表示”an object of any type”的時候再使用id,否則,儘量使用其他語法代替id。
References
相關文章
- 如何給 PHP 新增新的語法特性 (譯)PHP
- MySQL8.0新特性-CTE語法支援MySql
- DPC++中的現代C++語言特性C++
- 【新特性速遞】當法語遇上FineUI(Bonjour)!UI
- CSS變數var()語法和用法和特性CSS變數
- Flutter - Dart特性語法FlutterDart
- JDK1.8新特性:Lambda表示式語法和內建函式式介面JDK函式
- 新的主鍵和外來鍵的語法
- 追隨 Kotlin/Scala,看 Java 12-15 的現代語言特性KotlinJava
- C++11新特性(一):語言特性C++
- C++11新特性(三):語言特性C++
- C++11新特性(二):語言特性C++
- 記錄jdk17相對於jdk8增加的一下主要語法糖和新特性JDK
- Android相容Java 8語法特性的原理分析AndroidJava
- Flutter學習之Dart語法特性FlutterDart
- Java從8到21的語言新特性Java
- 快速掌握es6+新特性及es6核心語法盤點
- 【Java8新特性】Lambda表示式基礎語法,都在這兒了!!Java
- Superedge的新特性和未來之路
- JavaScript 新語法 「雙問號語法」與「可選鏈語法」JavaScript
- Chrome 71 新特性[雙語+視訊]Chrome
- Objective-C執行時特性:Method Swizzling魔法Object
- 巧用 LLVM 特性: Objective-C Class Properties 解耦LVMObject解耦
- Go 語言的詞法分析和語法分析(1)Go詞法分析語法分析
- 《星露穀物語》:在遊戲之中,思考現代生活的療法遊戲
- 輸入法的新時代:搜狗、訊飛、百度鏖戰智慧語音
- Laravel 5.8 新特性和新變化 — 影片Laravel
- Oracle 18c新特性詳解 - 表和表空間相關的新特性Oracle
- JAVA語法糖和語法糖編譯Java編譯
- ES6中let 和 const 的新特性
- PHP7.4 新特性和廢棄的功能PHP
- ES6中的新特性:Iterables和iterators
- 新時代佈局中一些有意思的特性
- 探索ChatGPT和新的AI時代ChatGPTAI
- HTML基本語法和語義HTML
- C++2.0——語言新特性之Variadic TemplatesC++
- Go 語言的詞法分析和語法分析(2)—Import宣告的解析Go詞法分析語法分析Import
- 001@瞭解Objective-C語言的起源ObjectC語言
- 『Java 語法基礎』物件導向有哪些特性Java物件