OC&Swift runtime 一 Classes

在Swift 4中繼承 NSObject 的 swift class 不再默認全部 bridge 到 OC盹兢,如果我們想要使用的話我們就需要在class前面加上@objcMembers 這么一個關(guān)鍵字。

方法一:class_getName
Discussion:獲取類的名字
在這之前先看在NSObject里的兩個方法聲明

- (Class)class OBJC_SWIFT_UNAVAILABLE("use 'type(of: anObject)' instead");
+ (Class)class OBJC_SWIFT_UNAVAILABLE("use 'aClass.self' instead");

實例方法獲取class
type(of: object) = [object class];
類方法獲取class
Class.self = [Class class];
OC

const char * class_getName(Class cls);
NSLog(@"%s", class_getName([self class]));
NSLog(@"%s", class_getName([ViewController class]));

Swift

public func class_getName(_ cls: Swift.AnyClass?) -> UnsafePointer<Int8>
print("\(String(cString: class_getName(type(of: self))))")
print("\(String(cString: class_getName(ViewController.self)))")

注意在Swift里返回的是UnsafePointer<Int8>類型,但是我們想要的是字符串。所以用String(cString: UnsafePointer<UInt8>)。把UnsafePointer<Int8>轉(zhuǎn)成String類型。

方法二:class_getSuperclass
Discussion:獲取類的父類
OC

Class class_getSuperclass(Class cls);
NSLog(@"%@", class_getSuperclass([self class]));
NSLog(@"%@", class_getSuperclass([ViewController class]));

Swift

func class_getSuperclass(_ cls: AnyClass?) -> AnyClass?
print("\(class_getSuperclass(type(of: self)))")
print("\(class_getSuperclass(ViewController.self))")

同時還可以獲取object的父類恶导,但是在NSObject的類里有一個superclass方法。(最簡單的方法調(diào)用不寫例子了)

方法三:class_isMetaClass
Discussion:判斷是不是metaclass
OC

BOOL class_isMetaClass(Class cls);
NSLog(@"%d", class_isMetaClass(nil));

Swift

func class_isMetaClass(_ cls: AnyClass?) -> Bool
print("\(class_isMetaClass(nil))")

這個方法可以用nil浸须。雖然OC方法的聲明里沒有寫惨寿。nil在OC里是指向空對象的指針。

方法四:class_getInstanceSize
Discussion:返回類對象的大小
OC

size_t class_getInstanceSize(Class cls);
size_t size = class_getInstanceSize([ViewController class]);

size_t是標準C庫中定義的删窒,應(yīng)為unsigned int裂垦,在64位系統(tǒng)中為 long unsigned int。一個是4字節(jié)一個是8字節(jié)肌索。返回的是size_t類型蕉拢。也就是說系統(tǒng)不同返回的可能也不同。
Swift

func class_getInstanceSize(_ cls: AnyClass?) -> Int
print("\(class_getInstanceSize(type(of: string)))")

方法五: class_getInstanceVariable
Discussion:返回一個指定的Ivar給定類的實例變量诚亚。
OC

Ivar class_getInstanceVariable(Class cls, const char *name);
NSLog(@"666%s", ivar_getName(class_getInstanceVariable(classType, "XXX")));

Swift

func class_getInstanceVariable(_ cls: AnyClass?, _ name: UnsafePointer<Int8>) -> Ivar?
print("\(String(cString: ivar_getName(class_getInstanceVariable(classType, "XXX")!)!))")

這里的classType是我自己通過objc_allocateClassPair創(chuàng)建的類晕换,然后class_addIvar添加的實例變量。

方法六: class_getClassVariable
Discussion:返回一個指定的Ivar給定類的類變量站宗。
class_getClassVariable(cls, name) merely calls class_getInstanceVariable(cls->isa, name)這是一個國外大佬寫的闸准。就是說class的isa里的Ivar。class的isa是metaclass,object的isa是class份乒。metaclass的Ivar就是isa了
OC

