OC進化簡述

Objective-C 最初起源于 NeXTSTEP 操作系統(tǒng),之后喬布斯回到蘋果,便將它在OS X和iOS中繼承了下來。
20世紀(jì)80年代初,Brad BoxTom LoveSmallTalk-80語言為基礎(chǔ)發(fā)明了Objective-CSmalltalk是歷史上第二個面向?qū)ο蟮某绦蛟O(shè)計語言,也就是說:Objective-C就是C語言面向?qū)ο骃mallTalk語法話的結(jié)果。
讓我們來看看早起SmallTalk的語法特點:

在 Smalltalk 中一切皆對象,一切調(diào)用都是發(fā)消息

比如下面的表達式:

2 + 3

它的意義是:向?qū)ο?code>2發(fā)送消息+,參數(shù)為對象3。
再比如用一個工廠方法來實例化一個對象:

p := Person name: 'Sai DiCaprio' age: 12

為Person類添加一個方法

greet: name  
  | message | 
  message := 'Hello ', name. 
  Transcript show: message.

在方法定義里,管道|包著的本地變量,然后是方法的實現(xiàn),把‘Hello’放到了變量message里,然后用逗號符把它和變量name連接起來。

p := Person new.
p greet: 'Jack'.

這時Transcript會輸出 Hello Jack。
從上可以看出,消息傳遞機制成了C語言進化為OC的最大障礙,要實現(xiàn)向一個target ( class / instance )發(fā)送消息名selector 動態(tài)尋找到函數(shù)實現(xiàn)地址IMP并調(diào)用,為了解決這一難題,需要提供一系列在Build Time無法實現(xiàn)的運行時函數(shù)支持,這些函數(shù)慢慢封裝完整,便出現(xiàn)了一套API:Runtime

早期的Objective-C = C + Preprocessor + Runtime

既然已經(jīng)形成了一套健全的面向?qū)ο蟮腃語言體系,那么我們來看看早期的Objective-C 代碼是如何書寫的

@interface Person{
  NSString *_name;
  int _age;
}
- (NSString *)name;
- (void)setName:(NSString *)name;

- (int)age;
- (void)setAge:(int)age;
@end

上面的代碼聲明了一個類Person,他有2個成員變量,并分別為其提供了setget方法。

秉著誰創(chuàng)建,誰釋放;誰引用,誰管理的MRC原則,在實現(xiàn)文件中便有了下面的代碼

@implementation Person
- (NSString *)name{
  return _name;
}
- (void)setName:(NSString *)name{
  if (_name != name){
    [_name release];
    _name = [name copy];
  }
  return _name;
}

- (int)age{
  return _age;
}
- (void)setAge:(int)age{
  _age = age;
}

@end

可以看到,僅僅創(chuàng)建了2個變量就為類帶來了這么大的代碼量,在成員變量多的情況下,通篇垃圾代碼,于是Objective-C 2.0馬上就出現(xiàn)了新的語法@property關(guān)鍵字
它用來讓編譯器自動幫我們生成成員變量和其對應(yīng)的get和set方法的聲明。
比如Person類的聲明中便化為這樣:

@interface Person
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;
@end

注意:這時的@property并不像現(xiàn)在一樣會幫我們自動生成成員變量的setter和getter方法的實現(xiàn)

在實現(xiàn)方面有另外一個關(guān)鍵字:@synthesize幫我們根據(jù)屬性修飾符自動合成settergetter的實現(xiàn)。

@implementation Person
@synthesize name = _name;
@synthesize age = _age;
@end

后來自動合成的@synthesize可以不用寫了,默認就是上面的代碼。這樣一來,整個類變得輕快了很多。
但是也會有這樣的需求:比如不希望系統(tǒng)幫我們自動實現(xiàn)settergetter,而由我們自己來實現(xiàn),便出現(xiàn)了@dynamic關(guān)鍵字,雖然編譯器會通過,但是如果在運行過程中方法調(diào)用了對應(yīng)的settergetter方法,但是發(fā)現(xiàn)沒有手動實現(xiàn)那么就會崩潰報unrecognized selector sent to instance 0x.......的錯誤。編譯時沒問題,運行時才執(zhí)行相應(yīng)的方法,這就是所謂的動態(tài)綁定。

總結(jié):

  • @synthesize 告訴編譯器幫我們合成屬性的getter和setter的實現(xiàn)
  • @dynamic 告訴編譯器不要幫我自動合成屬性,而由我們自己實現(xiàn)getter和setter的實現(xiàn)

既然現(xiàn)在的@property會幫我們自動合成autosynthesize那么@dynamic和synthesize如今還有什么意義呢?

回答這個問題前,我們要搞清楚一個問題,什么情況下不會autosynthesis(自動合成)?

  • 同時重寫了 setter 和 getter 時
  • 重寫了只讀屬性的 getter 時
  • 使用了 @dynamic 時
  • 在 @protocol 中定義的所有屬性
  • 在 category 中定義的所有屬性
  • 重載的屬性

當(dāng)同時重寫了setter和getter或者重寫了只讀屬性的getter時,系統(tǒng)就不會幫我們自動合成,就意味著ivar也不會被生成,所以,這種情況下有兩種方案:

  • 自己添加ivar
  • 使用@synthesize

也就是說,當(dāng)你想手動管理 @property 的所有內(nèi)容時,你就會嘗試通過實@property 的所有存取方法或者使用@dynamic來達到這個目的,這時編譯器就會認為你打算手動管理 @property,于是編譯器就禁用了自動合成。

另外,當(dāng)你在子類中重載了父類中的屬性,你必須 使用 @synthesize 來手動合成ivar。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 在這個信息無限發(fā)達的時代里,聯(lián)系一個人很容易,失去一個人,夜同樣容易。 你的生命里一定也出現(xiàn)過這樣的人,當(dāng)年你們是...
    十四條小魚閱讀 527評論 0 1
  • 摘錄自第四季《奇葩說》關(guān)于該不該把父母送到養(yǎng)老院?馬微微的闡述 你們覺得什么樣的人才會結(jié)婚生子,然...
    樓尚青閱讀 294評論 0 0
  • 今年春節(jié),我沒有讓自己沉浸在這種氣氛中,也許是脫離了這個慣性了吧,自己也會有點不適應(yīng),因為我可以不再受這些大...
    Sim2閱讀 289評論 2 0
  • 【出發(fā)】 A是一個對未來充滿想象,但對未知的生活又有些顧慮的女孩。大學(xué)畢業(yè)前,考取了在當(dāng)年是全國通過率10%的專業(yè)...
    熊小朱閱讀 330評論 3 0

友情鏈接更多精彩內(nèi)容