【问题标题】:UIViewController method swizzling not workingUIViewController 方法 swizzling 不起作用
【发布时间】:2017-01-04 21:14:18
【问题描述】:

我正在使用 UIViewController 上的一个类别来调动 viewWillAppear: 跨多个 ViewControllers 的方法。

@implementation UIViewController (Tracking)

+(void)load
{
    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{
        Class class = [self class];

        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector = @selector(xx_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);
        }

    });
}

-(void)xx_viewWillAppear:(BOOL)animated
{
    [self xx_viewWillAppear:animated];

    NSLog(@"VC loaded");
}

@end

当我从 Storyboard 加载初始 VC 时,从不调用 swizzled 方法。只有在 VC 中的 viewWillAppear 方法被注释掉时才会调用它。但是,当我删除类别并将代码移动到单个 VC 中时,这两种方法都会被调用。

#import "ViewController.h"
#import "UIViewController+Tracking.h"

@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

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

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

viewWillAppear 如果要被 swizzled,是否可以在 VC 中实现 viewWillAppear?如果没有,如果我需要在 VC 的 viewWillAppear 中编写一些代码,我该如何处理?

【问题讨论】:

  • 只尝试method_exchangeImplementations,不要添加,因为该方法已经存在于您的扩展中。
  • 此外,您正在从基类中调整方法,在您的自定义类中覆盖它意味着您需要调用 super 才能执行调整后的方法
  • @Cristik 我正在使用一个类别,我没有继承 VC。
  • @interface ViewController () - 看来你是子类化
  • 正是我所说的 :) 你在 UIViewController 上混合了 viewWillAppear:,并覆盖了 ViewController 子类。您需要从子类中调用 super,这在 Apple 的 documentation 中也有说明。

标签: ios objective-c method-swizzling


【解决方案1】:

您需要从ViewController 调用viewWillAppear: 中的super,否则基类(UIViewController) 中的方法将不会执行,这就是您调配的方法。

viewWillAppear: 的以下版本应该会给您预期的结果:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多