Objective—C語(yǔ)言的新魅力——Nullability声旺、泛型集合與類型延拓

本文原文轉(zhuǎn)自http://my.oschina.net/u/2340880/blog/514804

原 Objective—C語(yǔ)言的新魅力——Nullability尺锚、泛型集合與類型延拓

摘要相對(duì)于Java吼蚁,OC語(yǔ)言是一門古老的語(yǔ)言了贮缕,而它又是一門不斷發(fā)展完善的語(yǔ)言辙谜。一些新的編譯特性,為OC語(yǔ)言帶來(lái)了許多新的活力感昼。Objective—C語(yǔ)言的新魅力

一筷弦、引言? ? ? ?

?在Xcode7中,iOS9的SDK已經(jīng)全面兼容了Objective-C的一些新特性和新功能抑诸。這些功能都只作用于編譯期烂琴,對(duì)程序的運(yùn)行并沒(méi)有影響,因此蜕乡,它可以很好的向下進(jìn)行兼容奸绷,無(wú)縫的銜接低版本的iOS系統(tǒng),那么這些特性有什么樣的用處呢层玲,作為開(kāi)發(fā)者号醉,我保證你一定會(huì)愛(ài)上他們,如果你可以將這些新特性都應(yīng)用于你的開(kāi)發(fā)辛块,你的開(kāi)發(fā)效率和代碼質(zhì)量畔派,相比之前,會(huì)有一個(gè)很大的提升润绵。

二线椰、Nullability檢測(cè)的支持? ? ? ?

?在swift語(yǔ)言中,通過(guò)!和?可以將對(duì)象聲明成Optional尘盼,用于在開(kāi)發(fā)中標(biāo)記這個(gè)對(duì)象是否可以為空憨愉。在OC中烦绳,以前是沒(méi)有這樣的功能的,因此我們?cè)陂_(kāi)發(fā)中會(huì)經(jīng)常遇到因?yàn)槟硞€(gè)函數(shù)應(yīng)該返回實(shí)例而返回了空導(dǎo)致的崩潰配紫。Nullability的主要用武之地径密,就是在這里,它可以起到提示開(kāi)發(fā)者做是否為空得判斷的提示躺孝。? ? ? ?

?打開(kāi)Xcode7享扔,系統(tǒng)的框架中已經(jīng)支持了Nullability,如下:

@property (nullable, nonatomic, readonly) ObjectType firstObject;

@property (nullable, nonatomic, readonly) ObjectType lastObject;

這是NSArray中的兩個(gè)屬性植袍,其中nullable關(guān)鍵字說(shuō)明了這里可能返回空的值惧眠。

如果僅僅是在返回值中給開(kāi)發(fā)者一些提示,你可能覺(jué)得應(yīng)用并不大奋单,是的,對(duì)開(kāi)發(fā)者最大的幫助是這一特性可以用于函數(shù)的參數(shù)中猫十,這樣我們?cè)谡{(diào)用函數(shù)時(shí)起到的提示作用览濒,將是非常重要的,越是多人合作的項(xiàng)目拖云,作用也越大贷笛。

例如:

-(void)setValue:(NSNumber * _Nonnull )number{? ?

?}

我們?cè)谡{(diào)用函數(shù)時(shí),如果傳入了空值宙项,編譯器會(huì)給我們警告:

注意:這一特性在Xcode6.3中就已經(jīng)支持乏苦,但在Xcode7中又做了一些寫(xiě)法上的小改動(dòng),例如尤筐,在Xcode6.3中這樣寫(xiě):

-(void)setValue:( nonnull NSNumber *? )number{? ?

?}

而在Xcode7中提倡我們使用第一種寫(xiě)法汇荐。

與之相關(guān)的幾個(gè)關(guān)鍵字如下:

修飾參數(shù)nonnull:不可為空

nullable: 可以為空

null_unspecified:不確定是否可以為空(極少情況)

在屬性的聲明中,還會(huì)有如下一個(gè)修飾符:

null_resettable:set方法可以為nil盆繁,get方法不可返回nil

一點(diǎn)提示:你可以發(fā)現(xiàn)掀淘,iOS9的SDK中已經(jīng)完全兼容使用了這些特性,并且nonnull的使用會(huì)比nullable廣泛的多油昂,因此革娄,系統(tǒng)提供了這樣一對(duì)宏:

#define NS_ASSUME_NONNULL_BEGIN _Pragma("clang assume_nonnull begin")

#define NS_ASSUME_NONNULL_END? _Pragma("clang assume_nonnull end")

我們?cè)谶@對(duì)宏之間定義的變量都會(huì)加上nonnull的修飾符,只有我們特殊聲明nullable的才需要手動(dòng)寫(xiě)冕碟。

