• objc_runtime使用方法的几个简单例子(转)


    1. 给NSObject类动态添加属性
    h定义部分

    [cpp] 
    @interface UIWebView (LoadProgress) 
     
    @property (nonatomic, assign) NSInteger resourceCount; 
     
    @end 

    @interface UIWebView (LoadProgress)

    @property (nonatomic, assign) NSInteger resourceCount;

    @end

    m实现部分

    首先要定义一个全局的key

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

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

    [cpp]
    @implementation UIWebView (LoadProgress) 
    @dynamic resourceCount; 

    @implementation UIWebView (LoadProgress)
    @dynamic resourceCount;
    实现
    [cpp]
    #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); 

    #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
    基本替换方法


    [cpp]
    // 替换类方法  
    // 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; 

    // 替换类方法
    // 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;
    }


    新方法定义


    [cpp]
    // 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); 

    // 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中

    [cpp] 
    + (void)load 

        s_UIWebView__identifierForInitialRequest_Imp = (id (*)(id, SEL, id, id, id))HLSSwizzleSelector(self, @selector(webView:identifierForInitialRequest:fromDataSource:), (IMP)swizzled_UIWebView__identifierForInitialRequest_Imp); 

    + (void)load
    {
        s_UIWebView__identifierForInitialRequest_Imp = (id (*)(id, SEL, id, id, id))HLSSwizzleSelector(self, @selector(webView:identifierForInitialRequest:fromDataSource:), (IMP)swizzled_UIWebView__identifierForInitialRequest_Imp);
    }
    实现部分

    [cpp] 
    #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]; 

    #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中
    [cpp]
    // [self implementsProtocol:@protocol(UIActionSheetDelegate)] 

    // [self implementsProtocol:@protocol(UIActionSheetDelegate)][cpp] view plaincopyprint?
    // 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; 

    // 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;
    }

    http://www.2cto.com/kf/201304/204393.html 

  • 相关阅读:
    javascript 版的 MD5
    一个通用的动态加载数据例子(IE5,NS6,Mozilla 1.3b)
    javascript 版的 MD4
    javascript 版的 sha1
    用dhtml做了一个密码管理器
    java版本的escape和unescape函数
    java版的MD5
    vue:app.vue中添加监听beforeunload事件,即当浏览器窗口关闭或刷新时删除vuex中的数据
    vue设置全局样式:loadOptions
    内网穿透frp
  • 原文地址:https://www.cnblogs.com/xiaoxiaoyublogs/p/5446214.html
Copyright © 2020-2023  润新知