ios swizzle更好理解
ios swizzle better understanding
我有一个带有此代码的 UIViewController:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(@"CLASIC");
}
然后我有一个带有 UIViewController 类别的框架,它以这种方式调配:
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL viewWillAppearSelector = @selector(viewDidAppear:);
SEL viewWillAppearLoggerSelector = @selector(logged_viewDidAppear:);
Method originalMethod = class_getInstanceMethod(self, viewWillAppearSelector);
Method extendedMethod = class_getInstanceMethod(self, viewWillAppearLoggerSelector);
method_exchangeImplementations(originalMethod, extendedMethod);
});
}
- (void)logged_viewDidAppear:(BOOL)animated
{
[self logged_viewDidAppear:animated];
NSLog(@"SWIZZLED");
}
输出是 SWIZZLED,然后是 CLASIC。
现在我的问题是:如果在我的 viewcontroller 我评论 [super viewDidAppear:animated];然后 swizzled 方法不再被调用;这是为什么?我了解了大部分方面,但似乎这一方面不知何故滑落了。
- (void)viewDidAppear:(BOOL)animated
{
// we comment this and this will trigger the swizzled method not being called anymore
//[super viewDidAppear:animated];
NSLog(@"CLASIC");
}
// ========================
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL viewWillAppearSelector = @selector(viewDidAppear:);
SEL viewWillAppearLoggerSelector = @selector(logged_viewDidAppear:);
Method originalMethod = class_getInstanceMethod(self, viewWillAppearSelector);
Method extendedMethod = class_getInstanceMethod(self, viewWillAppearLoggerSelector);
method_exchangeImplementations(originalMethod, extendedMethod);
});
}
- (void)logged_viewDidAppear:(BOOL)animated
{
[self logged_viewDidAppear:animated];
NSLog(@"SWIZZLED");
}
方法调配用于在运行时用自定义方法覆盖原始方法。因此,您几乎可以将任何方法(包括私有苹果实现的方法)与您编写的自定义方法进行交换。
所以想象有一个名为 Parent
的 class 和一个名为 A
的方法,你在它被调用之前的某个地方与 B
交换它,就像在 load
方法。从现在开始,每个子 class 关闭 'Parent' 将使用 B
除了原来的 'A' 方法。但是,如果您在子 class 中覆盖 A
怎么办?作为继承定义,对象将调用它们的自己的方法,如果它们没有实现它,它们将使用它们的suprclass的方法.那么,如果您想要 parent implementation
怎么办?这就是 super
的用武之地。
结论
- 如果重写方法,super class(或 superclass 中的自定义交换方法)方法将不会被调用
- 如果你想要父实现,你必须使用 super 关键字来访问它
在这个问题的案例中:
- 覆盖子 class 中的方法而不 调用 super 意味着您只是覆盖 swizzled 方法,它不会被调用。
希望对您有所帮助
我有一个带有此代码的 UIViewController:
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
NSLog(@"CLASIC");
}
然后我有一个带有 UIViewController 类别的框架,它以这种方式调配:
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL viewWillAppearSelector = @selector(viewDidAppear:);
SEL viewWillAppearLoggerSelector = @selector(logged_viewDidAppear:);
Method originalMethod = class_getInstanceMethod(self, viewWillAppearSelector);
Method extendedMethod = class_getInstanceMethod(self, viewWillAppearLoggerSelector);
method_exchangeImplementations(originalMethod, extendedMethod);
});
}
- (void)logged_viewDidAppear:(BOOL)animated
{
[self logged_viewDidAppear:animated];
NSLog(@"SWIZZLED");
}
输出是 SWIZZLED,然后是 CLASIC。
现在我的问题是:如果在我的 viewcontroller 我评论 [super viewDidAppear:animated];然后 swizzled 方法不再被调用;这是为什么?我了解了大部分方面,但似乎这一方面不知何故滑落了。
- (void)viewDidAppear:(BOOL)animated
{
// we comment this and this will trigger the swizzled method not being called anymore
//[super viewDidAppear:animated];
NSLog(@"CLASIC");
}
// ========================
+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
SEL viewWillAppearSelector = @selector(viewDidAppear:);
SEL viewWillAppearLoggerSelector = @selector(logged_viewDidAppear:);
Method originalMethod = class_getInstanceMethod(self, viewWillAppearSelector);
Method extendedMethod = class_getInstanceMethod(self, viewWillAppearLoggerSelector);
method_exchangeImplementations(originalMethod, extendedMethod);
});
}
- (void)logged_viewDidAppear:(BOOL)animated
{
[self logged_viewDidAppear:animated];
NSLog(@"SWIZZLED");
}
方法调配用于在运行时用自定义方法覆盖原始方法。因此,您几乎可以将任何方法(包括私有苹果实现的方法)与您编写的自定义方法进行交换。
所以想象有一个名为 Parent
的 class 和一个名为 A
的方法,你在它被调用之前的某个地方与 B
交换它,就像在 load
方法。从现在开始,每个子 class 关闭 'Parent' 将使用 B
除了原来的 'A' 方法。但是,如果您在子 class 中覆盖 A
怎么办?作为继承定义,对象将调用它们的自己的方法,如果它们没有实现它,它们将使用它们的suprclass的方法.那么,如果您想要 parent implementation
怎么办?这就是 super
的用武之地。
结论
- 如果重写方法,super class(或 superclass 中的自定义交换方法)方法将不会被调用
- 如果你想要父实现,你必须使用 super 关键字来访问它
在这个问题的案例中:
- 覆盖子 class 中的方法而不 调用 super 意味着您只是覆盖 swizzled 方法,它不会被调用。
希望对您有所帮助