Method Swizzling(iOS的hook机制)

为了安全起见,要为NSUserDefaults中的数据加密。但是在每个调用NSUserDefaults读写方法的位置,加入加密解密方法也太麻烦。所以想重写NSUserDefaults的读写方法,把加密解密方法内嵌其中,这样修改代码量会大大减小。

先贴上代码

#import <Foundation/Foundation.h>

@interface NSUserDefaults (Swizzle)

-(void)swizzleSetObject:(nullable id) value forKey:(nullable NSString *)defaultName;
-(nullable id)swizzleObjectForKey:(NSString *)defaultName;

@end

#import "NSUserDefaults+Swizzle.h"
#import "WFTTripleDES.h"
@implementation NSUserDefaults (Swizzle)

-(void)swizzleSetObject:(nullable id) value forKey:(nullable NSString *)defaultName
{
    if ([value isKindOfClass:[NSString class]]) {
        //加密后写入
        [self swizzleSetObject:[WFTTripleDES TripleDES:value encryptOrDecrypt:kCCEncrypt key:[NSString stringWithFormat:@"2016012031009%@",defaultName] ] forKey:defaultName];
    }else{
        [self swizzleSetObject:value forKey:defaultName];
    }
}

-(nullable id)swizzleObjectForKey:(NSString *)defaultName;
{
    //如果键值为空直接返回
    if (!defaultName) {
        return @"";
    }
    
    id  getObject = [self swizzleObjectForKey:defaultName];
    if ([getObject isKindOfClass:[NSString class]]) {
        //把结果解密
        return [WFTTripleDES TripleDES:getObject encryptOrDecrypt:kCCDecrypt key:[NSString stringWithFormat:@"2016012031009%@",defaultName]];
    }else{
        return getObject;
    }
}
@end

然后交换自定义方法和系统方法

   Method originalMethod = class_getInstanceMethod([NSUserDefaults class],  @selector(setObject:forKey:));
    Method swizzledMethod = class_getInstanceMethod([NSUserDefaults class], @selector(swizzleSetObject:forKey:));
    method_exchangeImplementations(originalMethod, swizzledMethod);


Method Swizzling 原理


在Objective-C中调用一个方法,其实是向一个对象发送消息,查找消息的唯一依据是selector的名字。利用Objective-C的动态特性,可以实现在运行时偷换selector对应的方法实现,达到给方法挂钩的目的。

每个类都有一个方法列表,存放着selector的名字和方法实现的映射关系。IMP有点类似函数指针,指向具体的Method实现。


我们可以利用 method_exchangeImplementations 来交换2个方法中的IMP,



上面的代码实现


然后调用method_exchangeImplementations方法交换后变成


所以调用setObject:forKey:方法时,其实调用的是swizzleSetObject:forKey:的实现。而调用swizzleSetObject:forKey:方法时,调用的系统的setObject:forKey:的实现。

如果在swizzleSetObject:forKey:实现方法中,调用setObject:forKey:方法,其实会回调swizzleSetObject:forKey:。



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值