objective-c 關鍵字和概念 - ithero_zhou的專欄 - 博客頻道 - CSDN.NET c++
關鍵字
@
看到這個關鍵字,咱們就應該想到,這是Object-C對C語言的擴展,例如
@interface XXX。
聲明類
@implementation
實現類
聲明協議
@optional
與@protocol配合使用,說明協議中的某個或者某幾個方法能夠不實現
@required
與@protocol配合使用,說明協議中的某個方法或者某幾個方法必須實現
與
@interface ,@implementation,@protocol配合使用,表明聲明或者實現結束
@encode爲編譯器宏,它能夠將類型轉換爲相應的字符串。
id
id是指向Objective-C類對象的指針,它能夠聲明爲任何類對象的指針,當在Objective-C中使用id時,編譯器會假定你知道,id指向哪一個類的對象。與void*是不一樣的是,void*編譯器不知道也不假定指向任何類型的指針。 objective-c
nil
定義爲一個常量,若是一個指針的值爲nil,表明這個指針沒有指向任何對象。
self
在Objective-C中,關鍵字self與c++中this是同一律念,就是類對象自身的地址,經過self能夠調用本身的實例變量和方法 多線程
Super
當子類須要調用父類的方法時,會用到Super關鍵字. Super指向的是父類的指針,子類重寫父類的方法時,調用父類的方法是一個比較好的習慣。由於當咱們不知道父類在該方法中實現的功能時,若是不調用父類的方法,有可能咱們重寫的方法會失去該功能,這是咱們不肯意看到的狀況。
NSNull
NSNull是沒有的意思,若是一個字典的值爲NSNull,那說明與該值對應的Key是沒有值的,例如Key爲address,說明與address對應的是值是沒有。 app
self super class public protected private id 框架
[self class] [super class] selector 函數
objective-c runtime reference ui
標準用法 this
self = [super init] 編碼
new
1 Objective-C有一個特性,就是能夠把類當成對象來發送消息,這種用法一般用於新建對像時,例如 XXX *object = [XXX new];
類方法 +
若是想聲明屬於類而不屬於類對象的方法,用+。+用來修飾類的方法,使用+修飾的類方法,是整個類的方法,不屬於哪個類對象,這與C++中的static在類中使用的概念同樣,
%@
在NSLog中,使用%@表示要調用對象的description方法。
概念
類
是一種結構,它表示對象的類型,就像int與 char 同樣,也能夠聲明類的變量(對像)
實例化
爲類的對象分配內存和初始化,達到可使用該 類對象的目的。
對象(實例)
類的實例化後的產物
消息
在Object-C中,類的對象執行的操做,是經過給該類或者該類對象發送消息實現,如:[object func];就是給object對象發送func消息,相似C++中的方法調用。給object對象發送func消息後,object對象查詢所屬類的func方法執行。 atom
方法調度
當向一個對象發送消息時(調用方法),這個方法是怎麼被調用的呢?這就依賴於方法高度程序,方法調度程序查找的方法以下:
在本類的方法中,找被調用的方法,若是找到了,就調用,若是找不到被沿着繼承路徑去查找,從哪一個類找到,就調用哪一個類的方法,若是到最根上的類仍是沒有找到,那編譯就會出錯。
繼承與複合
在Objective-C中支持繼承,但只是支持單一繼承(有且只有一個父類有),若是想使用多繼承的特性,可使用分類和協議技術。
繼承是is-a,複合是has-a。複合是經過包含指向對象的指針實現的,嚴格意義上講,複合是針對於對象間來講,對於基本數據類型來講,它們被認爲是對象的一部分。
裝箱與拆箱
因爲NSArray,NSDirectory等類不能直接存儲基本數據類型,因此要想在NSArray\NSDirectory中使用基本數據類型,就得使用裝箱與拆箱。
在Objective-C中,可使用NSNumber和NSValue來實現對數據類型的包裝,NSNumber能夠實現對基本數據類型的包裝,NSValue能夠實現對任意類型數據的包裝。
將基本類型封裝成對象叫裝箱,從封裝的對象中提取基本類型叫拆箱(取消裝箱),其它語言如Java原生支持裝箱與拆箱,Ojbective-C不支持自動裝箱與拆箱,若是須要得須要本身來實現裝箱與拆箱。
存取方法
在使用類對象的實例變量(成員數據)時,不要直接使用對象中的實例,要使用存以方法來獲取或者修改實例,既setter和getter,在Cocoa中,存取方法有命名習慣,咱們得符合這種習慣,以便於與其它團隊成員合做。setter方法是修改或者設置實例值,命名習慣爲set+實例名,例有一個類有path實例變量,那setter命名爲setPath,getter命名爲Path,爲何不是getPath,由於get在Cocoa中有特殊的含義,這個含義就是帶有get的方法就意味着這個方法經過形參指針(傳入函數的參數指針)來返回值。咱們要遵照這個命名習慣或者說規則。
在Objective-C 2.0中加入了@property和@synthesize來代替setter和getter,這兩個關鍵字爲編譯器指令。 還有點表達式,存取類成員的值時,可使用點表達式。
Object.attribute,當點表達式在=號左邊時,調用的是setter方法,在=號右邊時,調用的是getter方法。
@property 語法爲:@property (參數) 類型 變量名.
在這裏主要說明一下參數.
參數分爲三種:
第一種:讀寫屬性包括(readonly/readwrite/)
第二種:setter屬性(assign,copy,retain),assign是簡單的賦值,copy是釋放舊成員變量,並新分配內存地址給成員變量,將傳入參數內容複製一份,給成員變量。retain是將傳 入
參數引用計數加1,而後將原有的成員變量釋放,在將成員變量指向該傳入參數。
第三種:與多線程有關(atomic,nonatomic).當使用多線程時,使用atomic,在不使用多線程時使用nonatomic
對象建立與初始化
在Objective-C中建立對象有兩種方法,一種是[類 new];另外一種是[[類 alloc] init],這兩種方法是等價的,但按慣例來說,使用[[類 alloc] init];
alloc操做是爲對象分配內存空間,並將對象的數據成員都初始,int 爲0,BOOL 爲NO, float 爲0.0等。
初始化,默認的初始化函數爲init,init返回值爲id,爲何回返回id呢,由於要實現鏈式表達式,在Objective-C中叫嵌套調用。
爲何要嵌套調用??由於初始化方法init返回值可能與alloc返回的對象不是同一個?爲何會發生這種狀況?基於類簇的初始化,由於init能夠接受參數,在init內部有可能根據不一樣的參數來返回不一樣種類型的對象,因此最會發生上面說的狀況。
在初始化時,建議使用if (self = [super init])
便利初始化
當一個類須要根據不一樣的狀況來初始化數據成員時,就須要便利初始化函數,與init初始化不一樣的是,便利初始化函數有參數,參數個數能夠有1到N個,N是類數據成員個數。
指定初始化函數:什麼是指定初始化函數?在類中,某個初始化函數會被指定爲指定的初始化函數, 肯定指定初始化函數的規則是初始化函數中,參數最多的爲指定初始化函數,
其它未被指定爲指定初始化函數的初始化函數要調用指定初始化函數來實現。對於該類的子類也是同樣,只要重寫或者直接使用父類的指定初始化函數。上述文字有些繞,來個例子吧
int x;
int y;
}
-(id) init;
-(id) initWithX:(int) xValue;
-(id) initWithY:(int) yValue;
-(id) initWithXY:(int) xValue
yVal:(int) yValue;
這裏initWithXY被肯定爲指定初始化函數。
-(id) initWithXY:(int) xValue
yVal:(int) yValue{
if (self = [super init]){
x = xValue;
y = yValue;
}
return self;
}
-(id) init{
if (self = self initWithXY:10
yVal:20){
}
return self;
}
.......
int z;
}
-(jd) initWithXY......;
@implementation B
-(id) initWithXY:(int) xValue
yVal:(int) yValue{
if (self = [super initWithXY:10
yVal=20]){
z= 40;
}
return self;
}
自動釋放池
內存管理是軟件代碼中的重中之重,內存管理的好壞,直接影響着軟件的穩定性。在Cocoa中,有自動釋放池,這相似於C++中的智能指針。
NSObject有一個方法是autorelease,當一個對象調用這個方法時,就會將這個對象放入到自動釋放池中。
drain,該方法是清空自動釋放池,不是銷燬它。drain方法只適用於Mac OS X 10.4以上的版本,在咱們寫的代碼中要使用release,release適用於全部版本。
自動釋放池是以 棧的方式實現,當建立一個自動釋放池A時,A被壓入棧頂,這時將接入autorelease消息的對象放入A自動釋放池,這時建立一個新的B自動釋放池,B被壓入棧頂,建立完成後刪除B,這個接收autorelease消息的對象依然存在,由於A自動釋放池依然存在。
引用計數
每一個對象都有一個與之相應的整數,稱它爲引用計數,當該 引用計數爲0時,Objective-C自動向該對象發送dealloc,以銷燬該對向,與該引用計數相關的方法(消息)有下面幾個
1 增長引用計數:經過alloc,new,copy建立一個對象時,該對象的引用計數加1(其實就是1,由於以前爲0)
2 增長引用計數: retain
3 減小引用計數: release
局部分配內存(臨時對象):
1 若是使用alloc,new,copy建立對象,則須要主動調用對象的release方法
2 若是使用非alloc,new,copy建立對象,咱們認爲該 對象引用計數爲1,並已經加入了自動釋放池,咱們不須要主動的調用對象的release方法。
擁有對象(在類中以成員的方法存在):
1 若是使用alloc,new,copy建立對象,則須要在dealloc方法中,釋放該對象
2 若是使用非alloc,new,copy建立對象,則在擁有該對象時,保留該對象(執行retain方法),在dealloc方法中,釋放該對象。
dealloc
當對象的引用計數爲0時,Objective-C會自動發送對象的dealloc消息(自動調用對象的dealloc方法,相似於C++的析構函數),因此咱們能夠本身重寫dealloc方法,來實現類裏的對其它使用資源的釋放工做。
注意:不要直接在代碼中顯示調用dealloc方法。
垃圾回收
在Objective-C 2.0中引入了垃圾回收機制(自動管理內存),在工程設置裏設置Objective-C Garbage Collection爲Required[-fobjc-gc-only]就可使用垃圾回收機制。
啓用垃圾回收機制後,一般的內存管理命令都變成了空操做指令,不執行任何操做。
Objective-C的垃圾回收機制是一種繼承性的垃圾回收器,垃圾回收器按期檢查變量和對象以及他們之間的指針,當發現沒有任何變量指向對象時,就將該對象視爲被丟棄的垃圾。因此在不在使用一個對象時,將指針他的指針設置爲nil,這時垃圾回收器就會清理該對象。
注意:若是開發iPhone軟件,則不能使用垃圾回收。在編寫iPhone軟件時,Apple公司建議不要在本身的代碼中使用autorelease方法,而且不要使用建立自動釋放對象的函數。
類別
什麼是類別?類別是一種爲現有類添加新方法的方式。
爲何使用類別或者說使用類別的目的是什麼?有如下三點:
第一,能夠將類的實現分散到多個不一樣的文件或多個不一樣的框架中。
若是一個類須要實現不少個方法,咱們能夠將方法分類,把分好的類造成類別,能夠有效的管理和駕馭代碼。
第二,建立對私有方法的前向引用。
第三,向對象添加非正式協議。
委託
委託的意思就是你本身想作某事,你本身不作,你委託給別人作。
在Ojbective-C中,實現委託是經過類別(或非正式協議)或者協議來實現。
舉個例子:Apple要生產iPhone,Apple本身不生產(種種緣由,其中之一就是在中國生產成本低,他們賺的銀子多),Apple委託富士康來生產,原本富士康原來不生產iPhone,如今要生產了,因此他得本身加一個生產iPhone的生產線(類別,增長生產iPhone方法),這就是經過類別來實現委託。下面用代碼來講明這個例子。
.....
Apple *apple = [[Apple alloc ] init];
Foxconn *fox = [[Foxconn alloc] init];
[apple setDelegate:fox];
[apple produceIPhone];
........
@implementation Apple
-(...) setDelegate:(id) x{
delegate = x; //! 將委託的生產對象指定爲x
}
-(...) produceIPhone{
[delegate produceIPhone]; //! 委託對象生產iPhone
}
...
@interface NSObject(ProduceIPhone) //! Foxconn以前就能夠生產其它產品,有過聲明和定義
-(...) produceIPhone //! 增長生產iPhone能力
@implementation NSObject(ProduceIPhone)
//! 生產iPhone
-(...) produceIPhone{
......
}
非正式協議
建立一個NSObject的類別, 稱爲建立一個非正式協議。爲何叫非正式協議呢?
也就是說能夠實現,也能夠不實現被委託的任務。
拿上面的例子來講,Apple要求Foxconn除了能生產iPhone外,還有一個要求是在必定時間內完成.因爲雙方沒有籤合同,因此時間要求和生產要求規格都是非正式協議
選擇器
選擇器就是一個方法的名稱。選擇器是在Objective-C運行時使用的編碼方式,以實現快速查找。可使用@selector預編譯指令,獲取選擇器@selector(方法名)。NSObject提供了一個方法respondsToSelector:的方法,來訪問對象是否有該方法(響應該消息)。
拿上面的Apple請Foxconn生產iPhone爲例,Apple怎麼知道Foxconn有沒有生產iPhone的能力呢?Apple就經過respondsToSelector方法詢問Foxconn,是否能夠生產iPhone(是否能夠響應produceIPhone),詢問結果是能夠,那Apple就委託Foxconn生產,Foxconn就生產出來了人們比較喜歡的iPhone產品。
正式協議
與非正式協議比較而言,在Ojbective-C中,正式協議規定的全部方法必須實現。在Ojbective-C2.0中,Apple又增長了兩個關鍵字,協議中的方法也能夠不徹底實現,是哪一個關鍵字見關鍵字部份的@optional,@required。
正式協議聲明以下:
-(...) func1;
-(...) func2;
使用協議:
@interface Object : NSObject<XXX> //! Object從NSObject派生,並遵循XXX協議,要實現func1,func2函數。
...
習慣用法
分配內存和初始化
self = [super init];
對象間交互
在Objective-C中,全部對象間的交互都是經過指針實現。
快速枚舉
for (Type *p in array)
注意:
Objective-C不支持多繼承