我需要-init
在Objective-C中隐藏(私有)我的类的方法.
我怎样才能做到这一点?
NS_UNAVAILABLE
- (instancetype)init NS_UNAVAILABLE;
这是不可用属性的简短版本.它首先出现在macOS 10.7和iOS 5中.它在NSObjCRuntime.h中定义为#define NS_UNAVAILABLE UNAVAILABLE_ATTRIBUTE
.
有一个版本只为Swift客户端禁用该方法,而不是ObjC代码:
- (instancetype)init NS_SWIFT_UNAVAILABLE;
unavailable
将unavailable
属性添加到标头以在任何对init的调用时生成编译器错误.
-(instancetype) init __attribute__((unavailable("init not available")));
如果您没有理由,只需输入__attribute__((unavailable))
,甚至__unavailable
:
-(instancetype) __unavailable init;
doesNotRecognizeSelector:
使用doesNotRecognizeSelector:
提出一个NSInvalidArgumentException."只要对象收到无法响应或转发的aSelector消息,运行时系统就会调用此方法."
- (instancetype) init { [self release]; [super doesNotRecognizeSelector:_cmd]; return nil; }
NSAssert
使用NSAssert
抛出NSInternalInconsistencyException并显示一条消息:
- (instancetype) init { [self release]; NSAssert(false,@"unavailable, use initWithBlah: instead"); return nil; }
raise:format:
使用raise:format:
抛出自己的异常:
- (instancetype) init { [self release]; [NSException raise:NSGenericException format:@"Disabled. Use +[[%@ alloc] %@] instead", NSStringFromClass([self class]), NSStringFromSelector(@selector(initWithStateDictionary:))]; return nil; }
[self release]
是必要的,因为该对象已经被使用了alloc
.使用ARC时,编译器会为您调用它.在任何情况下,当你打算故意停止执行时,不要担心.
objc_designated_initializer
如果您打算禁用init
强制使用指定的初始值设定项,则有一个属性:
-(instancetype)myOwnInit NS_DESIGNATED_INITIALIZER;
除非任何其他初始化方法在myOwnInit
内部调用,否则会生成警告.细节将在下一个Xcode发布后采用现代Objective-C发布(我猜).
Apple已开始在其头文件中使用以下内容来禁用init构造函数:
- (instancetype)init NS_UNAVAILABLE;
这在Xcode中正确显示为编译器错误.具体来说,这是在他们的几个HealthKit头文件中设置的(HKUnit就是其中之一).
与Smalltalk一样,Objective-C没有"私有"与"公共"方法的概念.任何消息都可以随时发送到任何对象.
你可以做的是抛出一个NSInternalInconsistencyException
if你的-init
方法被调用:
- (id)init { [self release]; @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"-init is not a valid initializer for the class Foo" userInfo:nil]; return nil; }
另一种选择 - 在实践中可能要好得多 - 就是尽可能-init
为你的班级做一些明智的事情.
如果您尝试这样做是因为您试图"确保"使用单个对象,请不要打扰.具体地,不与打扰"覆盖+allocWithZone:
,-init
,-retain
,-release
"创建单身的方法.它几乎总是不必要的,只是增加了复杂性,没有真正的显着优势.
相反,只需编写代码,以便您的+sharedWhatever
方法是访问单例的方法,并将其记录为在标题中获取单例实例的方法.在绝大多数情况下,这应该是你所需要的.