How to use nonnull and nullable Objective-C keywords in block-based API method

后端 未结 6 1332
暗喜
暗喜 2020-12-22 22:13

Consider the following method

- (void)methodWithArg:(NSString *)arg1 andArg:(NSString *)arg2 completionHandler:(void (^)(NSArray *results, NSError *error))co         


        
相关标签:
6条回答
  • 2020-12-22 22:40

    To define completions in a header file I did this

    typedef void (^PublicEventsHandler) (BOOL success, NSArray * _Nullable publicEvents);
    

    Of course, I agree with the accepted answer.

    0 讨论(0)
  • 2020-12-22 22:40

    Here is what I have used for the NSError ** case:

    -(BOOL) something:(int)number withError:(NSError *__autoreleasing  __nullable * __nullable)error;
    
    0 讨论(0)
  • 2020-12-22 22:45

    From apple developer blog: The Core: _Nullable and _Nonnull

    you can use the non-underscored forms nullable and nonnull immediately after an open parenthesis, as long as the type is a simple object or block pointer.

    The non-underscored forms are nicer than the underscored ones, but you’d still need to apply them to every type in your header.

    0 讨论(0)
  • 2020-12-22 22:51

    According to Apple Blog ("Nullability and Objective-C"), you can use

    NS_ASSUME_NONNULL_BEGIN and NS_ASSUME_NONNULL_END.

    Within these regions, any simple pointer type will be assumed to be nonnull. Then you can just add nullable for nullable object, which like

    NS_ASSUME_NONNULL_BEGIN
    
    @interface MyClass: NSObject
    
    - (void)methodWithArg:(NSString *)arg1 andArg:(nullable NSString *)arg2 completionHandler:(void (^)(NSArray *results, NSError *error))completionHandler;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    • if error is NSError ** type, should be NSError * _Nullable * _Nullable
    • if object is id * type, better use id _Nullable * _Nonnull, it depends (may be you want a _Nullable id * _Nullable type).
    • if object is NSObject * type, you need put annotation after pointer, like this NSObject * _Nullable * _Nonnull

    Note

    _Nonnull and _Nullable should used after pointer or id (Apple does in the example code AAPLListItem * _Nullable), but the non-underscored forms nonnull and nullable can used after an open parenthesis.

    However, in the common case there’s a much nicer way to write these annotations: within method declarations you can use the non-underscored forms nullable and nonnull immediately after an open parenthesis, as long as the type is a simple object or block pointer.

    check more in "Nullability and Objective-C"

    For safety, there are a few exceptions to this rule:

    • typedef types don’t usually have an inherent nullability—they can easily be either nullable or non-nullable depending on the context. Therefore, typedef types are not assumed to be nonnull, even within audited regions.
    • More complex pointer types like id * must be explicitly annotated. For example, to specify a non-nullable pointer to a nullable object reference, use _Nullable id * _Nonnull.
    • The particular type NSError ** is so often used to return errors via method parameters that it is always assumed to be a nullable pointer to a nullable NSError reference.

    The _Nullable id * _Nonnull can be confused, id _Nullable * _Nonnull is better understanding.

    _Nonnull and _Nullable should used after pointer or id (Apple does in the example code AAPLListItem * _Nullable)

    0 讨论(0)
  • 2020-12-22 22:53

    This seems to be working

    - (void)methodWithArg:(nonnull NSString *)arg1 
      andArg:(nullable NSString *)arg2 completionHandler:(nullable void (^)
      (NSArray * _Nullable results, NSError * _Nonnull error))completionHandler
    

    You need to specify nullability both for the block and its parameters...

    EDIT: For more information, see Swift Blog

    0 讨论(0)
  • 2020-12-22 22:58

    You can also do like this:

    - (id __nullable)methodWithArg:(NSString * __nullable)arg1
                            andArg:(NSString * __nonnull)arg2
                 completionHandler:(void (^ __nonnull)(NSArray * __nonnull results, NSError * __nullable error))completionHandler;
    

    It only depends which syntax you like more.

    0 讨论(0)
提交回复
热议问题