【问题标题】:Why the Objective-C cannot use 'self' object in protected function-pointer?为什么 Objective-C 不能在受保护的函数指针中使用“自我”对象?
【发布时间】:2019-01-11 08:01:23
【问题描述】:

我想在 Objective-C 中使用'protected',所以我写了FatherView 类和AView 类:

typedef NS_OPTIONS(NSInteger, DisplayViewT) {
    DisplayViewT_One ,
    DisplayViewT_Two ,
};

@interface FatherView : UIView{
@protected
    UIView *_test_one_view ;
    UIView *(*_testV_funcp_void)(DisplayViewT displayT) ;
}
@end

在FatherView类中,_testV_one_view属性是一个函数指针, 你可以看到FatherView的实现:

@interface FatherView()
@property (nonatomic , strong) UIView *test_two_view ;
@end

@implementation FatherView

- (id) init
{
    self = [super init] ;
    if( self ){
        self->_test_one_view = [[UIView alloc] init] ;
        self.test_two_view = [[UIView alloc] init] ;       
        self->_testV_funcp_void = (UIView *(*)(DisplayViewT))[self methodForSelector:@selector(test_func_testV:)] ;
    }
    return self ;
}
- (UIView *)test_func_testV:(DisplayViewT)displayT
{
    UIView *displayV = nil ;
    switch (displayT) {
        case DisplayViewT_One:{
            displayV = self->_test_one_view ;
        }
            break;
        case DisplayViewT_Two:
        default:{
                displayV = self.test_two_view ;
            }
            break;
    }
    return displayV ;
}
@end

AView 类是FatherView 类的子类:

@interface AView : FatherView
- (void)exc_teest ;
@end
@implementation AView
- (void)exc_test
{
    UIView *oneV = self->_testV_funcp_void(DisplayViewT_One) ;
    NSLog(@"%@",oneV) ;
}
@end

问题: AView 有一个方法,该方法的名称是 exc_test , 我调用方法(exc_test)。

但是 Xcode 打印结果:null !

为什么? AView是FatherView的子类,_test_one_view是FatherView的属性,_test_one_view是在FahterView的init方法中创建的,我想在AView类中打印FahterView的属性(属性为_test_one_view),结果为null,为什么?

我不知道为什么......

我需要你的帮助,谢谢...

【问题讨论】:

    标签: ios function-pointers protected


    【解决方案1】:

    问题是testV_funcp_void的声明类型,

    我们知道methodForSelector返回类型IMP,真正的IMPtypedef id (*IMP)(id, SEL, ...),但是现在你将IMP设置为UIView *(*_testV_funcp_void)(DisplayViewT displayT)

    正确的类型应该是UIView *(*_testV_funcp_void)(UIView *v , SEL sel, DisplayViewT displayT), 这是正确的方法如下,

    typedef NS_OPTIONS(NSInteger, DisplayViewT) {
        DisplayViewT_One ,
        DisplayViewT_Two ,
    };
    
    
    @interface FatherView : UIView{
    @protected
        UIView *_test_one_view ;
    //    UIView *(*_testV_funcp_void)(DisplayViewT displayT) ;
        UIView *(*_testV_funcp_void)(UIView *v , SEL sel, DisplayViewT displayT) ;
    }
    @end
    
    @interface FatherView()
    @property (nonatomic , strong) UIView *test_two_view ;
    @end
    
    @implementation FatherView
    
    - (id) init
    {
        self = [super init] ;
        if( self ){
            self->_test_one_view = [[UIView alloc] init] ;
            self.test_two_view = [[UIView alloc] init] ;
            self->_testV_funcp_void = (UIView *(*)(UIView *, SEL, DisplayViewT))[self methodForSelector:@selector(test_func_testV:)] ;
        }
        return self ;
    }
    - (UIView *)test_func_testV:(DisplayViewT)displayT
    {
        UIView *displayV = nil ;
        switch (displayT) {
            case DisplayViewT_One:{
                displayV = self->_test_one_view ;
            }
                break;
            case DisplayViewT_Two:
            default:{
                displayV = self.test_two_view ;
            }
                break;
        }
        return displayV ;
    }
    @end
    
    @interface AView : FatherView{
    @protected
    
    }
    @end
    
    @implementation AView
    
    - (void)exc_test
    {
        UIView *oneV = self->_testV_funcp_void(self, @selector(test_func_testV:),  DisplayViewT_One) ;
        NSLog(@"%@",oneV) ;
    }
    
    @end    
    

    【讨论】:

    • 我还有一个问题。如果我想使用函数指针指向一个 Objective-C 方法(而不是指向 IMP),怎么办?我不知道怎么写。请帮忙,谢谢。
    • IMP 是函数指针的别名。第一个参数是指向 self 的指针,第二个参数是 method selector ,您正在使用函数指针指向 Objective-C 方法
    • 那么,如果在 Objective-C 中使用 'protected' ,我们必须使用 IMP 并且必须定义一个带有 3 个参数的函数指针吗?在 Cpp 中,我们可以定义一个函数指针并使用 'protected' 来装饰这个函数指针。在 Cpp 中,这很容易
    • refer developer.apple.com/documentation/objectivec/… 从内存中,IMP 就像函数指针一样是内存地址,可以像普通 C 函数一样调用。但是,它保证使用我们之前讨论过的 Objective-C 消息传递约定(参数)。
    【解决方案2】:

    将选择器转换为函数指针是个问题。使用块。

    每个实例的函数指针不是唯一的 - 它是一个指向所有实例的方法实现的指针,并且不存储“self”指针。

    【讨论】:

    • 谢谢。如果使用块,如何使用“保护”来装饰这个块?我想保护区块。
    猜你喜欢
    • 2013-10-17
    • 2017-10-15
    • 1970-01-01
    • 2015-06-14
    • 1970-01-01
    • 2016-04-14
    • 2011-09-07
    • 2019-10-25
    • 2020-02-28
    相关资源
    最近更新 更多