• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ios swizzle 更好理解

[复制链接]
菜鸟教程小白 发表于 2022-12-12 14:59:21 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

我有一个带有此代码的 UIViewController:

- (void)viewDidAppearBOOL)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_viewDidAppearBOOL)animated
{
    [self logged_viewDidAppear:animated];

    NSLog(@"SWIZZLED");
}

输出是 SWIZZLED,然后是 CLASIC。

现在我的问题是:如果在我的 View Controller 中我评论了 [super viewDidAppear:animated];然后不再调用 swizzled 方法;这是为什么?我理解了大部分方面,但似乎这一方面不知何故滑倒了。

- (void)viewDidAppearBOOL)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_viewDidAppearBOOL)animated
{
    [self logged_viewDidAppear:animated];

    NSLog(@"SWIZZLED");
}



Best Answer-推荐答案


方法调配用于在运行时用自定义方法覆盖原始方法。因此,您几乎可以将任何方法(包括私有(private)苹果实现的方法)与您编写的自定义方法进行交换。

所以想象有一个名为 Parent 的类有一个名为 A 的方法,然后你在某个地方与 B 交换它,然后像在里面一样调用它加载方法。从现在开始,'Parent' 之外的每个子类都将使用 B 除了原始的 'A' 方法。但是,如果您在子类中覆盖 A 怎么办?作为继承定义,对象将调用它们的自己的方法,如果它们没有实现它,它们会使用它们的父类(super class)的方法。那么如果你想要父实现呢?这就是 super 的用武之地。

结论

  • 如果你重写一个方法,父类(super class)(或父类(super class)中的自定义交换方法)方法将不会被调用
  • 如果你想要父实现,你必须使用 super 关键字来访问它

在这个问题的情况下:

  • 在不调用 super 的情况下覆盖子类中的方法意味着您只需覆盖 swizzled 的方法,它不会被调用。

希望对你有帮助

关于ios swizzle 更好理解,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53188675/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap