iOS黑魔法之Method Swizzling

此黑魔法本应属于OC,它是基于Runtime实现的偷天换日大法。

那么什么是Method Swizzling呢?从字面意思来看叫方法协调,大概就是这个意思了。使用此魔法可以替换现有方法为自定义方法,来个偷天换日,偷梁换柱。

使用方法很简单,代码基本为以下框架。但其具有较强的魔力,这是一个方法hook啊。

/**
 *  Method Swizzling
 *  黑魔法之偷天换日
 */
#import "UIViewController+Extension.h"
#import <objc/runtime.h>

@implementation UIViewController (Extension)

// 为了保证一定执行 把代码放到+ (void)load;里
+ (void)load {
    [super load];
    // 线程安全 只执行一次
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        // 获取class
        Class class = [self class];
//        Class class = object_getClass((id)self);
        // 封装selector
        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector = @selector(lw_viewWillAppear:);
        // 封装方法
        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
        // 添加方法
        BOOL methodDidAdd = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
        if(methodDidAdd) {
            // 替换方法
            class_replaceMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
        }else {
            // 交换方法
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

#pragma mark - 自定义的魔法方法
- (void)lw_viewWillAppear:(BOOL)animated {
    [self lw_viewWillAppear:animated];
    NSLog(@"BLack Magic");
}

注意:

1 + (void)load;

2 dispatch_once;

3 [self lw_viewWillAppear:animated]; // 不回死循环 若为[self viewWillAppear:animated];死循环

时间: 2024-11-07 04:44:40

iOS黑魔法之Method Swizzling的相关文章

iOS黑魔法-Method Swizzling

公司年底要在新年前发一个版本,最近一直很忙,好久没有更新博客了.正好现在新版本开发的差不多了,抽空总结一下.由于最近开发新版本,就避免不了在开发和调试过程中引起崩溃,以及诱发一些之前的bug导致的崩溃.而且项目比较大也很不好排查,正好想起之前研究过的Method Swizzling,考虑是否能用这个苹果的“黑魔法”解决问题,当然用好这个黑魔法并不局限于解决这些问题...... 需求 就拿我们公司项目来说吧,我们公司是做导航的,而且项目规模比较大,各个控制器功能都已经实现.突然有一天老大过来,说我

iOS开发之 Method Swizzling 深入浅出

<p align="center"><img src ="https://raw.githubusercontent.com/DotzuX/Notes/master/logo.jpeg"/></p> iOS开发之 Method Swizzling 深入浅出 只要善用Google,网上有很多关于Method Swizzling的Demo,在这里我就不打算贴代码了,主要介绍下概念,原理,注意事项等等. 开发需求 如果产品经理突然说:&

iOS运行时与method swizzling

C语言是静态语言,它的工作方式是通过函数调用,这样在编译时我们就已经确定程序如何运行的.而Objective-C是动态语言,它并非通过调用类的方法来执行功能,而是给对象发送消息,对象在接收到消息之后会去找匹配的方法来运行.这种做法就把C语言在编译时的工作挪到了运行时来做,可以获得额外的灵活性. 在Objective-C中有个@selector,在很多地方被翻译成"选择子".实际上,对于类的实例对象来说,类的方法是用一个数字来代表的,并非是我们看到的一个长长的带着:这个字符的一串字符串.

iOS 开发:Method Swizzling

iOS 开发之Method Swizzling 前言 如果你还不知道什么是Method Swizzling,你可以看看NSHipster 的文章 ,我简单介绍一下,method swizzling 可以看成劫持了一个方法. 我们可以看看NSHipster 的文章中有以下代码: - (void)xxx_viewWillAppear:(BOOL)animated { [self xxx_viewWillAppear:animated]; NSLog(@"viewWillAppear: %@"

iOS执行时与method swizzling

C语言是静态语言,它的工作方式是通过函数调用,这样在编译时我们就已经确定程序怎样执行的.而Objective-C是动态语言,它并不是通过调用类的方法来执行功能,而是给对象发送消息,对象在接收到消息之后会去找匹配的方法来执行.这样的做法就把C语言在编译时的工作挪到了执行时来做,能够获得额外的灵活性. 在Objective-C中有个@selector,在非常多地方被翻译成"选择子".实际上,对于类的实例对象来说,类的方法是用一个数字来代表的,并不是是我们看到的一个长长的带着:这个字符的一串

iOS runtime探究(四): 从runtiem开始实践Category添加属性与黑魔法method swizzling

你要知道的runtime都在这里 转载请注明出处 http://blog.csdn.net/u014205968/article/details/67639335 本文主要讲解runtime相关知识,从原理到实践,由于包含内容过多分为以下五篇文章详细讲解,可自行选择需要了解的方向: 从runtime开始: 理解面向对象的类到面向过程的结构体 从runtime开始: 深入理解OC消息转发机制 从runtime开始: 理解OC的属性property 从runtime开始: 实践Category添加属

ios method swizzling

阅读器 iOS开发iOS 本文由TracyYih[博客]翻译自NSHipster的文章Method Swizzling. 在上周associated objects一文中,我们开始探索Objective-C运行时的一些黑魔法.本周我们继续前行,来讨论可能是最受争议的运行时技术:method swizzling. Method swizzling指的是改变一个已存在的选择器对应的实现的过程,它依赖于Objectvie-C中方法的调用能够在运行时进改变——通过改变类的调度表(dispatch tab

iOS中AOP与Method Swizzling 项目中的应用

引子:项目中需要对按钮点击事件进行统计分析,现在项目中就是在按钮的响应代码中添加点击事件,非常繁琐.所以使用了AOP(面向切面编程),将统计的业务逻辑统一抽离出来. 项目中添加的开源库:https://github.com/steipete/Aspects Method Swizzling 利用runtime交换了函数 SEL A,IMP A 与 SEL  B,IMP B,这一黑魔法使得抽离业务逻辑变的可能. 更多资料可以参考:http://www.cocoachina.com/ios/2015

iOS 使用Method Swizzling隐藏Status Bar

在iOS 6中,隐藏Status Bar非常的简单. // iOS 6及以前,隐藏状态栏 [[UIApplication sharedApplication] setStatusBarHidden:YES]; 来到了iOS 7的年代以后,需要在UIViewController中指定: #ifdef __IPHONE_7_0 - (BOOL)prefersStatusBarHidden { return YES; } #endif 并通过下列代码刷新状态栏: if ([viewController