Ivar class_getClassVariable(Class cls, const char *name);
NSLog(@"777%s", ivar_getName(class_getClassVariable([self class], "isa")));

Swift

func class_getClassVariable(_ cls: AnyClass?, _ name: UnsafePointer<Int8>) -> Ivar?
print("\(String(cString: ivar_getName(class_getClassVariable(ViewController.self, "isa")!)!))")

方法七: class_addIvar
Discussion:給一個類添加一個新的實例變量恕汇。
這個方法要使用在objc_allocateClassPair之后和objc_registerClassPair之前。說人話就是要寫在這兩個方法之間或辖。(蘋果沒有用between)。而且這個類不能是元類枣接。對已存在的類不能使用颂暇。
第4個參數(shù)alignment。內(nèi)存對齊但惶。這個東西大家有興趣可以自己查耳鸯。東西太多就不寫了湿蛔。第五個參數(shù)types。是@encode碼表里的县爬。
OC

BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment, const char *types);
class_addIvar(DXArrayClass, "XXX", sizeof(NSString *), log2(sizeof(NSString *)), "@");
class_addIvar(DXArrayClass, "age", sizeof(int), log2(sizeof(int)), "i");

Swift

func class_addIvar(_ cls: AnyClass?, _ name: UnsafePointer<Int8>, _ size: Int, _ alignment: UInt8, _ types: UnsafePointer<Int8>?) -> Bool
class_addIvar(classType!, "XXX", MemoryLayout.size(ofValue: NSString.init()), UInt8(log2(Float.init(MemoryLayout.size(ofValue: NSString.init())))), "@")
class_addIvar(classType!, "age", MemoryLayout.size(ofValue: Int32()), UInt8(log2(Float.init(MemoryLayout.size(ofValue: NSString.init())))), "i")

這里我對swift的處理可能不太好阳啥。求指教。
方法八: class_copyIvarList
Discussion:獲取一個類的實例變量數(shù)組
OC

Ivar  _Nonnull * class_copyIvarList(Class cls, unsigned int *outCount);
unsigned int i;
Ivar *array = class_copyIvarList(DXArrayClass, &i);
for (int temp = 0; temp < i; array++, temp++) {
      Ivar ivar = *array;
      NSLog(@"%s", ivar_getName(ivar));
      NSLog(@"%s", ivar_getTypeEncoding(ivar));
}

Swift

func class_copyIvarList(_ cls: AnyClass?, _ outCount: UnsafeMutablePointer<UInt32>?) -> UnsafeMutablePointer<Ivar>?
var i : UInt32 = 0
var array = class_copyIvarList(classType, &i)
var temp = 0
while temp < i {
    temp += 1
    print("\(String(cString: ivar_getName((array?.pointee)!)!))")
    array = array?.successor()
}

方法九: class_getIvarLayout
Discussion:返回一個類的ivar描述财喳,關(guān)于是否是strong類型的
OC

const uint8_t * class_getIvarLayout(Class cls);
const uint8_t * layoutArray = class_getIvarLayout([self class]);
int j = 0;
uint8_t value_w = layoutArray[j];
while (value_w != 0x0) {
     printf("\\x%02x\n", value_w);
     value_w = layoutArray[++j];
}

看一下打印出來的數(shù)據(jù)察迟。第一位是非strong的個數(shù)第二位是strong的個數(shù)。

\x01
\x11
\x32
\x12
\x22

翻譯過來就是耳高。非strong strong 非strong strong 非strong 非strong 非strong strong strong 非strong strong strong 非strong 非strong strong strong扎瓶。
Swift

func class_getIvarLayout(_ cls: AnyClass?) -> UnsafePointer<UInt8>?
let point = class_getIvarLayout(ViewController.self)
if ((point?.successor()) != nil) {
     print("\(String.init(cString: point!))")
}

Swift用這個方法返回是個nil。
方法十: class_setIvarLayout

方法十一: class_getWeakIvarLayout
Discussion:返回一個類的ivar描述泌枪,關(guān)于是否是weak類型的
OC

const uint8_t * class_getWeakIvarLayout(Class cls);

