在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中使用