一 .objc/runtime.h相关
Objecitve-C的重要特性是 Runtime(运行时),在 Interacting with the Runtime(交互运行)中,运行时函数部分,苹果给出了 /usr/lib/libobjc.A.dylib库,这个共享库提供支持动态属性的 objective - c语言,通过其接口,可以用于开发将其他语言运行于 Objective-C 上的中间层(桥接层),库里的函数定义为纯 C语言。
二 .objc/runtime.h使用
在这里我们主要举个简单的栗子�� ,通过新建一个UIButton 的类别。
1. 导入头文件
#import <objc/runtime.h>
2.新建一个 Action的 Category;
然后在.h 中添加一个事件的Block ,代码如下:
#import <UIKit/UIKit.h> typedef void (^ActionBlock)( UIButton *button); @interface UIButton (Action) @property ( nonatomic , copy ) ActionBlock actionBlock; + (UIButton *)createBtnWithFrame:(CGRect)frame title :( NSString *)title actionBlock :(ActionBlock)actionBlock; @end
在这里我们创建了一个加方法,来创建一个按钮;
实现如下:
+ ( UIButton *)createBtnWithFrame:(CGRect)frame title :( NSString *)title actionBlock :(ActionBlock)actionBlock{ UIButton *button = [[UIButton alloc ]init]; button.frame = frame; [button setTitle :title forState :UIControlStateNormal]; [button addTarget :button action : @selector (buttonClick:) forControlEvents :UIControlEventTouchUpInside]; objc_setAssociatedObject (button , &keyOfMethod, actionBlock, OBJC_ASSOCIATION_COPY_NONATOMIC); return button; }
objc_setAssociatedObject(id object, const void *key, id value, objc_AssociationPolicy policy)
id object :表示关联者,是一个对象,变量名理所当然也是 object
const void *key :获取被关联者的索引 key
id value :被关联者,这里是一个 block
objc_AssociationPolicy policy : 关联时采用的协议,有 assign, retain, copy等协议,一般使用 OBJC_ASSOCIATION_RETAIN_NONATOMIC
注意这里面我声明了两个索引KEY;
static NSString *keyOfMethod; static NSString *keyOfBlock;
- ( void )buttonClick:( UIButton *)button{ ActionBlock block1 = (ActionBlock)objc_getAssociatedObject(button, &keyOfMethod); if (block 1 ){ block1 (button); } ActionBlock block2 = (ActionBlock)objc_getAssociatedObject(button, &keyOfBlock); if (block 2 ){ block2 (button); } } - (void )setActionBlock:(ActionBlock)actionBlock{ objc_setAssociatedObject (self , &keyOfBlock, actionBlock, OBJC_ASSOCIATION_COPY_NONATOMIC ); } - (ActionBlock)actionBlock{ return objc_getAssociatedObject ( self ,&keyOfBlock); }
3.通过类别创建两个按钮
- ( void )uiConfig{ UIButton *button 1 = [UIButton createBtnWithFrame :CGRectMake((ScreenWidth - 1 0 0 )/ 2 , (ScreenHeight - 5 0 )/ 2 - 5 0 , 1 0 0 , 5 0 ) title : @"按钮" actionBlock :^( UIButton *button) { float r = random()% 2 5 5 / 2 5 5 .0 ; float g = random()% 2 5 5 / 2 5 5 .0 ; float b = random()% 2 5 5 / 2 5 5 .0 ; self .view .backgroundColor = RGB(r, g, b); }]; button1 .backgroundColor = [UIColor lightGrayColor ]; [self .view addSubview :button 1 ]; UIButton *button 2 = [UIButton createBtnWithFrame :CGRectMake((ScreenWidth - 1 0 0 )/ 2 , CGRectGetMaxY(button 1 .frame ) + 5 0 , 1 0 0 , 5 0 ) title : @"按钮2" actionBlock :nil ]; button2 .actionBlock = ^( UIButton *button){ NSLog(@"---%@---" ,button .currentTitle ); }; button2 .backgroundColor = [UIColor lightGrayColor ]; [self .view addSubview :button 2 ]; }
4.获取苹果私有的APi
这里我们也可以通过 runtime获取苹果私有的方法;
#pragma mark - 获取苹果私有的APi方法 - (void )getiOSPrivateAPi{ NSString *className = NSStringFromClass([UIView class ]); const char char *cClassName = [className UTF8String ]; id theClass = objc_getClass(cClassName); unsigned int outCount; Method *m = class_copyMethodList(theClass,&outCount); NSLog(@"%d" ,outCount); for ( int i = 0 ; i<outCount; i++) { SEL a = method_getName(*(m+i)); NSString *sn = NSStringFromSelector(a); NSLog(@"%@" ,sn); } }