Swift

func class_getWeakIvarLayout(_ cls: AnyClass?) -> UnsafePointer<UInt8>?

方法十二: class_setWeakIvarLayout

方法十三: class_getProperty
Discussion:返回具有給定類的給定名稱的屬性概荷。
OC

objc_property_t  _Nonnull * class_copyPropertyList(Class cls, unsigned int *outCount);
NSLog(@"888%s", property_getName(class_getProperty([self class], "property_1_s")));

Swift

func class_copyPropertyList(_ cls: AnyClass?, _ outCount: UnsafeMutablePointer<UInt32>?) -> UnsafeMutablePointer<objc_property_t>?

方法十四: class_copyPropertyList
Discussion:
OC

objc_property_t  _Nonnull * class_copyPropertyList(Class cls, unsigned int *outCount);
objc_property_t *properties = class_copyPropertyList([self class], &i);
j = 0;
while (j < i) {
    NSLog(@"property   %s", property_getName(*properties));
    properties++;
    j++;
}

Swift

func class_copyPropertyList(_ cls: AnyClass?, _ outCount: UnsafeMutablePointer<UInt32>?) -> UnsafeMutablePointer<objc_property_t>?

方法十五: class_addMethod
Discussion:class_addMethod將添加父類實現(xiàn)的重寫,但不會替換該類中的現(xiàn)有實現(xiàn)碌燕。要更改現(xiàn)有實現(xiàn)误证,請使用method_setImplementation。
OC

BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types);
class_addMethod([UIApplication class], @selector(addMethodxxx:), class_getMethodImplementation([self class], @selector(addMethodxxx:)), "v@:@");

方法十六: class_getInstanceMethod
Discussion:注意修壕,該函數(shù)可以搜索到從父類繼承來且自己沒重寫實現(xiàn)的方法愈捅,而class_copyMethodList則沒有。
OC

Method class_getInstanceMethod(Class cls, SEL name);
NSLog(@"%@", NSStringFromSelector(method_getName(class_getInstanceMethod([NewModel class], @selector(init)))));

方法十七: class_getClassMethod
OC

Method class_getClassMethod(Class cls, SEL name);
NSLog(@"%@", NSStringFromSelector(method_getName(class_getClassMethod([NewModel class], @selector(load)))));

方法十八: class_copyMethodList
Discussion:獲取一個類的所有實現(xiàn)的實例方法叠殷,不能獲取未被重寫實現(xiàn)的父類的方法改鲫。
OC

Method  _Nonnull * class_copyMethodList(Class cls, unsigned int *outCount);
Method *methods = class_copyMethodList([NewModel class], &i);
j = 0;
while (j < i) {
   NSLog(@"method   %s", sel_getName(method_getName(*methods)));
    methods++;
    j++;
}
free(methods);

方法十九: class_replaceMethod
Discussion:這個函數(shù)有兩種不同的表現(xiàn)方式:
如果名稱所標識的方法還不存在,那么它就會被添加林束,就像調(diào)用class_addMethod一樣像棘。類型指定的類型編碼被使用為給定。
如果名稱所標識的方法確實存在壶冒,那么它的IMP就會被替換為method_setImplementation缕题。類型指定的類型編碼將被忽略
OC

IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types);
class_replaceMethod([self class], @selector(addMethodxxx:), class_getMethodImplementation([self class], @selector(nslogMySon)), method_getTypeEncoding(class_getInstanceMethod([self class], @selector(nslogMySon))));

Swift

func class_replaceMethod(_ cls: AnyClass?, _ name: Selector, _ imp: IMP, _ types: UnsafePointer<Int8>?) -> IMP?

方法二十: class_getMethodImplementation
Discussion:class_getdimplementation可能比method_getimplem(class_getInstanceMethod(cls, name))更快。
返回的函數(shù)指針可能是運行時的函數(shù)胖腾,而不是實際的方法實現(xiàn)烟零。例如,如果類的實例不響應(yīng)選擇器咸作,返回的函數(shù)指針將是運行時消息轉(zhuǎn)發(fā)機制的一部分锨阿。
OC

