gpt4 book ai didi

ios - 方法 Swizzling 未正确触发?

转载 作者:行者123 更新时间:2023-11-28 18:33:22 25 4
gpt4 key购买 nike

我正在关注这个 article更好地理解方法调配的工作原理。我有这样的主视图 Controller (这是一个新项目):

#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

如果我运行它,它会打印 glviewappear,如果我删除

-(void)viewWillAppear:(BOOL)animated
{
NSLog(@"glviewappear");
}

然后打印viewWillAppear: <GLViewController: 0x9d11a90> .我的项目需要能够使用这两种方法。有办法做到这一点吗?

最佳答案

原因很简单。您没有调用 UIViewController 实现,因为您没有调用 [super viewWillAppear:animated]

只是做:

-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(@"glviewappear");
}

这里有更详细的解释

Objective C 类中的每个方法只不过是一个简单的函数,通过保存在调度表中的指针引用:键是选择器,它们关联的值是指向每个方法实现的指针( IMP).

当你调配时,你只是交换调度表中的两个指针,以交换引用的函数。由于调度表附加到类,因此调配发生在您执行它的类中,而不发生在子类中。

在您的例子中,有 3 个不同的函数在起作用:UIViewController 在调度表中有指向以下函数的指针。这些函数在运行时通过 swizzling 进行交换。

  • viewWillAppear:(现在指向 xxx_viewWillAppear: 实现)
  • xxx_viewWillAppear:(现在指向 viewWillAppear: 实现)

GLViewController 有另一个指针,指向它自己的 viewWillAppear: 实现。

如果你不调用 super,你就不会访问 UIViewController 类的调度表,所以你根本不会调用实现。

当您删除 viewWillAppear: 方法时,显然它有效,因为 super 实现会自动调用。

关于ios - 方法 Swizzling 未正确触发?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23748573/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com