文章标题

关于runtime的 class_addMethod 和 method_exchangeImplementations方法

//
// UIBarButtonItem+Public.m
// RuntimeDemo
//
// Created by huokr on 2/27/14.
// Copyright (c) 2014 huokr. All rights reserved.
//

#import "UIBarButtonItem+Public.h"
#import <objc/runtime.h>

@implementation UIBarButtonItem (Public)
/**/


- (id)initWithCustomTitle:(NSString *)title
                    style:(UIBarButtonItemStyle)style
                   target:(id)target
                   action:(SEL)action
{
    ___start_log___

    self = [super init];

    if (self) {

        UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 44, 44)];
        CGRect frame = button.frame;

        if (title) {

            CGSize size = [title sizeWithFont:[UIFont boldSystemFontOfSize:16.0f]
                            constrainedToSize:CGSizeMake(MAXFLOAT, 16.0f)
                                lineBreakMode:(NSLineBreakByCharWrapping)];

            [button setTitle:title
                    forState:(UIControlStateNormal)];

            [button setTitleColor:[UIColor purpleColor]
                         forState:(UIControlStateNormal)];

            button.titleLabel.font = [UIFont systemFontOfSize:16.0f];

            if (size.width > 40) {

                frame.size.width = size.width + 10;
                button.frame = frame;
            }
        }

        button.backgroundColor = [UIColor clearColor];

        [button addTarget:target
                   action:action
         forControlEvents:(UIControlEventTouchUpInside)];

        self = [[UIBarButtonItem alloc] initWithCustomView:button];

    }

    return self;
}

+ (void)load
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        Class class = [self class];

//系统的原方法
// - (instancetype)initWithTitle:(NSString *)title style:(UIBarButtonItemStyle)style target:(id)target action:(SEL)action;

        SEL originalSelector = @selector(initWithTitle:style:target:action:);
        SEL swizzledSelector = @selector(initWithCustomTitle:style:target:action:);

        Method originalMethod =
        class_getInstanceMethod(class,
                                @selector(initWithTitle:style:target:action:));

        Method swizzledMethod =
        class_getInstanceMethod(class,
                                @selector(initWithCustomTitle:style:target:action:));

        //class_addMethod 参考 [这里写链接内容](http://longtimenoc.com/archives/ios%E5%9C%A8%E8%BF%90%E8%A1%8C%E6%97%B6%E4%B8%BA%E7%B1%BB%E6%B7%BB%E5%8A%A0%E6%96%B9%E6%B3%95)
        BOOL didAddMethod =
        class_addMethod(class,
                        originalSelector,
                        method_getImplementation(originalMethod),
                        method_getTypeEncoding(originalMethod));

        if (didAddMethod) {

            ___start_log___

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

        } else {

            //交换两个方法的实现!
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }

    });
}
/**/
@end

以上代码重载了load方法,其中利用oc 的 runtime机制把系统的initWithTitle:style:target:action:方法替换为自定义的initWithCustomTitle:style:target:action:
其中:
了解class_addMethod 参考 这里
本代码原作者地址:github

你可能感兴趣的:(Runtime)