iOS - Method Swizzling
程序员文章站
2024-03-21 23:49:22
...
Method Swizzling 通过改变特定 selector(方法)与实际实现之间的映射,在 runtime 时将一个方法的实现替换成其它方法的实现。
用途:替换UIViewController的viewWillAppear方法,用于观察项目结构。
Objective-C
//
// UIViewController+Swizzling.m
// SwizzlingDemo
//
// Created by Shile on 16/3/25.
// Copyright © 2017年 Shile. All rights reserved.
//
#import "UIViewController+Swizzling.h"
#import <objc/runtime.h>
@implementation UIViewController (Swizzling)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [self class];
SEL originalSelector = @selector(viewWillAppear:);
SEL swizzledSelector = @selector(swizzledViewWillAppear:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddedMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
NSLog(@"%@",aaa@qq.com"YES":@"NO");
if (didAddedMethod) {
class_replaceMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
}else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
- (void)swizzledViewWillAppear:(BOOL)animated {
[self swizzledViewWillAppear:animated];
NSLog(@"View Controller: %@ ViewWillAppear %@", NSStringFromClass([self class]), aaa@qq.com"YES":@"NO");
}
@end
Swift
Swift 2.3
//MARK: - Shile Test -
extension UIViewController {
public override static func initialize () {
struct Static {
static var token:dispatch_once_t = 0
}
if self != UIViewController.self {
return
}
dispatch_once(&Static.token) {
let originalSelector = Selector("viewWillAppear:")
let swizzledSelector = Selector("newViewWillAppear:")
let originalMethod = class_getInstanceMethod(self, originalSelector)
let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
let didAddMthod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
if didAddMthod {
class_replaceMethod(self, swizzledSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
}
func newViewWillAppear(animated: Bool) {
self.newViewWillAppear(animated)
if let name = self.title {
print("\n \n shile viewWillAppear:\(name) \(self)\n \n ")
} else {
print("\n \n shile viewWillAppear:\(self) \n \n ")
}
}
}
Swift 3
extension UIViewController {
open override static func initialize() {
struct Static {
static var token = NSUUID().uuidString
}
if self != UIViewController.self {
return
}
DispatchQueue.once(token: Static.token) {
let originalSelector = #selector(UIViewController.viewWillAppear(_:))
let swizzledSelector = #selector(UIViewController.xl_viewWillAppear(animated:))
let originalMethod = class_getInstanceMethod(self, originalSelector)
let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)
//在进行 Swizzling 的时候,需要用 class_addMethod 先进行判断一下原有类中是否有要替换方法的实现
let didAddMethod: Bool = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
//如果 class_addMethod 返回 yes,说明当前类中没有要替换方法的实现,所以需要在父类中查找,这时候就用到 method_getImplemetation 去获取 class_getInstanceMethod 里面的方法实现,然后再进行 class_replaceMethod 来实现 Swizzing
if didAddMethod {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
}
func xl_viewWillAppear(animated: Bool) {
self.xl_viewWillAppear(animated: animated)
print("xl_viewWillAppear in swizzleMethod")
}
}
extension DispatchQueue {
private static var onceTracker = [String]()
open class func once(token: String, block:() -> Void) {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
if onceTracker.contains(token) {
return
}
onceTracker.append(token)
block()
}
}
上一篇: python实现从excel读取数据进行批量get请求
下一篇: 测试开发进阶(四十一)
推荐阅读
-
华山论剑之浅谈iOS中的百变金刚---ReactiveCocoa
-
Cordova配置IOS企业版热更新IVersion插件
-
华山论剑之浅谈iOS的Touch ID验证
-
华山论剑之浅谈iOS的屏幕适配(AutoLayout与Masonry)
-
iOS 开发:『Runtime』详解(二)Method Swizzling
-
iOS热更新、热修复方案
-
iOS - Method Swizzling
-
iOS开发SDK(.framework静态库,.bundle资源文件,脚本打包SDK和.bundle)
-
iOS学习之自定义弹出UIPickerView或UIDatePicker(动画效果)
-
即拿即用-仿IOS风格的弹出框和对话框