ios runtime重要性_iOS Runtime的理解与使用

简介

Objective-C是一门古老的语言,但是是一门动态性的语言,因为它的动态性,使其又有了强大的生命力,在苹果生态系统的平台应用广泛,可谓互相成全了对方,Objective-C的动态性随处可见,当子类覆写父类方法的时候,总是在执行前才决定该执行什么,不像C在编译时就已经决定了代码的执行,能让Objective-C有强大动态性的就是Runtime类库。

原理

Runtime的核心就是消息转发,当对象调用方法是,程序执行[object doSomething]时,会向消息接收者(object)发送一条消息(doSomething),runtime会根据消息接收者是否能响应该消息而做出不同的反应。

简单的说主要有这几点:

1.消息传递(Messaging)

2.动态方法解析和转发

原理这一块儿我并没有写的很详细,大家可以看这几篇原理博客的详细介绍。

使用

1.在使用delegate的时候我们在判断代理是否遵守协议的时候,会发送一条消息,当消息没有被响应的时候,会抛出异常。

//这里就是发送了一条消息,看代理是否能够响应到,响应到的时候执行方法

if ([self.delegate respondsToSelector:@selector(dosomething:)]) {

[self.delegate dosomething:@""];

}

2.给对象添加category的时候是没有办法给之间添加property方法的,需要使用runtime进行动态绑定,这个可以参考AFNetwortking里面的写法

@interface UIView (category)

//声明

@property (nonatomic,copy) NSString *text;

@end

#import "UIView+category.h"

#import

//设置key

static char textKey;

@implementation UIView (category)

//设置关联

-(void)setText:(NSString *)text{

objc_setAssociatedObject(self, &textKey, text, OBJC_ASSOCIATION_COPY_NONATOMIC);

}

//获取关联的值

-(NSString *)text{

return objc_getAssociatedObject(self, &textKey);

}

@end

3.Method Swizzling

我觉得这才是Runtime运用场景最为广泛的地方,java有反射机制,可以设置动态代理,实现AOP编程,但是Objective-C的Runtime则更为强大。

原理图

下面来看一段代码

void swizzleMethod(Class class, SEL originalSelector, SEL swizzledSelector) {

//原始方法指针

originalMethod = class_getInstanceMethod(class, originalSelector);

Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

// 给类添加方法指针

didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod));

if (didAddMethod)

{

//将原始的方法实现赋给swizzledSelector

class_replaceMethod(class, swizzledSelector,method_getImplementation(originalMethod),method_getTypeEncoding(originalMethod));

} else {

//交换方法实现

method_exchangeImplementations(originalMethod, swizzledMethod);

}

}

上面是一段比较常见的方法交叉代码,但是我们在开发中用的是Aspects这个第三方的开源库,用这个开源库你可以实现自己的一些埋点统计或者判断UI刷新。

埋点统计

+ (void)load

{

[UIViewController aspect_hookSelector:@selector(viewWillAppear:)

withOptions:AspectPositionAfter

usingBlock:^(id aspectInfo) {

NSString *className = NSStringFromClass([[aspectInfo instance] class]);

DebugLog(@"%@ class tpo appear",className);

} error:NULL];

[UIViewController aspect_hookSelector:@selector(viewWillDisappear:)

withOptions:AspectPositionAfter

usingBlock:^(id aspectInfo) {

NSString *className = NSStringFromClass([[aspectInfo instance] class]);

DebugLog(@"%@ class tpo disappear",className);

} error:NULL];

}

判断子线程UI刷新

+(void)load{

#if DEBUG

[UIView aspect_hookSelector:@selector(setNeedsLayout)

withOptions:AspectPositionAfter

usingBlock:^(id aspectInfo) {

NSString *className = NSStringFromClass([[aspectInfo instance] class]);

className = [NSString stringWithFormat:@"%@ can't use in background",className];

NSAssert([NSThread isMainThread],className);

} error:NULL];

[UIView aspect_hookSelector:@selector(setNeedsDisplay)

withOptions:AspectPositionAfter

usingBlock:^(id aspectInfo) {

NSString *className = NSStringFromClass([[aspectInfo instance] class]);

className = [NSString stringWithFormat:@"%@ can't use in background",className];

NSAssert([NSThread isMainThread],className);

} error:NULL];

[UIView aspect_hookSelector:@selector(setNeedsDisplayInRect:)

withOptions:AspectPositionAfter

usingBlock:^(id aspectInfo) {

NSString *className = NSStringFromClass([[aspectInfo instance] class]);

className = [NSString stringWithFormat:@"%@ can't use in background",className];

NSAssert([NSThread isMainThread],className);

} error:NULL];

#else

//不在release的时候添加是因为和jspatch有冲突

#endif

}

hotfix

其实热修复有很多方案,原理都是Method Swizzling,比较常见的选择方案是JSPatch,但是我觉得JSPatch和Aspects冲突引发崩溃的问题应该有JSPatch的作者bang来解决,不应该由开发者自己解决,虽然bang团队给出过解决方案。

爱生活,爱运动,热爱交流,欢迎讨论!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值