Objective-C 奇巧淫技--IMS

奇技淫巧 指过于奇巧而无益的技艺与制品.

IMS指的是 Instance Method Swizzling, 实例方法混淆.

下段代码是一个Instance Method Swizzling和一个Method Swizzling的例子:

// Man.m
- (void)run
{
    NSLog(@"%s, %@", __func__, _name);
}
- (void)jump
{
    NSLog(@"%s, %@", __func__, _name);
}
- (void)handsUp
{
    NSLog(@"%s, %@", __func__, _name);
}
- (void)handsDown
{
    NSLog(@"%s, %@", __func__, _name);
}

//  ViewController.m
- (void)viewDidLoad {
    ...
    Man *a = [Man manWithName:@"a"];
    Man *b = [Man manWithName:@"b"];

    [self swizzleInstanceMethodWithInstance:a originalSel:@selector(run) replacementSel:@selector(jump)];
    [self swizzleInstanceMethodWithClass:[Man class] originalSel:@selector(handsUp) replacementSel:@selector(handsDown)];

    [a run];
    [b run];

    [a handsUp];
    [b handsUp];
}

// 输出的结果是
2015-03-14 23:53:39.832 testRuntime[2196:629365] -[Man jump], a
2015-03-14 23:53:39.833 testRuntime[2196:629365] -[Man run], b
2015-03-14 23:53:39.833 testRuntime[2196:629365] -[Man handsDown], a
2015-03-14 23:53:39.833 testRuntime[2196:629365] -[Man handsDown], b

为什么run方法是只有对象a被替换了,handsUp方法是都被替换了呢?

我们先来看下普通的Method Swizzling是如何实现的

- (void)swizzleInstanceMethodWithClass:(Class)clazz originalSel:(SEL)original replacementSel:(SEL)replacement
{
    Method a = class_getInstanceMethod(clazz, original);
    Method b = class_getInstanceMethod(clazz, replacement);
    // class_addMethod 为该类增加一个新方法
    if (class_addMethod(clazz, original, method_getImplementation(b), method_getTypeEncoding(b)))
    {
        // 替换类方法的实现指针
        class_replaceMethod(clazz, replacement, method_getImplementation(a), method_getTypeEncoding(a));
    }
    else
    {
        // 交换2个方法的实现指针
        method_exchangeImplementations(a, b);
    }
}

Instance Method Swizzling是用了类似KVO的办法.

先动态添加一个类MySubclass继承自原来的类,然后修改对象a的isa为新类,再替换掉新类的方法.

- (void)swizzleInstanceMethodWithInstance:(id)object originalSel:(SEL)original replacementSel:(SEL)replacement
{
    Class newClass = objc_allocateClassPair([object class], "MySubclass", 0);
    objc_registerClassPair(newClass);

    Method a = class_getInstanceMethod(newClass, original);
    Method b = class_getInstanceMethod([object class], replacement);
    if (class_addMethod(newClass, original, method_getImplementation(b), method_getTypeEncoding(b)))
    {
        class_replaceMethod(newClass, replacement, method_getImplementation(a), method_getTypeEncoding(a));
    }
    else
    {
        method_exchangeImplementations(a, b);
    }

    object_setClass(object, newClass);
}
时间: 2024-08-10 14:02:54

Objective-C 奇巧淫技--IMS的相关文章

octave之奇巧淫技向量化计算实现寻找样本点所属聚类下标

前面有文章提到过,K-means算法,第一步骤是找出样本点的的所属聚类.下面用两种方式实现,一种是普通的循环,一种是完全向量化计算. 假设 : X 是m×n样本矩阵,其每一行是一个样本,m表示样本数目,n表示特征数目: centroids是K×n矩阵,K表示聚类数目,n表示特征数目,每一行是一个聚类的中心. idx是m×1矩阵,idx(i) 表示第i个样本所属的聚类下标.(取值范围 1..K ) 半循环半向量化方式 实现: 思想:循环遍历每一个样本点,计算每一个样本点距离K个聚类中心的值,并取最

iOS开发的一些奇巧淫技(转载)

