iOS開發(fā)閱讀 - Objective-C系列(目錄)
class 舱禽,struct與object
class是類,struct是結(jié)構(gòu)體。
什么是類?具有相同特性(數(shù)據(jù)元素)和行為(功能)的對象的抽象就是類下翎。類是一種抽象的數(shù)據(jù)類型,為所有的對象定義了抽象的屬性與行為宝当。類具有屬性,它是對象的狀態(tài)的抽象胆萧,用數(shù)據(jù)結(jié)構(gòu)來描述類的屬性庆揩。類具有操作,它是對象的行為的抽象跌穗,用操作名和實現(xiàn)該操作的方法來描述订晌。
什么是結(jié)構(gòu)體?由一系列具有相同類型或不同類型的數(shù)據(jù)構(gòu)成的數(shù)據(jù)集合蚌吸,叫做結(jié)構(gòu)锈拨。結(jié)構(gòu)被用來代表一個記錄,比如一本書羹唠,有標(biāo)題奕枢,作者娄昆, 主題,圖書ID缝彬,這就是一個結(jié)構(gòu)萌焰。
而在Objective-C中,類在Objective-C中是objc_class
結(jié)構(gòu)體指針谷浅。
typedef struct objc_class *Class;
在objc/runtime.h
中objc_class
結(jié)構(gòu)體的定義如下:
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE;
const charchar *name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
struct objc_cache *cache OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
isa
: 指向元類的objc_class
結(jié)構(gòu)體指針扒俯,iOS中的類也是對象,元類中儲存有類對象的類方法一疯;
superclass
: 指向父類的objc_class
結(jié)構(gòu)體指針撼玄,如果該類已經(jīng)是最頂層的根類(如NSObject
或NSProxy
)掌猛,則superclass
為NULL
磕蒲,可以通過父類的指針找到變量和方法留潦;
name
:類名;
version
:版本號辣往,默認(rèn)為0
info
:其他信息兔院,運行期間的一些位標(biāo)示
instance_size
:類實例變量大小
ivars
: 該類的成員變量鏈表,是objc_ivar_list
結(jié)構(gòu)體指針
struct objc_ivar_list {
int ivar_count;
/* variable length structure */
struct objc_ivar ivar_list[1];
}
objc_var
:變量結(jié)構(gòu)體---名稱站削,類型坊萝,偏移字節(jié)和占用的空間
struct objc_ivar {
charchar *ivar_name OBJC2_UNAVAILABLE;
charchar *ivar_type OBJC2_UNAVAILABLE;
int ivar_offset OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space OBJC2_UNAVAILABLE;
#endif
}
objc_method_list
: 方法鏈表結(jié)構(gòu)體
struct objc_method_list {
struct objc_method_list *obsolete OBJC2_UNAVAILABLE;
int method_count OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space OBJC2_UNAVAILABLE;
#endif
/* variable length structure */
struct objc_method method_list[1] OBJC2_UNAVAILABLE;
}
method
: 對象的每個方法的結(jié)構(gòu)體,SEL
是方法選擇器许起,是hash后的值园细,是一個字符串惦积,可以很快地通過這個值找到函數(shù)體的實現(xiàn),IMP
是函數(shù)指針
struct objc_method {
SEL method_name OBJC2_UNAVAILABLE;
charchar *method_types OBJC2_UNAVAILABLE;
IMP method_imp OBJC2_UNAVAILABLE;
}
cache
: 對象使用過的方法鏈表
struct objc_cache {
unsigned int mask /* total = mask + 1 */ OBJC2_UNAVAILABLE;
unsigned int occupied OBJC2_UNAVAILABLE;
Method buckets[1] OBJC2_UNAVAILABLE;
};
protocols
:協(xié)議鏈表
struct objc_protocol_list {
struct objc_protocol_list *next;
long count;
Protocol *list[1];
};
objc_class
的定義中猛频,在使用runtime以class為前綴的方法時狮崩,主要就是針對這個struct中的各個字段的。
isa指針
在OC中所有的類其實也是一個對象毡熏,那么這個對象也會有一個所屬的類坦敌,這個類就是元類也就是結(jié)構(gòu)體里面isa指針?biāo)傅念悺?元類的定義:元類就是類對象的類。每個類都有自己的元類,因為每個類都有自己獨一無二的方法狱窘。)
1.對象的isa指針指向所屬的類
2.類的isa指針指向了所屬的元類
3.元類的isa指向了根元類杜顺,根元類指向了自己。
有這樣一幅圖展示這樣一種關(guān)系:
成員變量(ivars)及屬性
在objc_class
中训柴,所有的成員變量哑舒、屬性的信息是放在鏈表ivars中的。ivars是一個數(shù)組幻馁,數(shù)組中每個元素是指向Ivar(變量信息)的指針洗鸵。runtime提供了豐富的函數(shù)來操作這一字段。大體上可以分為以下幾類:
1.成員變量操作函數(shù):
// 獲取類中指定名稱實例成員變量的信息
Ivar class_getInstanceVariable ( Class cls, const char *name );
// 獲取類成員變量的信息
Ivar class_getClassVariable ( Class cls, const char *name );
// 添加成員變量
BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char *types );
// 獲取整個成員變量列表
Ivar * class_copyIvarList ( Class cls, unsigned int *outCount );
Objective-C不支持往已存在的類中添加實例變量仗嗦,可以通過runtime
class_addIvar
函數(shù)來添加,只能在objc_allocateClassPair
與objc_registerClassPair
之間調(diào)用膘滨。
另外,這個類也不能是元類稀拐。成員變量的按字節(jié)最小對齊量是1<<alignment
火邓。這取決于ivar
的類型和機器的架構(gòu)。如果變量的類型是指針類型德撬,則傳遞log2(sizeof(pointer_type))
铲咨。
2.屬性操作函數(shù)
// 獲取指定的屬性
objc_property_t class_getProperty ( Class cls, const char *name );
// 獲取屬性列表
objc_property_t * class_copyPropertyList ( Class cls, unsigned int *outCount );
// 為類添加屬性
BOOL class_addProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );
// 替換類的屬性
void class_replaceProperty ( Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount );
methodLists方法
objc_method_list方法鏈表中存放的是該類的成員方法
// 添加方法
BOOL class_addMethod ( Class cls, SEL name, IMP imp, const char *types );
// 獲取實例方法
Method class_getInstanceMethod ( Class cls, SEL name );
// 獲取類方法
Method class_getClassMethod ( Class cls, SEL name );
// 獲取所有方法的數(shù)組
Method * class_copyMethodList ( Class cls, unsigned int *outCount );
// 替代方法的實現(xiàn)
IMP class_replaceMethod ( Class cls, SEL name, IMP imp, const char *types );
// 返回方法的具體實現(xiàn)
IMP class_getMethodImplementation ( Class cls, SEL name );
IMP class_getMethodImplementation_stret ( Class cls, SEL name );
// 類實例是否響應(yīng)指定的selector
BOOL class_respondsToSelector ( Class cls, SEL sel );
類與結(jié)構(gòu)體的主要區(qū)別是struct
是Value Type
,就是值類型, class
是Reference Type
蜓洪,是引用類型纤勒。(在swift里,要想用它的方法修改屬性數(shù)據(jù)隆檀,就必須在方法前面加上mutating
關(guān)鍵詞摇天。結(jié)構(gòu)體和枚舉都是值類型的,默認(rèn)情況下恐仑,值類型的屬性是不能從它的實例方法內(nèi)部改變的泉坐。如果想要在實例方法里面修改結(jié)構(gòu)體或者枚舉的屬性值的話,就需要使用mutating
關(guān)鍵詞特殊處理裳仆。帶有mutating
關(guān)鍵詞標(biāo)志的方法腕让,可以在方法內(nèi)部修改這些值,并且方法返回后還有效歧斟,class
沒有這個限制记某。)
對象是啥?
對象其實就是實例化的類构捡。
對象是一種結(jié)構(gòu),它包含值和指向其類的隱藏指針壳猜」椿眨“實例”是對象的另一種稱呼,例如统扳,Circle對象也可以稱呼為Circle類的實例喘帚。
編寫面向?qū)ο蟮某绦驎r畅姊,你所創(chuàng)建的類和對象之間存在一定的關(guān)系,它們協(xié)同工作才能實現(xiàn)程序的相應(yīng)功能吹由。
處理類和對象之間的關(guān)系若未,尤其要重視OOP的兩個方面。第一個方面是繼承倾鲫。創(chuàng)建一個新類時粗合,通常需要定義新類以區(qū)別于其他類及現(xiàn)有類。使用繼承可以定義一個具有父類所有功能的新類乌昔,它繼承了父類的這些功能隙疚。你也可以添加額外的方法以及重寫現(xiàn)有的方法來達(dá)到你所要實現(xiàn)的功能。
另一個和類有關(guān)的OOP技術(shù)是復(fù)合(composition)磕道。在復(fù)合中供屉,對象可以引用其他對象,可以利用其他對象提供的特性溺蕉,這就是復(fù)合伶丐。復(fù)合是通過包含作為實例變量的指針實現(xiàn)的。
嚴(yán)格的講疯特,只有對象間的組合才能叫做復(fù)合哗魂,諸如int、float辙芍、enum和struct等基本類型都被認(rèn)為是對象的一部分啡彬。
剛才是主要介紹了iOS的類,結(jié)構(gòu)體故硅,對象的關(guān)系庶灿。在實際應(yīng)用過程中,我們可能會對某個類增加方法或者變量吃衅。
這時我們就要知道分類Category
和Extension
往踢。