viewcontroller:
#import "ViewController.h" #import <objc/runtime.h> #import <objc/message.h> @interface ViewController ()<UITableViewDataSource>{ NSArray *_property0; NSArray *property1; } @property (nonatomic,strong)UIColor *property2; @property (nonatomic,strong)NSArray *property0; @end @implementation ViewController
-(void)method0{
NSLog(@">>>>>>>>5");
}
-(void)method1{
NSLog(@">>>>>>>>6");
}
动态添加变量
-(void)getAndSet{ //添加--为动态创建类添加变量 /** * 1.只能给动态创建的类添加变量也就是用 objc_allocateClassPair 创建的类 * 2.添加变量只能在函数 objc_allocateClassPair 和 class_getInstanceVariable 之间添加才有效 */ Class CreatClass0 = objc_allocateClassPair([NSObject class], "CreatClass0", 0); class_addIvar(CreatClass0, "_attribute0", sizeof(NSString *), log(sizeof(NSString *)), "i"); Ivar ivar = class_getInstanceVariable(CreatClass0, "_attribute0");//获取变量,如果没获取到说明不存在 NSLog(@">>>>>>>>0:%@",[NSString stringWithUTF8String:ivar_getName(ivar)]); objc_registerClassPair(CreatClass0); NSLog(@" "); //添加--为动态创建的类添加变量然后添加属性,类和变量和属性都是动态创建的 /** * 1.各个属性:暂时不知道 * 2.下面这个反驳了上面的第二标,这个证明id不是不会报错,规律是如果id调用的是系统的类的方法,那么就不会报错, 详细介绍:上面的@selector(name) 和 @selector(setName:) name是好多系统类都有方法,所以id会认为本身代表的是那个类 所以不会报错,但是如果你硬写一个完全没有的方法,它就会报错 * 3.添加属性不用再objc_registerClassPair之前,因为添加属性其实就是添加变量的set 和 get方法而已 * 4.添加的属性和变量不能用kvc设置值和取值 */ objc_property_attribute_t type2 = { "T", "@"NSString"" };//"T"表示获取该属性的类型 // objc_property_attribute_t attribute2 = {"N",""};//value无意义时通常设置为空 objc_property_attribute_t ownership2 = { "C", "" }; // C = copy objc_property_attribute_t backingivar2 = { "V", "_attribute0" };// objc_property_attribute_t attrs2[] = { type2, ownership2, backingivar2 }; class_addProperty(CreatClass0, "_attribute0", attrs2, 3); SEL getter = NSSelectorFromString(@"attribute0"); SEL setter = NSSelectorFromString(@"setAttribute0:"); BOOL suc0 = class_addMethod(CreatClass0, getter, (IMP)attribute0Getter, "@@:");//i@:@ i:返回值类型int,若是v则表示void BOOL suc1 = class_addMethod(CreatClass0, setter, (IMP)attribute0Setter, "v@:@");//i@:@ NSLog(@">>>>>>>>3:%@:%@",@(suc0),@(suc1)); id idclass = [[CreatClass0 alloc]init]; NSLog(@">>>>>>>>1:%@",[idclass performSelector:getter withObject:nil]);//withObject 传递的参数 [idclass performSelector:setter withObject:@"为动态创建类先添加变量再添加属性"]; NSLog(@">>>>>>>>2:%@",[idclass performSelector:getter withObject:nil]); //class获取--获取整个类的实例方法的方法列表 /** * 1.获取所有实例方法,不包含静态方法 * 2.不获取父类的方法 * 3.隐式的get set 方法也能获取到 * 4.关于Method的更多用法参考Class2类 */ unsigned int copycopyMethodListCount = 0; Method *methods = class_copyMethodList([self class], ©copyMethodListCount); for (NSInteger i = 0; i < copycopyMethodListCount; i++) { Method method = methods[i]; SEL name = method_getName(method); // NSLog(@">>>>>>>>2:copyMethodList:%@",NSStringFromSelector(name)); } free(methods);//释放 NSLog(@" "); BOOL result0 = class_addProtocol([self class], NSProtocolFromString(@"UITableViewDelegate")); NSLog(@">>>>>>>>3:添加协议成功"); //添加--协议 /** * 1.class_addProtocol 参数含义:第一个:要添加协议的类,第二个:协议对象 * 2.获取协议列表具体细节参照Class1里的内容 */ unsigned int copyProtocolListCount = 0; Protocol * __unsafe_unretained *protocals = class_copyProtocolList([self class], ©ProtocolListCount); for (NSInteger i = 0; i < copyProtocolListCount; i++) { Protocol * protocal = protocals[i]; const char *name = protocol_getName(protocal); NSLog(@">>>>>>>>4:copyProtocolList:%s",name); } free(protocals);//释放 NSLog(@" "); }
// - (void)viewDidLoad { [super viewDidLoad]; // [self getAndSet]; // [self objectGetMethod]; // [self getClassCopy]; [self method0]; BOOL result0 = class_replaceMethod([self class], @selector(method0), [ViewController instanceMethodForSelector:NSSelectorFromString(@"method1")], NULL); NSLog(@">>>>>>>>2:%@",@(result0)); [self method0]; } //get方法 NSString *attribute0Getter(id classInstance, SEL _cmd) { NSLog(@"%@ %@",classInstance,NSStringFromSelector(_cmd)); Ivar ivar = class_getInstanceVariable([classInstance class], "_attribute0");//获取变量,如果没获取到说明不存在 return object_getIvar(classInstance, ivar); } //set方法 void attribute0Setter(id classInstance, SEL _cmd, NSString *newName) { Ivar ivar = class_getInstanceVariable([classInstance class], "_attribute0");//获取变量,如果没获取到说明不存在 id oldName = object_getIvar(classInstance, ivar); if (oldName != newName) object_setIvar(classInstance, ivar, [newName copy]); } -(void)getClassCopy{ //class获取--获取整个成员变量列表 /** * 1.获取所有私有变量和属性 * 2.获取的私有变量的名和定义的名一模一样 * 3.获取的属性的名前面都添加了下划线 */ unsigned int copyIvarListCount = 0; Ivar *ivars = class_copyIvarList([self class], ©IvarListCount); for (NSInteger i = 0; i< copyIvarListCount; i ++) { Ivar ivar = ivars[i]; const char *name = ivar_getName(ivar); NSLog(@">>>>>>>>0:class_copyIvarList:%s",name); } free(ivars);//释放 NSLog(@" "); //获取属性列表(只获取属性不获取变量) //入参:类Class,int变量指针 //返回:属性信息objc_property_t列表 //* 1.获取所有属性 //* 2.获取的属性名和你代码写的一样,获取出来的属性名不自动添加下划线 //* 3.不能获取Category添加的属性。 unsigned int property = 0; objc_property_t *objcProperty = class_copyPropertyList([self class], &property); for (NSInteger i = 0; i < property; i++) { objc_property_t propertyT = objcProperty[i]; const char *name = property_getName(propertyT); NSLog(@">>>>>>>>0:class_copyIvarList:%s",name); } free(objcProperty); NSLog(@" "); //获取方法列表 //入参:类Class,int变量指针 //返回:方法信息Method列表 //* 1.获取所有实例方法,不包含静态方法 //* 2.不获取父类的方法 //* 3.隐式的get set 方法也能获取到 //* 4.可以获取分类和动态添加的方法。 // Method *class_copyMethodList(Class cls, unsigned int *outCount) unsigned int methodCount = 0; Method *methods = class_copyMethodList([self class], &methodCount); for(NSInteger i = 0 ; i < methodCount; i++){ Method thod = methods[i]; SEL name = method_getName(thod); NSLog(@"***:%@",NSStringFromSelector(name)); ; } free(methods); NSLog(@" "); //添加--协议 /** * 1.class_addProtocol 参数含义:第一个:要添加协议的类,第二个:协议对象 * 2.获取协议列表具体细节参照Class1里的内容 */ unsigned int copyProtocolListCount = 0; Protocol * __unsafe_unretained *protocals = class_copyProtocolList([self class], ©ProtocolListCount); for (NSInteger i = 0; i < copyProtocolListCount; i++) { Protocol * protocal = protocals[i]; const char *name = protocol_getName(protocal); NSLog(@">>>>>>>>3:copyProtocolList:%s",name); } free(protocals);//释放 NSLog(@" "); } -(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{ return 0; } -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ return nil; } /* SEL:类成员方法的指针,但不同于C语言中的函数指针,函数指针直接保存了方法的地址,但SEL只是方法编号。 IMP:一个函数指针,保存了方法的地址 Method:方法的结构体,其中保存了方法的名字,实现和类型描述字符串 //在runtime.h里面我们可以看到定义 //Method 是一个方法结构体的指针 typedef struct objc_method *Method; //方法的结构体包含了方法需要的信息 struct objc_method { SEL method_name; char *method_types;//方法返回值,和各个参数类型等的字符串描述 IMP method_imp; } //根据函数获取函数的SEL @selector() //获取函数指针SEL的函数名字符串 NSString *NSStringFromSelector(SEL aSelector); //根据函数名获取函数指针 SEL NSSelectorFromString(NSString *aSelectorName); //获取类Class的字符串描述 NSString *NSStringFromClass(Class aClass); //根据类的字符串描述获取类Class Class _Nullable NSClassFromString(NSString *aClassName); //获取协议的字符串描述(协议名字) NSString *NSStringFromProtocol(Protocol *proto) //根据协议名字获取协议对象 Protocol * _Nullable NSProtocolFromString(NSString *namestr) */ #pragma mark objectGetMethod - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end
获取对象方法
-(void)objectGetMethod{ //获取类名 //入参:类Class //返回:类名char数组 const char *result0 = class_getName([ViewController class]); NSLog(@">>>>>>>>0:%@",[NSString stringWithUTF8String:result0]); //获取父类 //入参:类Class //返回:类Class Class result1 = class_getSuperclass([ViewController class]); NSLog(@">>>>>>>>1:%@",result1); //获取实例大小(返回size_t) //入参:实例的类Class //返回:大小size_t //深究请看这篇文章http://www.jianshu.com/p/df6b252fbaae size_t result2 = class_getInstanceSize([ViewController class]); NSLog(@">>>>>>>>2:%zu",result2); //获取类中指定名称实例成员变量的信息 //入参:类Class,变量名 //返回:变量信息Ivar //* 1.实例变量是指变量不是属性.例如某类有个属性为:username 那么它对应的实例变量为_username //* 2.这个方法可以获取属性的变量,也可以获取私有变量(这点很重要) //* 3.如果获取的变量为空,那么 ivar_getName和 ivar_getTypeEncoding 获取的值为空,那么[NSString stringWithUTF8String:ivar1Name] 执行崩溃 const char *result3 = [@"property0" UTF8String]; Ivar result4 = class_getInstanceVariable([ViewController class], result3); NSLog(@">>>>>>>>3:%@",result4); //获取指定的属性 //入参:类Class,属性名char数组 //返回:属性objc_property_t // * 1.属性不是变量,此方法只能获取属性 // * 2.如果属性不存在那么返回的结构体为0(可以参考下面的判断) // * 3.属性不存在获取property_getName 和 property_getAttributes 会崩溃 const char *result5 = [@"property0" UTF8String]; objc_property_t result6 = class_getProperty([ViewController class], result5); NSLog(@">>>>>>>>4:%@",[NSString stringWithUTF8String:property_getName(result6)]); //获取方法实现 //入参:类Class,方法名SEL //返回:方法实现IMP IMP result7 = class_getMethodImplementation([ViewController class], @selector(method0)); result7(); //获取方法实现 //入参:类Class,方法名SEL //返回:方法实现IMP IMP result8 = class_getMethodImplementation_stret([ViewController class], @selector(method1)); result8(); //获取类方法 //入参:类Class,方法名SEL //返回:方法Method Method result9 = class_getClassMethod([ViewController class], @selector(viewDidLoad)); NSLog(@">>>>>>>>7:%@",result9); }
OBJC_ASSOCIATION_RETAIN_NONATOMIC
/* #import <objc/runtime.h>头文件 //1 源对象alert //2 关键字 唯一静态变量key associatedkey //3 关联的对象 sender //4 关键策略 OBJC_ASSOCIATION_RETAIN_NONATOMIC associatedkey associatedButtonkey是一个唯一静态变量 objc_setAssociatedObject(alert, &associatedkey, message,OBJC_ASSOCIATION_RETAIN_NONATOMIC); objc_setAssociatedObject(alert, &associatedButtonkey, sender,OBJC_ASSOCIATION_RETAIN_NONATOMIC); NSString *messageString =objc_getAssociatedObject(alertView, &associatedkey); UIButton *sender = objc_getAssociatedObject(alertView, &associatedButtonkey); objc_removeAssociatedObjects可以断开所有关联 */