ParkLU开发使用IOS黑魔法

只有不停的总结才有成长
ParkLU 开发
               数据问题:(网络请求下的数据有坑,总是造成闪退)
                                    1.关键字Key存在有时候不存在
                                    2.关键字Key对应的value有时候有,有时候是“”、NULL、(null)或者干脆没有
               解决方式:
                                使用RUNTIME,在运行时通过修改类的分发表中selector对应的函数,来修改方法的实现。简单来讲就是自己写方法替换系统方法的实现。

Method Swizzling简单介绍:
Method Swizzling
是改变一个selector的实际实现的技术。通过这一技术,我们可以在运行时通过修改类的分发表中selector对应的函数,来修改方法的实现。

使用原因:

1.例如,我们想跟踪在程序中每一个view controller展示给用户的次数:当然,我们可以在每个viewcontrollerviewDidAppear中添加跟踪代码;但是这太过麻烦,需要在每个view controller中写重复的代码。创建一个子类可能是一种实现方式,但需要同时创建UIViewController, UITableViewController, UINavigationController及其它UIKitview controller的子类,这同样会产生许多重复的代码。

2.iOS系统方法总是有可能因为越界而让程序崩溃(crash),我们这时可以考虑自己写方法替换系统的方法了。
3.字典的key-value,如果有nil也是崩溃的

刨根问底ObjectiveCRuntimehttp://www.cocoachina.com/ios/20141224/10740.html

 MethodSwizzling

我们可以使用苹果的黑魔法Method SwizzlingMethod Swizzling本质上就是对IMPSEL进行交换。

MethodSwizzling原理

Method Swizzing是发生在运行时的,主要用于在运行时将两个Method进行交换,我们可以将Method Swizzling代码写到任何地方,但是只有在这段Method Swilzzling代码执行完毕之后互换才起作用。

而且Method Swizzling也是iOSAOP(面相切面编程)的一种实现方式,我们可以利用苹果这一特性来实现AOP编程。

ParkLU开发使用IOS黑魔法

UIViewController+Extension.m 是一个controller的扩展,程序一旦启动绘画页面,这个.m离开会立刻编译


针对字典崩溃处理实现理解:

图1:


ParkLU开发使用IOS黑魔法
 
图2:
ParkLU开发使用IOS黑魔法

MethodSwizzling类簇

在我们项目开发过程中,经常因为NSArray数组越界或者NSDictionarykey或者value值为nil等问题导致的崩溃,对于这些问题苹果并不会报一个警告,而是直接崩溃,感觉苹果这样确实有点太狠了

由此,我们可以根据上面所学,对NSArrayNSMutableArrayNSDictionaryNSMutableDictionary等类进行Method Swizzling,实现方式还是按照上面的例子来做。但是....你发现MethodSwizzling根本就不起作用,代码也没写错啊,到底是什么鬼?

这是因为Method SwizzlingNSArray这些的类簇是不起作用的。因为这些类簇类,其实是一种抽象工厂的设计模式。抽象工厂内部有很多其它继承自当前类的子类,抽象工厂类会根据不同情况,创建不同的抽象对象来进行使用。例如我们调用NSArrayobjectAtIndex:方法,这个类会在方法内部判断,内部创建不同抽象类进行操作。

所以也就是我们对NSArray类进行操作其实只是对父类进行了操作,在NSArray内部会创建其他子类来执行操作,真正执行操作的并不是NSArray自身,所以我们应该对其真身进行操作。

1.通过runtime函数获取真正的类:
1.NSString *className = [NSString stringWithFormat:@"%@", [[NSMutableDictionarydictionaryWithObjectsAndKeys:@"parklu_yanggfDEV"@"key"nilclass]];
2. 
char name[100];
 
  strcpy(name,(char *)[className UTF8String]);
3.
Class class = objc_getClass(name); 
这时class才是
NSMutableDictionary真正的类
(同理:
 NSString *className = [NSString stringWithFormat:@"%@", [[NSDictionarydictionaryWithObjectsAndKeys:@"parklu_yanggfDEV"@"key"nilclass]];NSString *className = [NSStringstringWithFormat:@"%@", [[NSMutableString stringWithFormat:@"parklu_yanggfDEV"class]];NSString *className = [NSStringstringWithFormat:@"%@", [@"parklu_yanggfDEV" class]]; NSString *className = [NSString stringWithFormat:@"%@", [[NSMutableArray arrayWithObjects:@"parklu_yanggfDEV"nilclass]];NSString *className = [NSStringstringWithFormat:@"%@", [[NSArray arrayWithObjects:@"parklu_yanggfDEV"nilclass]];)  

2.方法覆盖:

[self swizzleInstanceMethod:class originSelector:@selector(objectForKey:)otherSelector:@selector(safe_YGF_mutable_objectForKey:)];

[self swizzleInstanceMethod:class originSelector:@selector(valueForKey:)otherSelector:@selector(safe_YGF_mutable_valueForKey:)];

[self swizzleInstanceMethod:class originSelector:@selector(setObject:forKey:)otherSelector:@selector(safe_YGF_mutable_setObjectForKey:forKey:)];
[self swizzleInstanceMethod:class originSelector:@selector(setValue:forKey:)otherSelector:@selector(safe_YGF_mutable_setValueForKey:forKey:)]; 

3.实现自定义的方法:

ParkLU开发使用IOS黑魔法 

ParkLU开发使用IOS黑魔法

ParkLU开发使用IOS黑魔法 


其他:

NSDictionary
ParkLU开发使用IOS黑魔法 



ParkLU开发使用IOS黑魔法

ParkLU开发使用IOS黑魔法

NSMutableArray
ParkLU开发使用IOS黑魔法

ParkLU开发使用IOS黑魔法

ParkLU开发使用IOS黑魔法

介绍完毕