借助Xcode 6.3,引入了新的注释,以便在 Objective-C 中更好地表达API的意图(当然,并确保更好的Swift支持)。这些注释当然是nonnullnullablenull_unspecified

但是使用Xcode 7时,会出现很多警告,例如:



除此之外,Apple使用另一种可空性说明符,标记其C代码(source):
CFArrayRef __nonnull CFArrayCreate(
CFAllocatorRef __nullable allocator, const void * __nonnull * __nullable values, CFIndex numValues, const CFArrayCallBacks * __nullable callBacks);
因此,总而言之,我们现在有以下3种不同的可空性注释:

  • nonnullnullablenull_unspecified
  • _Nonnull_Nullable_Null_unspecified
  • __nonnull__nullable__null_unspecified

  • 即使我知道为什么以及在何处使用哪种注释,我还是对应该使用哪种类型的注释,地点和原因感到困惑。这是我可以收集的:
  • 对于属性,我应该使用nonnullnullablenull_unspecified
  • 对于方法参数,我应该使用nonnullnullablenull_unspecified
  • 对于C方法,我应该使用__nonnull__nullable__null_unspecified
  • 对于其他情况,例如双指针,我应该使用_Nonnull_Nullable_Null_unspecified

  • 但是对于为什么我们有这么多基本上执行相同操作的注释,我仍然感到困惑。

    所以我的问题是:

    这些注释之间的确切区别是什么,如何正确放置它们以及为什么?

    最佳答案

    clang documentation:



    , 和



    因此,对于方法返回和参数,您可以使用
    带双下划线的版本__nonnull/__nullable/__null_unspecified,而不是单下划线版本或非下划线版本。 所不同的是,必须在类型定义之后放置单划线和双下划线的内容,而在类型定义之前放置非下划线的内容。

    因此,以下声明是等效的并且是正确的:

    - (nullable NSNumber *)result
    - (NSNumber * __nullable)result
    - (NSNumber * _Nullable)result
    

    对于参数:
    - (void)doSomethingWithString:(nullable NSString *)str
    - (void)doSomethingWithString:(NSString * _Nullable)str
    - (void)doSomethingWithString:(NSString * __nullable)str
    

    对于属性:
    @property(nullable) NSNumber *status
    @property NSNumber *__nullable status
    @property NSNumber * _Nullable status
    

    但是,当涉及到双指针或块返回的结果与void不同时,事情就变得复杂了,因为这里不允许使用非下划线:
    - (void)compute:(NSError *  _Nullable * _Nullable)error
    - (void)compute:(NSError *  __nullable * _Null_unspecified)error;
    // and all other combinations
    

    与将块作为参数的方法类似,请注意,nonnull/nullable限定符适用于块,而不适用于其返回类型,因此以下内容是等效的:
    - (void)executeWithCompletion:(nullable void (^)())handler
    - (void)executeWithCompletion:(void (^ _Nullable)())handler
    - (void)executeWithCompletion:(void (^ __nullable)())handler
    

    如果该块具有返回值,那么您将被迫进入下划线版本之一:
    - (void)convertObject:(nullable id __nonnull (^)(nullable id obj))handler
    - (void)convertObject:(id __nonnull (^ _Nullable)())handler
    - (void)convertObject:(id _Nonnull (^ __nullable)())handler
    // the method accepts a nullable block that returns a nonnull value
    // there are some more combinations here, you get the idea
    

    结论是,只要编译器可以确定要向其分配限定符的项目,就可以使用任一个。

    关于objective-c - Objective-C中可为空,__ nullable和_Nullable之间的区别,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/32452889/

    10-11 19:47