OC&Swift runtime 一 Classes

在Swift 4中繼承 NSObject 的 swift class 不再默認(rèn)全部 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是標(biāo)準(zhǔn)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)方式:
如果名稱所標(biāo)識的方法還不存在,那么它就會被添加,就像調(diào)用class_addMethod一樣。類型指定的類型編碼被使用為給定。
如果名稱所標(biāo)識的方法確實存在,那么它的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)建一個類的實例,在默認(rèn)的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)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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

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