iOS开发的一些奇巧淫技 http://www.cocoachina.com/ios/20141229/10783.html iOS开发的一些奇巧淫技2 http://www.cocoachina.com/ios/20141229/10801.html iOS开发的一些奇巧淫技3 http://www.cocoachina.com/ios/20150210/11130.html 2011斯坦福大学iOS应用开发视频教程笔记 http://blog.csdn.net/column/details/

Objective-C 奇巧淫技--delegate挂钩

Objective-C 奇巧淫技–delegate挂钩 奇技淫巧 指过于奇巧而无益的技艺与制品. 需求说明 在实际的编程过程中,我们总要定制一些控件,在定制的过程里,有时喜欢自己实现部分delegate方法 // MYScrollView.m - (instancetype)init { ... self.delegae = self; ... } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { NSLog(@"%s 我被执行&q

Objective-C 奇巧淫技--用汉语写Objective-C

奇技淫巧 指过于奇巧而无益的技艺与制品. 转载请注明出处 http://blog.csdn.net/uxyheaven/article/details/46391771 我们可以用宏定义基本的运算符和类型 #define 加 + #define 减 - #define 乘 * #define 除 / #define 大于 > #define 小于 < #define 对比 == #define 等于 = typedef NSInteger 整数型; typedef NSString 字符串型;

Objective-C 奇巧淫技--让对象伪装成一个字典

奇技淫巧 指过于奇巧而无益的技艺与制品. 转载请注明出处 uxyheaven csdn博客 其实这个技巧特定情况下,要求不高还挺是有用的. 我们原本有个接口1,设计的-.,为了灵活性嘛,就用了字典 - (void)method1:(NSDictionary *)dic { NSString *name = dic[@"name"]; NSLog(@"%s, name: %@",__FUNCTION__, name); } 等到我们水平提高了,发现代码应该这么写 @p

C基础 那些年用过的奇巧淫技

引言 - 为寻一颗明星 为要寻一颗明星 徐志摩 1924年12月1日<晨报六周年纪念增刊> 我骑著一匹拐腿的瞎马, 向著黑夜里加鞭:—— 向著黑夜里加鞭, 我跨著一匹拐腿的瞎马.// 我冲入这黑绵绵的昏夜, 为要寻一颗明星:—— 为要寻一颗明星, 我冲入这黑茫茫的荒野.// 累坏了,累坏了我胯下的牲口, 那明星还不出现:—— 那明星还不出现, 累坏了,累坏了马鞍上的身手.// 这回天上透出了水晶似的光明, 荒野里倒著一只牲口, 黑夜里躺著一具尸首.—— 这回天上透出了水晶似的光明!// { 风

iOS调试奇巧淫技(一)

你以为,你以为的就是你以为的吗? 你以为你代码写的很OK啦? 你以为你的是大牛啦? 你以为的就是你以为的吗? 你的代码经得起考验吗?(PS:爱经得起考验吗) iOS调试的技巧很多,通过调试我们不仅可以迅速找到Bug的所在,更能优化代码,让你的你以为不再是你以为! 一.断点 普通断点 当运行时遇到断点会停止下来供程序员调试 我们清晰的看到此时的i依旧等于0,该函数在一个名为ViewController中 上图中有五个可选按钮 分别是取消断点按钮.继续执行一步按钮.步入按钮.步出按钮 条件断点 点击

iOS开发的一些奇巧淫技

http://blog.csdn.net/Dwarven/article/details/42388711 TableView不显示没内容的Cell怎么办? 类似这种,我不想让下面那些空的显示. 很简单. [objc] view plaincopy self.tableView.tableFooterView = [[UIView alloc] init]; 试过的都说好. 加完这句之后就变成了这样.   自定义了leftBarbuttonItem左滑返回手势失效了怎么办? [objc] vie

iOS开发的一些奇巧淫技1&amp;2

转自:http://www.cocoachina.com/ios/20141231/10783.html TableView不显示没内容的Cell怎么办? 类似这种,我不想让下面那些空的显示. 很简单. 1 self.tableView.tableFooterView = [[UIView alloc] init]; 试过的都说好. 加完这句之后就变成了这样. 自定义了leftBarbuttonItem左滑返回手势失效了怎么办? 1 2 3 4 5 6     self.navigationIt