IMP class_getMethodImplementation(Class cls, SEL name);
class_getMethodImplementation([self class], @selector(addMethodxxx:))

方法二十一: class_respondsToSelector
Discussion:你通常應(yīng)該使用NSObject的respondsToSelector:或者instancesRespondToSelector:方法而不是這個函數(shù)。
OC

BOOL class_respondsToSelector(Class cls, SEL sel);
NSLog(@"%d", class_respondsToSelector([self class], @selector(viewDidAppear:)));

方法二十二: class_addProtocol
OC

BOOL class_addProtocol(Class cls, Protocol *protocol);
class_addProtocol([self class], objc_getProtocol("UICollectionViewDelegate"));

方法二十三: class_addProperty
OC

BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount);
objc_property_attribute_t nonatomic = {"N", ""};
objc_property_attribute_t strong = {"&", ""};
objc_property_attribute_t type = {"T", "@\"NSString\""};
objc_property_attribute_t ivar = {"V", "_qqqqq"};
objc_property_attribute_t attributes[] = {nonatomic, strong, type, ivar};
class_addProperty([self class], "qqqqq", attributes, 4);

方法二十四: class_replaceProperty
Discussion:property = ivar + setter + getter记罚。我們在這個方法里只替換了ivar墅诡。但是沒有替換getter和setter。
OC

void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount);
    NSLog(@"666%s", property_getAttributes(class_getProperty([self class], "property_1_s")));
    objc_property_attribute_t nonatomic = {"N", ""};
    objc_property_attribute_t strong = {"&", ""};
    objc_property_attribute_t type = {"T", "@\"NSString\""};
    objc_property_attribute_t ivar = {"V", "_name"};
    objc_property_attribute_t attributes[] = {nonatomic, strong, type, ivar};
    ([self class], "property_1_s", attributes, 4);
    NSLog(@"666%s", property_getAttributes(class_getProperty([self class], "property_1_s")));

方法二十五: class_conformsToProtocol
Discussion:通常應(yīng)該使用NSObject的conformsToProtocol:方法而不是這個函數(shù)桐智。同樣也是引入即可末早。
OC

BOOL class_conformsToProtocol(Class cls, Protocol *protocol);
NSLog(@"%d", class_conformsToProtocol([self class], objc_getProtocol("UICollectionViewDelegate")));

方法二十六: class_copyProtocolList
Discussion:這個方法里返回的protocol不需要類進行設(shè)置代理烟馅,只需要引入?yún)f(xié)議即可
OC

Protocol * _Nonnull * class_copyProtocolList(Class cls, unsigned int *outCount);
Protocol * _Nonnull __unsafe_unretained *protocolList = class_copyProtocolList([self class], &protocolCount);
    j = 0;
    while (j < protocolCount) {
        j ++;
        NSLog(@"%s", protocol_getName(*protocolList));
        protocolList ++;
    }

方法二十七: class_getVersion
OC

int class_getVersion(Class cls);
NSLog(@"%d", class_getVersion([self class]));

Swift

int class_getVersion(Class cls);
print(class_getVersion(ViewController.self))

方法二十八: class_setVersion
OC

void class_setVersion(Class cls, int version);
class_setVersion([self class], 10086);

Swift

void class_setVersion(Class cls, int version);
class_setVersion(ViewController.self, 10086)

方法二十九: objc_allocateClassPair
Discussion:第一個參數(shù),創(chuàng)建類的父類然磷,如果為nil就創(chuàng)建一個NSObject類似的root class郑趁。第三個參數(shù),給0就行姿搜。要創(chuàng)建一個新類寡润,首先調(diào)用objc_allocateClassPair。然后使用class_addMethod和class_addIvar之類的函數(shù)設(shè)置類的屬性痪欲。構(gòu)建完類后悦穿,調(diào)用objc_registerClassPair。新類現(xiàn)在可以使用了业踢。應(yīng)該將實例方法和實例變量添加到類本身栗柒。類方法應(yīng)該添加到元類中。
OC