三拦惋、泛型集合的支持? ? ? ?

?這一特性和Nullability一樣,只作用于編譯期安寺,是為我們開(kāi)發(fā)者服務(wù)的另一重要特性厕妖。還記得,在Xcode7之前挑庶,依然是為了方便多人開(kāi)發(fā)叹放,我經(jīng)常會(huì)在框架中寫(xiě)這樣的一個(gè)空得宏:

在開(kāi)發(fā)時(shí)如下使用饰恕,做到提示伙伴我這個(gè)數(shù)組中是什么東西的作用:

@interface ViewController (){ ? ?

??? NSArray __TYPE__FIT_TO__CLASS(NSString) *? array;

}

@end

當(dāng)然,所有這些都是我自己的自導(dǎo)自演井仰,編譯器并不會(huì)鳥(niǎo)我埋嵌,我在這個(gè)數(shù)組中加其他的東西,它也不會(huì)介意俱恶,所有這些只是我和我的伙伴們約定的一種一廂情愿雹嗦。所以,當(dāng)我看到Xcode7中的集合類型時(shí)合是,我著實(shí)興奮了一下了罪。

1、有類型約定的集合? ? ? ?

?在Xcode7中聪全,我們可以給集合類型添加一個(gè)泛型的約定泊藕,如下: NSMutableArray*array = [[NSMutableArray alloc]init];聲明了這樣一個(gè)數(shù)組后,就好比我告訴了編譯器难礼,這個(gè)數(shù)組中的數(shù)據(jù)類型都是NSString*類型的娃圆,現(xiàn)在非常好,如果我這個(gè)數(shù)組中元素的方法蛾茉,會(huì)出現(xiàn)如下的提示:激動(dòng)吧讼呢,使用點(diǎn)語(yǔ)法可以訪問(wèn)到數(shù)組中泛型的方法了,還有更加誘人的:在我們向這個(gè)數(shù)組中追加元素的時(shí)候谦炬,編譯器將元素的類型提示了出來(lái)悦屏,并且將FromArray方法中需要的元素類型也提示了出來(lái)。同樣键思,如果我們向這個(gè)數(shù)組中追加類型不匹配的元素础爬,如下:? ??

NSMutableArray*array = [[NSMutableArray alloc]init];? ?

?[array addObject:@1];

編譯器會(huì)給我們一個(gè)這樣的警告:

2、關(guān)于一個(gè)類型通配符? ? ? ??

觀察Xcode7中iOS系統(tǒng)的類吼鳞,我們可以發(fā)現(xiàn)這么一個(gè)好玩的東西:ObjectType幕帆。它既不是一個(gè)類型,也不是關(guān)鍵字赖条,然而卻大量存在失乾,如下是系統(tǒng)的NSMutableArray的頭文件:

@interface NSMutableArray: NSArray

- (void)addObject:(ObjectType)anObject;

- (void)insertObject:(ObjectType)anObject atIndex:(NSUInteger)index;

- (void)removeLastObject;

- (void)removeObjectAtIndex:(NSUInteger)index;

- (void)replaceObjectAtIndex:(NSUInteger)index withObject:(ObjectType)anObject;

- (instancetype)init NS_DESIGNATED_INITIALIZER;

