【发布时间】:2019-06-03 23:14:52
【问题描述】:
众所周知,在.h文件中声明的ObjC属性是接口“外部可见”,而在.m文件中声明的属性(类扩展名)只能在.m中访问,类型为“私有”或“隐藏” ”。但实际上可以编译如下代码。
ClassA.h
@interface ClassA : NSObject
+ (void)foo;
@end
ClassA.m
#import "ClassA.h"
@interface ClassA ()
@property (nonatomic) NSInteger aInt;
@end
@implementation ClassA
+ (void)foo {
ClassA *aObj = [ClassA new];
aObj.aInt = 2; //?
}
@end
@interface _ClassB : NSObject //Some private class defined in the same .m file...
@end
@implementation _ClassB
+ (void)bar {
ClassA* aObj = [ClassA new];
aObj.aInt = 2; //?
}
@end
事实是,不仅ClassA自己的方法中定义的ClassA *aObj可以访问类扩展属性aInt,而且在同一个ClassA.m文件中定义在另一个_ClassB中的ClassA *aObj也可以访问aInt。
据我了解,在类方法foo 中定义的aObj 与在另一个类和单独的.m 文件中定义的任何ClassA * 类型变量没有区别。但是后者绝不会访问'aInt',比如说
ClassC.m
#import "ClassA.h"
...
- (void)fun {
ClassA *aObj = [ClassA new];
NSLog("%d", aObj.aInt); //Error! Property aInt not found on object of type 'ClassA*'
}
为什么会这样?这可以用 ObjC 运行时机制什么的来解释吗?
【问题讨论】:
-
因为
objective-c语言没有私有方法和属性。您只能在编译时通过隐藏它们的声明来模拟可访问性,但无论如何在运行时它们都是公开的。比如你可以调用私有api,苹果只能通过拒绝appstore中的分发来禁止它。
标签: ios objective-c properties class-extensions