下面的代碼你們一定再熟悉不過了,我們來重溫一下吧:
@property (strong, nonatomic) NSArray *someViews;
這絕對符合Objective-C完美主義開發者的标準。對它表示的屬性,不同人有不同觀點。但是,其中仍然存在着一些難以察覺的缺陷。
除非有現成的文件,或開發者全程都在一旁,否則光憑看是無法獲取信息的。
還是那句話——不确定。也許答案是reflection? 或許問題可以改成:除了UIView,有可能出現UIView子類嗎?
因為是一隊列……東西,知道那東西是什麼之後,經過cast後才能利用。
很遺憾,Swift支持泛型(generics)就意味着(Objective-C )隻會以optional的AnyObject集合的形式出現。如此一來,開發者要使用該屬性就必須在Swift和Objective-C之間進行轉換。
單單一個屬性就引發了這麼多擔憂,還挺讓人不安的。如果代碼本身引發很多質疑,出現error的可能性就大大增加,更别提在廣為熟知的Objective-C和語言新秀Swift之間相互調用(interoperability)了。現在有了nullability annotations——我最愛的Objective-C新功能之一,問題就簡單多了,編程也會省下很多麻煩。
現在談到API,(intent.)可能會,也可能不會返回nil。簡而言之,終于不用花費數小時來排除漏洞了。以下有三個選項:
再回到實例屬性。假設在運行時叠代這個屬性來創建某個用戶界面,在相應的位置應該有UIButton和UIView。
但是,天哪!——不論怎麼樣它們也不應該是nil啊。現在出現如下的信息:
@property (strong, nonatomic, nonnull) NSArray *someViews;
intent.大大提升了Objective-C,而且這個屬性也不會在Swift裡滿滿都是optional了。
開發者看看代碼就知道有沒有nil pointer了,太棒了!
計算機的靜态檢驗和Swift的可用性都得到了提升,最重要的是實現了API的intent通訊。
……Objective-C開發者們舉國歡慶。嗚呼,泛型的恩澤終于籠罩大地,這無疑是那些開發者勇士們的功勞。
如果把Cocoa Touch比作孩子們的睡前故事,那麼Objective-C就好比是主演,故事書肯定是以上面那段話結尾的。泛型的缺席一直以來是Objective-C開發者心頭之痛,而誕生32年之後,Objective-C終于也支持泛型了。2015 WWDC上Swift 2成為了鎂光燈下的寵兒,而Objective-C這一巨大的跨越卻被忽視了,實在委屈。支持泛型将帶來諸多改變,而且都是積極的改變。
現在可以定義屬性,下指令給編譯器來顯示所有UIView:
@property (strong, nonatomic, nonnull) NSArray<UIView *> *someViews;
向屬性強加UIView之外的東西時,編譯器會報錯。而且如今不用做大量頭痛的轉換(cast)了。
Objective-C支持泛型對Swift而言也是好消息。上次更新時,我們讓Swift知道對象不應該是optional的,現在Swift還知道它們是UIViews,如此一來含混不清的AnyObject聲明就不需要了。如今的Objective-C可以像C#、C 、Swift等語言一樣通過<>括号來表示類型了。雖然通常是對協議表示一緻性(conformance),但編譯器知道何時、何地以及如何運用它們,且運用是經過推理的。
再進一步,可以用參數來表示擴展(extensions)、類别(categories)和類(classes),好處不僅僅體現在集合(collections)上。泛型的強大體現在整個Objective-C之中,集合僅僅是結果而已。舉個例子,看看NSDictionary,開發者肯定會偷着樂吧:
@interface NSDictionary<KeyType, ObjectType> (Lookup) - (nullable ObjectType)objectForKey:(KeyType)aKey; @end
剛開始知道類型擦除(type erasure)是為了這個的時候,我有點兒不滿意,但考慮到老舊的Objective-C程序堆積在一起的問題,也就釋懷了。
類型擦除(type erasure)不但能實現二進制兼容,而且不改變Objective-C的執行時間。所以親愛的開發者們,C#的泛型的确勝過其他語言,皺皺眉頭,發幾句牢騷就算了,日子還得繼續呢。
啊,這是最後一部分重要内容。再次調用之前定義的屬性,就會顯示UIView。判斷裡面包含着views和buttons是再正常不過的事。
這種情況下,添加如下代碼會發生什麼呢?
[self.someViews[0] addTarget:self action:selector(aMethod:) forControlEvents:UIControlEventTouchUpInside];
啊,編譯器警告。
這就對啦,因為即便可以在這個屬性裡插入一個button,就算可以假設是個UIView,button也不一定沒有經過轉換。
新的KindOf特性能夠輕松解決這種始料未及的情況。我們再回到實例屬性上:
@property (strong, nonatomic, nonnull) NSArray<__kindof UIView *> *someViews;
實際上我們已經告訴編譯器:屬性及其集合會出現一些UIView。這樣在類型協議裡顯示更多我們之前看不到的信息。其本質向下轉型(downcasting)。
這意味着上述代碼編譯沒什麼問題,因為編譯器知道集合裡肯定會出現一個button。
現在那些擔憂就都解釋得清了。
雖然不喜歡Swift的人可能會刻意誇大Objective-C的優點,但如今兩種語言實現了互相調用,這是Objective-C所有提升的最大價值所在,我們應該心存感激。
毋庸置疑,Objective-C的确比以往更加強大。
對我來說,Objective-C是開發生涯中的初戀,相比其他語言,它是那麼與衆不同——直到今天都是如此,它的好、它的壞都讓我欲罷不能。雖然如今Swift正以迅雷不及掩耳之勢征服着我的心,我還是希望Objective-C陪伴在身邊。
Objective-C的提升能夠幫助開發者寫出更好的代碼,這是好事。而且這些優勢已經在Foundation中随處可見了。
(翻譯/張新慧 審校/唐小引)
文章來源: Medium
第一時間掌握最新移動開發相關信息和技術,請關注mobilehub公衆微信号(ID: mobilehub)。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!