修改系统方法生命周期

来源:互联网 发布:白银td知乎 编辑:程序博客网 时间:2024/05/18 02:23

参考文章

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

0 0