Geo*_*e L 0 objective-c uiviewcontroller swizzling ios
我正在关注这篇文章,以便更好地理解方法调配是如何工作的.我有我的主视图控制器(这是一个新项目),如下所示:
#import "GLViewController.h"
#import <objc/runtime.h>
@implementation UIViewController (Tracking)
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [UIViewController class];
SEL originalSelector = @selector(viewWillAppear:);
SEL swizzledSelector = @selector(xxx_viewWillAppear:);
Method originalMethod = class_getInstanceMethod(class, originalSelector);
Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
BOOL didAddMethod =
class_addMethod(class,
originalSelector,
method_getImplementation(swizzledMethod),
method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod(class,
swizzledSelector,
method_getImplementation(originalMethod),
method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
#pragma mark - Method Swizzling
- (void)xxx_viewWillAppear:(BOOL)animated {
[self xxx_viewWillAppear:animated];
NSLog(@"viewWillAppear: %@", self);
}
@end
@implementation GLViewController
-(void)viewWillAppear:(BOOL)animated
{
NSLog(@"glviewappear");
}
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
Run Code Online (Sandbox Code Playgroud)
如果我运行它,那么它会打印glviewappear,如果我删除
-(void)viewWillAppear:(BOOL)animated
{
NSLog(@"glviewappear");
}
Run Code Online (Sandbox Code Playgroud)
然后它打印 viewWillAppear: <GLViewController: 0x9d11a90>.我的项目需要能够触发这两种方法.有没有办法做到这一点?
有一个简单的原因.您没有调用UIViewController实现,因为您没有调用[super viewWillAppear:animated].
做就是了:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(@"glviewappear");
}
Run Code Online (Sandbox Code Playgroud)
Objective C类中的每个方法只不过是一个简单的函数,通过保存在调度表中的指针引用:键是选择器,它们的关联值是每个方法实现的指针(IMP).
当您调度时,您只需在调度表中交换两个指针,以交换引用的函数.由于调度表附加到类,因此只在执行它的类中发生调配,而不是在子类中.
在您的情况下,有3个不同的函数在起作用:UIViewController具有指向调度表中以下函数的指针.这些函数在运行时通过调配进行交换.
viewWillAppear:(现在指向xxx_viewWillAppear:实施)xxx_viewWillAppear:(现在指向viewWillAppear:实施)GLViewController有另一个指针,它自己的实现viewWillAppear:.
如果您不调用super,则不会访问UIViewController该类的调度表,因此您根本不会调用该实现.
当您删除viewWillAppear:方法时,显然它可以工作,因为超级实现会被自动调用.
| 归档时间: |
|
| 查看次数: |
427 次 |
| 最近记录: |