为什么 Objective-C 不能在受保护的函数指针中使用 'self' 对象?

Why the Objective-C cannot use 'self' object in protected function-pointer?

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

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 class 中, _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 class 是 FatherView class' subclass :

@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 打印结果:空!

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

我不知道为什么...

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

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

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

问题是 testV_funcp_void,

的声明类型

我们知道methodForSelectorreturns的类型是IMP,真正的IMPtypedef id (*IMP)(id, SEL, ...),但是现在你设置IMPUIView *(*_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