动态创建一个类
//TODO:
参照objc runtime的文章写一个demo,然后把vc中的代码和运行结果贴出来
- (void)viewDidLoad {
[super viewDidLoad];
//利用RunTime创建一个类
Class PersonClass = objc_allocateClassPair([NSObject class], "Person", 0);
class_addIvar(PersonClass, "avatar", sizeof(UIImage *), log2(sizeof(UIImage *)), @encode(UIImage *));
class_addIvar(PersonClass, "name", sizeof(NSString *), log2(sizeof(NSString *)), @encode(NSString *));
objc_registerClassPair(PersonClass);
unsigned int count = 0;
Ivar *members = class_copyIvarList(PersonClass, &count);
for (int i = 0 ; i < count; i++) {
Ivar var = members[i]; const char *memberName = ivar_getName(var); const char *memberType = ivar_getTypeEncoding(var);
NSLog(@"memberType %s: memberName %s",memberType,memberName);
}
Ivar nameIvar = class_getInstanceVariable(PersonClass, "name");
Ivar avatarIvar = class_getInstanceVariable(PersonClass, "avatar");
id personObject = [[NSClassFromString(@"Person") alloc]init];
UIImage *avartarImage = [UIImage imageNamed:@"IMG_1.JPG"];
NSLog(@"avartarImage == %@",avartarImage);
object_setIvar(personObject, nameIvar, @"张三");
object_setIvar(personObject, avatarIvar,avartarImage );
NSString *achivedName = object_getIvar(personObject, nameIvar);
UIImage *achivedAvartarImage = object_getIvar(personObject, avatarIvar);
NSLog(@"runtime achivedAvartarImage == %@",achivedAvartarImage);
NSLog(@"runtime achivedName == %@",achivedName);
NSLog(@"try kvc instead ");
[personObject setValue:@"李四" forKey:@"name"];
[personObject setValue:avartarImage forKey:@"avatar"];
NSLog(@"kvc name == %@",[personObject valueForKey:@"name"]);
NSLog(@"kvc image == %@",[personObject valueForKey:@"avatar"]);
// Do any additional setup after loading the view, typically from a nib.
}
打印结果
memberType @: memberName avatar
memberType @: memberName name
avartarImage == <UIImage: 0x135e3d0f0>, {2448, 3264}
runtime achivedAvartarImage == <UIImage: 0x135e3d0f0>, {2448, 3264}
runtime achivedName == 张三
try kvc instead
kvc name == 李四
kvc image == <UIImage: 0x135e3d0f0>, {2448, 3264}
runtime过程中出现了内存管理的问题,野指针。相反的KVC就不会遇到这样的问题
1,常见的几种用法找一下,MJRefresh和MJExtension中
2,修改系统常用的方法
3,创建匿名对象
4,JSPatch了解一下
5,发布app
修改系统API方法的实现
- (void)backup{
Class dynaClass = objc_allocateClassPair([NSObject class], "HXShareItem", 0);
class_addIvar(dynaClass, "hxImage", sizeof(UIImage *), log2(sizeof(UIImage *)), @encode(UIImage *));
class_addIvar(dynaClass, "hxImagePath", sizeof(NSURL *), log2(sizeof(NSURL *)), @encode(NSURL *));
class_addMethod(dynaClass, @selector(activityViewControllerPlaceholderItem:), (IMP)activityViewControllerPlaceholderItem, "@@:@");
class_addMethod(dynaClass, @selector(activityViewController:itemForActivityType:), (IMP)activityViewControlleritemForActivityType, "@@:@@");
//声明类遵守UIActivityItemSource 协议
class_addProtocol(dynaClass, @protocol(UIActivityItemSource));
objc_registerClassPair(dynaClass);
Ivar imageIvar = class_getInstanceVariable(dynaClass, "hxImage");
Ivar pathIvar = class_getInstanceVariable(dynaClass, "hxImagePath");
int count = 0;
Ivar *members = class_copyIvarList([dynaClass class], &count);
for (int i = 0 ; i < count; i++) {
Ivar var = members[i]; const char *memberName = ivar_getName(var); const char *memberType = ivar_getTypeEncoding(var);
NSLog(@"memberType %s: memberName %s",memberType,memberName);
}
id dynaObject = [[NSClassFromString(@"HXShareItem") alloc]init];
object_setIvar(dynaObject, imageIvar, [UIImage imageNamed:@"IMG_1.JPG"]);
UIImage *image2 = object_getIvar(dynaObject, imageIvar);
NSLog(@"image2 == %@ class %@",image2,dynaClass);
object_setIvar(dynaObject, pathIvar, [NSURL URLWithString:@"http://www.baidu.com"]);
// [NSURL URLWithString:@"http://img5.duitang.com/uploads/item/201601/20/20160120132111_LGiVZ.thumb.224_0.jpeg"]
NSURL *url = object_getIvar(dynaObject, pathIvar);
NSLog(@"url1 == %@",url);
}
采用了KVC对其中的内容进行赋值
#pragma mark - 用OC动态实现一个类
//定义协议方法1 返回图片
id activityViewControllerPlaceholderItem(id self,SEL _cmd,UIActivityViewController *activityViewController){
UIImage *image = [self valueForKey:@"hxImage"];
NSLog(@"image == %@",image);
return image;
}
//定义协议方法2 返回网址
id activityViewControlleritemForActivityType(id self,SEL _cmd,UIActivityViewController *activityViewController,NSString *activityType){
NSURL *url = [self valueForKey:@"hxImagePath"];
NSLog(@"url == %@",url);
return url;
}
//调用动态类的过程
-(void)startFromALAssets{
NSMutableArray *shareItems = [NSMutableArray array];
Class HXShareItemClass =NSClassFromString(@"HXShareItem");
if (!HXShareItemClass) {
//动态生成一个类
HXShareItemClass = objc_allocateClassPair([NSObject class], "HXShareItem", 0);
class_addIvar(HXShareItemClass, "hxImage", sizeof(UIImage *), log2(sizeof(UIImage *)), @encode(UIImage *));
class_addIvar(HXShareItemClass, "hxImagePath", sizeof(NSURL *), log2(sizeof(NSURL *)), @encode(NSURL *));
//实现协议的必须方法
class_addMethod(HXShareItemClass, @selector(activityViewControllerPlaceholderItem:), (IMP)activityViewControllerPlaceholderItem, "@@:@");
class_addMethod(HXShareItemClass, @selector(activityViewController:itemForActivityType:), (IMP)activityViewControlleritemForActivityType, "@@:@@");
//声明类遵守UIActivityItemSource 协议
class_addProtocol(HXShareItemClass, @protocol(UIActivityItemSource));
objc_registerClassPair(HXShareItemClass);
}
// 网址和placeholder是独立的,具体作用要后续看看。placeholder的字面意思是占位
id dynaObject = [[NSClassFromString(@"HXShareItem") alloc]init];
//采用KVC的方式是可以的
[dynaObject setValue:[UIImage imageNamed:@"IMG_1.JPG"] forKey:@"hxImage"];
[dynaObject setValue:[NSURL URLWithString:@"http://img5.duitang.com/uploads/item/201601/20/20160120132111_LGiVZ.thumb.224_0.jpeg"] forKey:@"hxImagePath"];
if (dynaObject) {
[shareItems addObject:dynaObject];
}
//调用分享的组件
UIActivityViewController *activityVC =[[UIActivityViewController alloc]initWithActivityItems:shareItems applicationActivities:nil];
if (activityVC) {
[self presentViewController:activityVC animated:YES completion:nil];
}
}
http://blog.youkuaiyun.com/u013538542/article/details/50923701
http://www.cocoachina.com/ios/20151231/14828.html
http://www.cocoachina.com/ios/20160128/15154.html
http://www.cocoachina.com/ios/20160324/15768.html
http://www.cocoachina.com/ios/20160523/16386.html
http://www.360doc.com/content/11/1231/10/8455184_176246899.shtml
拦截系统方法的一次实践
处理按钮不能被连续点击的问题。
通过hzt_ignoreEvent 设定值,使按钮在指定时间hzt_acceptEventInterval内不可以连续被点击
#import <UIKit/UIKit.h>
@interface UIButton (HZTButton)
@property (nonatomic, assign) NSTimeInterval hzt_acceptEventInterval;
@end
#import "UIButton+HZTButton.h"
@interface UIButton ()
@property (nonatomic,assign) BOOL hzt_ignoreEvent;
@end
@implementation UIButton (HZTButton)
static const char *UIControl_acceptEventInterval = "UIControl_acceptEventInterval";
static const char *UIControl_ignoreEvent = "UIControl_ignoreEvent";
+ (void)load
{
Method a = class_getInstanceMethod(self, @selector(sendAction:to:forEvent:));
Method b = class_getInstanceMethod(self, @selector(__hzt_sendAction:to:forEvent:));
method_exchangeImplementations(a, b);
}
- (void)__hzt_sendAction:(SEL)action to:(id)target forEvent:(UIEvent *)event
{
if (self.hzt_ignoreEvent){
NSLog(@"not send");
self.enabled = NO;
return;
}
if (self.hzt_acceptEventInterval > 0)
{
self.hzt_ignoreEvent = YES;
[self performSelector:@selector(setHzt_ignoreEvent:)
withObject:@(NO)
afterDelay:self.hzt_acceptEventInterval];
}
[self __hzt_sendAction:action to:target forEvent:event];
}
- (BOOL)hzt_ignoreEvent{
BOOL ignore = [objc_getAssociatedObject(self,UIControl_ignoreEvent) boolValue];
return ignore;
}
- (void)setHzt_ignoreEvent:(BOOL)hzt_ignoreEvent{
self.enabled = !hzt_ignoreEvent;
objc_setAssociatedObject(self, UIControl_ignoreEvent, @(hzt_ignoreEvent), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (NSTimeInterval)hzt_acceptEventInterval
{
double timeInterval = [objc_getAssociatedObject(self, UIControl_acceptEventInterval) doubleValue];
if (timeInterval==0) {
timeInterval = 3;
}
return timeInterval;
}
- (void)setHzt_acceptEventInterval:(NSTimeInterval)hzt_acceptEventInterval
{
objc_setAssociatedObject(self, UIControl_acceptEventInterval, @(hzt_acceptEventInterval), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
http://www.cocoachina.com/ios/20150828/13260.html