参考文章
http://www.cocoachina.com/applenews/devnews/2014/0225/7880.html
Method swizzling指的是改变一个已存在的选择器对应的实现的过程,它依赖于Objectvie-C中方法的调用能够在运行时进改变——通过改变类的调度表(dispatch table)中选择器到最终函数间的映射关系。
举个例子,假设我们想跟踪在一个iOS应用中每个视图控制器展现给用户的次数:
我们可以给每个视图控制器对应的viewWillAppear:实现方法中增加相应的跟踪代码,但是这样做会产生大量重复的代码。子类化可能是另一个选择,但要求你将UIViewController、 UITableViewController、 UINavigationController 以及所有其他视图控制器类都子类化,这也会导致代码重复。
这时我们可以使用method swizzling
使用category也可以达到相同的效果
category(类别)。category可以对类进行扩展。当类别中的方法与原始方法名冲突时,类别具有更高的优先级,即会完全取代原始方法。
可以使用类别进行方法替换
上代码,找到一个既有的工程,将下面代码加入工程中,当绘制界面的时候(viewDidLoad),就会调用sdh_swizzlingMethod方法
//
// SwizzlingMethod.h
//
// Created by songdh on 14-3-20.
// Copyright (c) 2014年 xxxx. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface SwizzlingMethod : NSObject
@end
@interface UIViewController(package)
@end
//
// SwizzlingMethod.m
//
// Created by songdh on 14-3-20.
// Copyright (c) 2014年 xxx. All rights reserved.
//
#import "SwizzlingMethod.h"
#import <objc/runtime.h>
SEL originalSelector;
@implementation SwizzlingMethod
//originalSelector:被替换掉的方法
//origClass:originalSelector所在的类
//返回值:修改名字后的原始方法。
//使用时,若原始方法中包含有处理方法,那么将其替换后就会出错,可以在newSelector方法中调用replaceSelector的返回值方法。
+ (SEL)replaceSelector:(SEL)originalSelector OrigClass:(Class)origClass NewSelector:(SEL)newSelector NewClass:(Class)newClass
{
Method originMethod = class_getInstanceMethod(origClass, originalSelector);
IMP originImplementation = method_getImplementation(originMethod);
const char *methodTypeEncoding = method_getTypeEncoding(originMethod);
IMP newImplementation = [newClass instanceMethodForSelector:newSelector];
NSString *selectorName = [NSString stringWithFormat:@"%@_%@", NSStringFromClass(origClass), NSStringFromSelector(originalSelector)];
if (class_addMethod(origClass, NSSelectorFromString(selectorName), originImplementation, methodTypeEncoding)) {
method_setImplementation(originMethod, newImplementation);
}
return NSSelectorFromString(selectorName);
}
+(void)load
{
originalSelector = [SwizzlingMethod replaceSelector:@selector(viewDidLoad) OrigClass:[UIViewController class] NewSelector:@selector(sdh_swizzlingMethod) NewClass:[self class]];
}
- (void)sdh_swizzlingMethod
{
[self performSelector:originalSelector withObject:nil];
NSLog(@"%s",__FUNCTION__);
}
@end
@implementation UIViewController(package)
- (void)viewDidLoad
{
NSLog(@"%s",__FUNCTION__);
}
@end
我创建了一个QQ群,希望大家能本着互联网开放的心态,将遇到的问题和经验在群里分享,大家互相交流心得,共同提高。
群号:77311380