objc_runtime使用方法的几个简单例子

67 篇文章 0 订阅
17 篇文章 0 订阅

1. 给NSObject类动态添加属性

h定义部分
@interface UIWebView (LoadProgress)

@property (nonatomic, assign) NSInteger resourceCount;

@end

m实现部分

首先要定义一个全局的key

// resourceCount object keys
static void *s_resourceCountKey = &s_resourceCountKey;
//static void *s_resourceCountKey = "s_resourceCountKey";

初始
@implementation UIWebView (LoadProgress)
@dynamic resourceCount;

实现
#pragma mark Accessors and mutators

- (NSInteger)resourceCount
{
    NSNumber *resourceCountNumber = objc_getAssociatedObject(self, s_resourceCountKey);
    if (! resourceCountNumber)
    {
        return 0;
    }
    else
    {
        return [resourceCountNumber integerValue];
    }
}

- (void)setResourceCount:(NSInteger)rCount
{
    objc_setAssociatedObject(self, s_resourceCountKey, [NSNumber numberWithInteger:rCount], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

这样就可以直接使用了

webView.resourceCount = 10;



2. 给NSObject类动态添加代理protocol

同属性

动态创建代理暂时先不写了


3. 替换或变更NSObject类方法Method

基本替换方法

// 替换类方法
// frome: CoconutKit
IMP HLSSwizzleClassSelector(Class clazz, SEL selector, IMP newImplementation)
{
    // Get the original implementation we are replacing
    Class metaClass = objc_getMetaClass(class_getName(clazz));
    Method method = class_getClassMethod(metaClass, selector);
    IMP origImp = method_getImplementation(method);
    if (! origImp) {
        return NULL;
    }
    
    class_replaceMethod(metaClass, selector, newImplementation, method_getTypeEncoding(method));
    return origImp;
}

// 替换实例方法
IMP HLSSwizzleSelector(Class clazz, SEL selector, IMP newImplementation)
{
    // Get the original implementation we are replacing
    Method method = class_getInstanceMethod(clazz, selector);
    IMP origImp = method_getImplementation(method);
    if (! origImp) {
        return NULL;
    }
    
    class_replaceMethod(clazz, selector, newImplementation, method_getTypeEncoding(method));
    return origImp;
}

新方法定义

// Original implementation of the methods we swizzle
static id (*s_UIWebView__identifierForInitialRequest_Imp)(id, SEL, id, id, id) = NULL;

// Swizzled method implementations
static id swizzled_UIWebView__identifierForInitialRequest_Imp(UIWebView *self, SEL _cmd, id webView, id initialRequest, id dataSource);

方法初始化需要写在类方法+ (void)load中
+ (void)load
{
    s_UIWebView__identifierForInitialRequest_Imp = (id (*)(id, SEL, id, id, id))HLSSwizzleSelector(self, @selector(webView:identifierForInitialRequest:fromDataSource:), (IMP)swizzled_UIWebView__identifierForInitialRequest_Imp);
}

实现部分
#pragma mark Swizzled method implementations

static id swizzled_UIWebView__identifierForInitialRequest_Imp(UIWebView *self, SEL _cmd, id webView, id initialRequest, id dataSource)
{
    // 调用原方法
    (*s_UIWebView__identifierForInitialRequest_Imp)(self, _cmd, webView, initialRequest, dataSource);
    
    [self setResourceCount:self.resourceCount+1];
    
    return [NSNumber numberWithInteger:self.resourceCount];
}


4. 代理方法检索

可直接定义到NSObject的Category中
// [self implementsProtocol:@protocol(UIActionSheetDelegate)]
// frome: CoconutKit
- (BOOL)implementsProtocol:(Protocol *)protocol
{
    // Only interested in optional methods. Required methods are checked at compilation time
    unsigned int numberOfMethods = 0;
    struct objc_method_description *methodDescriptions = protocol_copyMethodDescriptionList(protocol, NO /* optional only */, YES, &numberOfMethods);
    for (unsigned int i = 0; i < numberOfMethods; ++i) {
        struct objc_method_description methodDescription = methodDescriptions[i];
        SEL selector = methodDescription.name;
        if (! class_getInstanceMethod([self class], selector)) {
            NSString *selectorString = [NSString stringWithCString:sel_getName(selector) encoding:NSUTF8StringEncoding];
            NSString *protocolName = [NSString stringWithCString:protocol_getName(protocol) encoding:NSUTF8StringEncoding];
            HLSLoggerInfo(@"Class %@ does not implement method %@ of protocol %@", [self className], selectorString, protocolName);
            selectorString = nil;               // Just to remove unused variable warnings
            protocolName = nil;
            return NO;
        }
    }
    
    return YES;
}







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值