- (instancetype)initWithCapacity:(NSUInteger)numItems NS_DESIGNATED_INITIALIZER;

- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;

@end

這個(gè)ObjectType其實(shí)只是一個(gè)類型標(biāo)識(shí)符,它具體怎么寫(xiě)并不重要纬乍,只是系統(tǒng)中都約定使用了ObjectType碱茁,你也可以在自己的類中按自己的喜好來(lái)命名,這個(gè)東西有怎樣的用處仿贬,我用文字描述不清楚纽竣,我們可以通過(guò)自己來(lái)定義一個(gè)集合類來(lái)理解:創(chuàng)建一個(gè)類,繼承于NSObject,我取名叫MyArray://這個(gè)類型通配符只能在interfave里使用蜓氨,作用域?yàn)锧interface到@end之間//這里我使用Type來(lái)做這個(gè)通配符

@interface MyArray: NSObject

@property(nonatomic,strong,nonnull)NSMutableArray*array;

-(void)addObject:(nonnull Type)obj;

@end

實(shí)現(xiàn)如下:

- (instancetype)init{ ??

??? self = [super init];? ?

???? if (self) {? ? ??

????????? _array = [[NSMutableArray alloc]init];??

????? }? ?

???? return self;}

-(void)addObject:(id)obj{? ?

? ?? [_array addObject:obj];

}

-(NSString *)description{??

????? NSMutableString * str = [[NSMutableString alloc]init];? ?

???? for (int i=0; i<_array.count; i++) {? ? ??

????????? [str appendString:[NSString stringWithFormat:@"%@\n",_array[i]]];? ?

?}? ?

???? return str;

}

我們?cè)谑褂眠@個(gè)自定義的集合類型時(shí)聋袋,就會(huì)有和系統(tǒng)一樣的效果了:

3、關(guān)于多參數(shù)的泛型集合? ? ? ?

?多參數(shù)的泛型集合穴吹,有一個(gè)非常好的例子幽勒,就是NSDictionary,在Xcode7中我們可以這樣寫(xiě)字典:可以看到港令,字典鍵值的類型編譯器為我們提示了出來(lái)啥容,結(jié)合上面類型通配符的使用,對(duì)于多參的集合顷霹,將參數(shù)類型用“,”隔開(kāi)即可咪惠。

4、協(xié)變性與逆變性? ? ? ??

因?yàn)橛辛朔盒图系母拍盍艿恚啾戎耙C粒覀兊念愋蛯?shí)際上更加復(fù)雜了,比如還拿我們自定義的集合類型來(lái)舉例:? ??

MyArray* array;? ? MyArray*muArray;array和muArray在編譯器看來(lái)已經(jīng)是不同的類型朵纷,如果我們強(qiáng)行轉(zhuǎn)換炭臭,會(huì)報(bào)如下的警告:

因此,就有了逆變和協(xié)變這個(gè)概念:

__covariant :子類型指針可以向父類型指針轉(zhuǎn):

__contravariant:父類型指針可以向子類型轉(zhuǎn)換上面的情況柴罐,我們將自定義的類做如下修改徽缚,就不會(huì)出現(xiàn)警告:

@interface MyArray<__covariant Type> : NSObject

@property(nonatomic,strong,nonnull)NSMutableArray*array;

-(void)addObject:(nonnull Type)obj;

@end

四憨奸、類型延拓符的應(yīng)用? ? ? ??

在開(kāi)發(fā)中革屠,開(kāi)發(fā)者經(jīng)常會(huì)遇到這樣的情況,例如通過(guò)tag獲取某些UI控件時(shí)排宰,viewWithTag方法通常會(huì)返回給我們一個(gè)UIView類型的指針似芝,這就需要開(kāi)發(fā)者手動(dòng)的強(qiáng)轉(zhuǎn)一下,十分麻煩板甘。新增加的__kindof修飾符可以幫助我們解除這個(gè)煩惱党瓮。我們還從自定義的那個(gè)數(shù)組類開(kāi)刀,對(duì)其添加一個(gè)屬性:

@interface MyArray<__covariant Type> : NSObject@property(nonatomic,strong,nonnull)NSMutableArray*array;

@property(nonnull,strong,nonatomic)NSMutableArray* viewArray;

-(void)addObject:(nonnull Type)obj;

@end

創(chuàng)建一個(gè)自定義的數(shù)組對(duì)象盐类,并向其中添加一個(gè)UIButton寞奸,我們會(huì)看到有如下一個(gè)警告:

這也是我們開(kāi)發(fā)中常遇到的問(wèn)題,對(duì)吧在跳,以前需要強(qiáng)轉(zhuǎn)枪萄。但是以后就不需要了,我們?cè)诼暶鬟@個(gè)數(shù)組時(shí)加上一個(gè)__kindof修飾符:

@property(nonnull,strong,nonatomic)NSMutableArray<__kindof UIView *> * viewArray;

警告就消失了猫妙,很cool吧瓷翻。

這個(gè)修飾符就是告訴編譯器,這里可以返回UIView的子類指針。

五齐帚、結(jié)語(yǔ)

雖然這些優(yōu)點(diǎn)在swift中早有體現(xiàn)妒牙,但就我個(gè)人而言,我對(duì)OC的感情會(huì)更深一些对妄,也更加愿意接受OC的改變和成長(zhǎng)湘今,大家都說(shuō)swift的趨勢(shì)勢(shì)在必行,我只想說(shuō)饥伊,swift很優(yōu)秀象浑,OC亦然。

? 著作權(quán)歸作者所有

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末琅豆,一起剝皮案震驚了整個(gè)濱河市愉豺,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌茫因,老刑警劉巖蚪拦,帶你破解...
    沈念sama閱讀 216,997評(píng)論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異冻押,居然都是意外死亡驰贷,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門洛巢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)括袒,“玉大人,你說(shuō)我怎么就攤上這事稿茉∏旅蹋” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,359評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵漓库,是天一觀的道長(zhǎng)恃慧。 經(jīng)常有香客問(wèn)我,道長(zhǎng)渺蒿,這世上最難降的妖魔是什么痢士? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,309評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮茂装,結(jié)果婚禮上怠蹂,老公的妹妹穿的比我還像新娘。我一直安慰自己少态,他們只是感情好城侧,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,346評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著况增,像睡著了一般赞庶。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,258評(píng)論 1 300
  • 那天歧强,我揣著相機(jī)與錄音澜薄,去河邊找鬼。 笑死摊册,一個(gè)胖子當(dāng)著我的面吹牛肤京,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播茅特,決...
    沈念sama閱讀 40,122評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼忘分,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了白修?” 一聲冷哼從身側(cè)響起妒峦,我...
    開(kāi)封第一講書(shū)人閱讀 38,970評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎兵睛,沒(méi)想到半個(gè)月后肯骇,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,403評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡祖很,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,596評(píng)論 3 334
  • 正文 我和宋清朗相戀三年笛丙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片假颇。...
    茶點(diǎn)故事閱讀 39,769評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡胚鸯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出笨鸡,到底是詐尸還是另有隱情姜钳,我是刑警寧澤,帶...
    沈念sama閱讀 35,464評(píng)論 5 344
  • 正文 年R本政府宣布镜豹,位于F島的核電站傲须,受9級(jí)特大地震影響蓝牲,放射性物質(zhì)發(fā)生泄漏趟脂。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,075評(píng)論 3 327
  • 文/蒙蒙 一例衍、第九天 我趴在偏房一處隱蔽的房頂上張望昔期。 院中可真熱鬧,春花似錦佛玄、人聲如沸硼一。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,705評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)般贼。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間哼蛆,已是汗流浹背蕊梧。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,848評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留腮介,地道東北人肥矢。 一個(gè)月前我還...
    沈念sama閱讀 47,831評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像叠洗,于是被迫代替她去往敵國(guó)和親甘改。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,678評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容