目录
一,类
二,成员变量
三,属性
四,方法
五,交换函数
一,类
1,创建和销毁
int main(int argc, char * argv[]) {
@autoreleasepool {
// 创建类
Class newClass = objc_allocateClassPair([NSObject class], "Person", 0);
// 注册类
objc_registerClassPair(newClass);
id person = [newClass new];
NSLog(@"%@", person);
// 销毁类
objc_disposeClassPair(newClass);
}
return 0;
}
// 打印
<Person: 0x10066a270>
2,获取和设置
// Person
@interface Person : NSObject
- (void)eat;
+ (void)run;
@end
@implementation Person
- (void)eat {
NSLog(@"%s", __func__);
}
+ (void)run {
NSLog(@"%s", __func__);
}
@end
// Dog
@interface Dog: NSObject
- (void)eat;
+ (void)run;
@end
@implementation Dog
- (void)eat {
NSLog(@"%s", __func__);
}
+ (void)run {
NSLog(@"%s", __func__);
}
@end
// main
int main(int argc, char * argv[]) {
@autoreleasepool {
// 获取isa指向的Class(传实例对象返回类对象,传类对象返回元类对象)
NSLog(@"%@", object_getClass([Person new]));
// 设置isa指向的Class(设置实例对象的类对象,设置类对象的元类对象)
Person *person = [Person new];
object_setClass(person, [Dog class]);
object_setClass([Person class], object_getClass([Dog class]));
[person eat];
[Person run];
// 是否为类对象
NSLog(@"%d", object_isClass(object_getClass([Person new])));
// 是否为元类对象
NSLog(@"%d", class_isMetaClass(object_getClass([Person class])));
}
return 0;
}
// 打印
Person
-[Dog eat]
+[Dog run]
1
1
二,成员变量
1,获取和设置
// Person
@interface Person : NSObject
@property (nonatomic, assign) int age;
@property (nonatomic, copy) NSString *name;
@end
@implementation Person
@end
// main
int main(int argc, char * argv[]) {
@autoreleasepool {
// 获取成员变量
Ivar nameIvar = class_getInstanceVariable([Person class], "_name");
// 获取成员变量的名称和类型
NSLog(@"%s---%s", ivar_getName(nameIvar), ivar_getTypeEncoding(nameIvar));
// 获取和设置成员变量的值
Person *person = [Person new];
object_setIvar(person, nameIvar, @"111");
NSLog(@"%@", object_getIvar(person, nameIvar));
}
return 0;
}
// 打印
_name---@"NSString"
111
2,添加
- 代码
int main(int argc, char * argv[]) {
@autoreleasepool {
Class newClass = objc_allocateClassPair([NSObject class], "Person", 0);
// 添加成员变量
class_addIvar(newClass, "_name", sizeof(NSString *), log2(sizeof(NSString *)), @encode(NSString *));
objc_registerClassPair(newClass);
id person = [newClass new];
[person setValue:@"111" forKey:@"_name"];
NSLog(@"%@", [person valueForKey:@"_name"]);
}
return 0;
}
// 打印
111
- 说明
1>已经存在的类不能添加成员变量
2>动态创建的类必须在注册之前添加成员变量
3>已经存在或注册的类,它的结构已经确定,成员变量列表是只读的,不可以修改// ro是readonly的缩写 struct class_ro_t { const ivar_list_t *ivars; };
3,列表
- 基本使用
int main(int argc, char * argv[]) {
@autoreleasepool {
// 获取成员变量列表
unsigned int count;
Ivar *ivarList = class_copyIvarList([Person class], &count);
for (int i = 0; i < count; i++) {
Ivar ivar = ivarList[i];
NSLog(@"%s---%s", ivar_getName(ivar), ivar_getTypeEncoding(ivar));
}
free(ivarList);
}
return 0;
}
// 打印
_age---i
_name---@"NSString"
- 应用(字典转模型)
// NSObject
@interface NSObject (Add)
+ (instancetype)yj_modelWithDict:(NSDictionary *)dict;
@end
@implementation NSObject (Add)
+ (instancetype)yj_modelWithDict:(NSDictionary *)dict {
id model = [self new];
unsigned int count;
Ivar *ivarList = class_copyIvarList(self, &count);
for (int i = 0; i < count; i++) {
Ivar ivar = ivarList[i];
NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(ivar)];
// 去掉下划线
ivarName = [ivarName substringFromIndex:1];
[model setValue:dict[ivarName] forKey:ivarName];
}
free(ivarList);
return model;
}
@end
// main
int main(int argc, char * argv[]) {
@autoreleasepool {
NSDictionary *dict = @{@"age" : @1, @"name" : @"111"};
Person *person = [Person yj_modelWithDict:dict];
NSLog(@"%d---%@", person.age, person.name);
}
return 0;
}
// 打印
1---111
三,属性
1,获取
// Person
@interface Person : NSObject
@property (nonatomic, assign) int age;
@property (nonatomic, copy) NSString *name;
@end
@implementation Person
@end
// main
int main(int argc, char * argv[]) {
@autoreleasepool {
// 获取属性
objc_property_t nameProperty = class_getProperty([Person class], "name");
// 获取属性的名称和其他信息
NSLog(@"%s---%s", property_getName(nameProperty), property_getAttributes(nameProperty));
// 获取属性的其他信息列表
unsigned int count;
objc_property_attribute_t *attributeList = property_copyAttributeList(nameProperty, &count);
for (int i = 0; i < count; i++) {
objc_property_attribute_t attribute = attributeList[i];
NSLog(@"%s---%s", attribute.name, attribute.value);
}
free(attributeList);
}
return 0;
}
// 打印
name---T@"NSString",C,N,V_name
T---@"NSString" // type(类型):@表示对象,"NSString"表示具体类型
C--- // copy
N--- // nonatomic
V---_name // variable(成员变量)
2,添加和列表
int main(int argc, char * argv[]) {
@autoreleasepool {
// 添加属性
objc_property_attribute_t attribute1 = {"T", "@\"NSNumber\""};
objc_property_attribute_t attribute2 = {"&", ""}; // strong
objc_property_attribute_t attribute3 = {"N", ""};
objc_property_attribute_t attribute4 = {"V", "_height"};
objc_property_attribute_t attributeList[] = {attribute1, attribute2, attribute3, attribute4};
class_addProperty([Person class], "height", attributeList, 4);
// 获取属性列表
unsigned int count;
objc_property_t *propertyList = class_copyPropertyList([Person class], &count);
for (int i = 0; i < count; i++) {
objc_property_t property = propertyList[i];
NSLog(@"%s---%s", property_getName(property), property_getAttributes(property));
}
free(propertyList);
}
return 0;
}
// 打印
height---T@"NSNumber",&,N,V_height
age---Ti,N,V_age
name---T@"NSString",C,N,V_name
四,方法
1,获取
// Person
@interface Person : NSObject
- (int)eat:(int)food;
+ (void)run;
@end
@implementation Person
- (int)eat:(int)food {
NSLog(@"%s", __func__);
return 1;
}
+ (void)run {
NSLog(@"%s", __func__);
}
@end
// main
int main(int argc, char * argv[]) {
@autoreleasepool {
// 获取实例方法
Method eatMethod = class_getInstanceMethod([Person class], @selector(eat:));
// 获取类方法
Method runMethod = class_getClassMethod(object_getClass([Person class]), @selector(run));
// 获取方法的名称
NSLog(@"%@", NSStringFromSelector(method_getName(eatMethod)));
// 获取方法的返回值类型
NSLog(@"%s", method_copyReturnType(eatMethod));
// 获取方法的参数个数(系统默认会添加两个参数)
NSLog(@"%d", method_getNumberOfArguments(eatMethod));
// 获取方法第三个参数的类型
NSLog(@"%s", method_copyArgumentType(eatMethod, 2));
// 获取方法返回值类型和参数类型的编码
NSLog(@"%s", method_getTypeEncoding(eatMethod));
}
return 0;
}
// 打印
eat:
i
3
i
i20@0:8i16
2,SEL
和IMP
void run2() {
NSLog(@"begin run2");
}
// main
int main(int argc, char * argv[]) {
@autoreleasepool {
// 用字符串生成SEL
SEL runSel = sel_registerName("run");
Method runMethod = class_getInstanceMethod(object_getClass([Person class]), @selector(run));
// 获取方法的IMP
IMP runImp = method_getImplementation(runMethod);
// 重设方法的IMP(函数)
method_setImplementation(runMethod, (IMP)run2);
[Person run];
// 重设方法的IMP(block)
void(^impBlock)(void) = ^{
NSLog(@"imp with block");
};
method_setImplementation(runMethod, imp_implementationWithBlock(impBlock));
[Person run];
}
return 0;
}
// 打印
begin run2
imp with block
3,添加和列表
void work() {
NSLog(@"begin work");
}
// main
int main(int argc, char * argv[]) {
@autoreleasepool {
// 添加方法
class_addMethod([Person class], sel_registerName("work"), (IMP)work, "v");
[[Person new] performSelector:@selector(work)];
// 获取方法列表
unsigned int count;
Method *methodList = class_copyMethodList([Person class], &count);
for (int i = 0; i < count; i++) {
Method method = methodList[i];
NSLog(@"%@", NSStringFromSelector(method_getName(method)));
}
free(methodList);
}
return 0;
}
// 打印
begin work
work
eat:
五,交换函数
1,基本使用
// Person
@interface Person : NSObject
- (void)eat;
- (void)run;
@end
@implementation Person
- (void)eat {
NSLog(@"%s", __func__);
}
- (void)run {
NSLog(@"%s", __func__);
}
@end
// main
int main(int argc, char * argv[]) {
@autoreleasepool {
// 交换方法的IMP
Method eatMethod = class_getInstanceMethod([Person class], @selector(eat));
Method runMethod = class_getInstanceMethod([Person class], @selector(run));
method_exchangeImplementations(eatMethod, runMethod);
Person *person = [Person new];
[person eat];
[person run];
}
return 0;
}
// 打印
-[Person run]
-[Person eat]
2,应用(防止数组下标越界)
// NSArray
@interface NSArray (Add)
@end
@implementation NSArray (Add)
+ (void)load {
// NSArray的真实类型是__NSArrayI
Method systemMethod = class_getInstanceMethod(NSClassFromString(@"__NSArrayI"), @selector(objectAtIndexedSubscript:));
Method customMethod = class_getInstanceMethod(NSClassFromString(@"__NSArrayI"), @selector(yj_objectAtIndexedSubscript:));
method_exchangeImplementations(systemMethod, customMethod);
}
// 系统调用的并不是objectAtIndex:
- (id)yj_objectAtIndexedSubscript:(NSUInteger)idx {
if (idx < self.count) {
return [self yj_objectAtIndexedSubscript:idx];
} else {
return @"下标已越界";
}
}
@end
// main
int main(int argc, char * argv[]) {
@autoreleasepool {
NSArray *array = @[@"1", @"2", @"3"];
NSLog(@"%@", array[3]);
}
return 0;
}
// 打印(交换前)
*** Terminating app due to uncaught exception 'NSRangeException',
reason: '*** -[__NSArrayI objectAtIndexedSubscript:]: index 3 beyond bounds [0 .. 2]'
// 打印(交换后)
下标已越界
3,本质
- 底层代码(源码下载地址)
void method_exchangeImplementations(Method m1, Method m2)
{
if (!m1 || !m2) return;
mutex_locker_t lock(runtimeLock);
// 交换IMP
IMP m1_imp = m1->imp;
m1->imp = m2->imp;
m2->imp = m1_imp;
// 清理方法缓存
flushCaches(nil);
updateCustomRR_AWZ(nil, m1);
updateCustomRR_AWZ(nil, m2);
}
- 图解
网友评论