Class objc_allocateClassPair(Class superclass, const char *name, size_t extraBytes);
Class DXArrayClass = objc_allocateClassPair([NSArray class], "DXArray", 0);

Swift

func objc_allocateClassPair(_ superclass: AnyClass?, _ name: UnsafePointer<Int8>, _ extraBytes: Int) -> AnyClass?
let classType = objc_allocateClassPair(NSArray.self, "DXArray", 0)

方法三十: objc_registerClassPair
OC

void objc_registerClassPair(Class cls);
objc_registerClassPair(DXArrayClass);

Swift

func objc_registerClassPair(_ cls: AnyClass)
objc_registerClassPair(classType!)

方法三十一: objc_disposeClassPair
Discussion:刪除類及其關(guān)聯(lián)元類知举。如果存在類或任何子類的實例瞬沦,則不要調(diào)用此函數(shù)。
OC

void objc_disposeClassPair(Class cls);
objc_disposeClassPair(DXArrayClass);

Swift

func objc_disposeClassPair(_ cls: AnyClass)
objc_disposeClassPair(classType!)

方法三十二: class_createInstance
Discussion:創(chuàng)建一個類的實例雇锡,在默認的malloc內(nèi)存區(qū)域中為該類分配內(nèi)存逛钻。
OC

id class_createInstance(Class cls, size_t extraBytes);

方法三十三: objc_constructInstance
Discussion:不能在ARC中使用
方法三十四:objc_destructInstance
Discussion:不能在ARC中使用

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市锰提,隨后出現(xiàn)的幾起案子曙痘,更是在濱河造成了極大的恐慌,老刑警劉巖立肘,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件边坤,死亡現(xiàn)場離奇詭異,居然都是意外死亡谅年,警方通過查閱死者的電腦和手機茧痒,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來融蹂,“玉大人旺订,你說我怎么就攤上這事〕迹” “怎么了区拳?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長意乓。 經(jīng)常有香客問我劳闹,道長,這世上最難降的妖魔是什么洽瞬? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任本涕,我火速辦了婚禮,結(jié)果婚禮上伙窃,老公的妹妹穿的比我還像新娘菩颖。我一直安慰自己,他們只是感情好为障,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布晦闰。 她就那樣靜靜地躺著,像睡著了一般鳍怨。 火紅的嫁衣襯著肌膚如雪呻右。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天鞋喇,我揣著相機與錄音声滥,去河邊找鬼。 笑死侦香,一個胖子當著我的面吹牛落塑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播罐韩,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼憾赁,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了散吵?” 一聲冷哼從身側(cè)響起龙考,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎矾睦,沒想到半個月后晦款,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡顷锰,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年柬赐,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片官紫。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡肛宋,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出束世,到底是詐尸還是另有隱情酝陈,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布毁涉,位于F島的核電站沉帮,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜穆壕,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一待牵、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧喇勋,春花似錦缨该、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至熄云,卻和暖如春膨更,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缴允。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工荚守, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人癌椿。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓健蕊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親踢俄。 傳聞我的和親對象是個殘疾皇子缩功,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 1,690評論 0 9
  • 引導(dǎo) 對于從事 iOS 開發(fā)人員來說都办,所有的人都會答出「 Runtime 是運行時 」嫡锌,什么情況下用 Runtim...
    Winny_園球閱讀 4,197評論 3 75
  • 參考鏈接: http://www.cnblogs.com/ioshe/p/5489086.html 簡介 Runt...
    樂樂的簡書閱讀 2,132評論 0 9
  • 主要參考鏈接: http://yulingtianxia.com/blog/2014/11/05/objectiv...
    Kevin_Junbaozi閱讀 3,305評論 0 10
  • 我是一個非常普通的人,普通到不知道時光如何流逝就恍恍惚惚到了四十歲琳钉,然后周圍的人都說你已經(jīng)四十了势木,你已經(jīng)是中年人了...
    月半2閱讀 285評論 0 1