• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

iOS-在子类调用父类私有方法

武飞扬头像
liudongshizhang
帮助1

https://www.jianshu.com/p/6171e6ec78a3
三方中在.h中声明的方法比较好重写,直接在子类里重写方法,如果需要重调父类原有方法可以用super直接调用。而一些私有方法并没有在.h中声明,这时我们也可以直接重写父类方法,但是相对于想要重调父类方法,就不能用super直接调用来实现。这里super只是一个编译器修饰符,是一个指向父类标志,并不是对象的父类实例。所以你再用super调用父类的私有方法是没有作用的。这时我们有几种选择可以帮我们实现父类私有方法的调用。

首先可以用Method Swizzling(方法交换)来帮我们实现,但是此方法会引起全局的方法指针交换,多人开发中如果没有交流好很容易出现一些纰漏等问题

第二种方法是我们可以利用runtime的消息发送机制,为我们的对象调用其父类的私有方法。主要用到objc_msgSendSuper方法,但是直接调用是不安全的,因为你不能确定父类是否含有这个方法,所以在调用之前需要判断父类是否含有此方法,举个例子,代码如下:

#import "Parent.h"

@implementation Parent

- (void)say {
    NSLog(@"我是父类的私有方法say");
}

@end
#import "Children.h"
#import <objc/message.h>

@implementation Children

- (void)say {
    if ([self containsSuperMethod:@"say"]) {
        struct objc_super super_obj;
        super_obj.receiver = self;
        super_obj.super_class = [Parent class];
        void (*say)(void *, SEL) = (void *)objc_msgSendSuper;
        say(&super_obj, sel_registerName("say"));
    }
}

- (BOOL)containsSuperMethod:(NSString *)methodName {
    unsigned int outCount = 0;
    Method *methods = class_copyMethodList([Parent class], &outCount);
    for (int i = 0; i < outCount; i  ) {
        Method method = methods[i];
        SEL methodNameSEL = method_getName(method);
        if ([methodName isEqualToString:NSStringFromSelector(methodNameSEL)]) {
            free(methods);
            return YES;
        }
    }
    free(methods);
    return NO;
}

学新通

这个方法是利用遍历父类中的所有方法来判断是否包含某一方法,这样做其实也有一定的弊端,比如当这个父类方法很多时,而你又需要频繁调用此方法时就会引起不必要的消耗。如果父类包含此方法就直接利用objc_msgSendSuper发送消息就可以了,需要声明#import <objc/message.h>

第三种是先获取父类方法,然后利用构建的方式来调用。判断父类是否包含此方法是根据构建出来的方法是否存在来判断的,相比于上一个方法减少了遍历的过程。例子代码如下:

- (void)say {
    Method method = class_getInstanceMethod([Parent class], sel_registerName("say"));
    void (*super_func)(id,SEL) = (void *)method_getImplementation(method);
    if (super_func){
        super_func(self, sel_registerName("say"));
    }
}

if (super_func) 是判断父类是否包含的此方法,如果含有此方法则调用,否则不调用。

参考:https://www.jianshu.com/p/6171e6ec78a3
https://www.cnblogs.com/zbblog/p/12333073.html

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhgcbcjc
系列文章
更多 icon
同类精品
更多 icon
继续加载