ブロックベースのAPIメソッドでnull以外およびnull許容のObjective-Cキーワードを使用する方法


105

次の方法を検討してください

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

新しいキーワードnonnullnullable アノテーションキーワードを使用すると、次のようにキーワードを強化できます。

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

ただし、次の警告も表示されます。

ポインターにヌル可能型指定子(__nonnullまたは__nullable)がありません

3番目のパラメーター(ブロック1)を参照します。

ドキュメントには、ブロックパラメータのNULL値の許容を指定する方法の例をカバーしていません。それは逐語的に述べています

型が単純なオブジェクトまたはブロックポインターである限り、左かっこの直後に、アンダースコアなしのフォームnull可能およびnullなしを使用できます。

ブロックの2つのキーワードの1つを(任意の位置に)運がなくても入れてみました。また、アンダースコア付きのバリアント(__nonnullおよび__nullable)も試しました。

したがって、私の質問は次のとおりです。どのようにして、ブロックパラメーターのnull可能性セマンティクスを指定できますか

回答:


128

これは機能しているようです

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

ブロックとそのパラメーターの両方にnullの可能性を指定する必要があります...

編集:詳細については、Swiftブログを参照してください


それはNSError **タイプでどのように機能しますか?コンパイラーを幸せにすることはできません。
duhanebel

3
迅速なブログによると: 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. developer.apple.com/swift/blog/
id

@duhanebel答えはstackoverflow.com/questions/33198597/…に記載されています:(NSError * _Nullable * _Nullable)エラー
Elise van Looij

33

Apple Blog( "nullability and Objective-C")によれば、

NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END

これらの領域内では、単純なポインタ型はすべてであると見なされますnonnull。次にnullable、null許容オブジェクトを追加できます。

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
  • エラーNSError **タイプの場合、NSError * _Nullable * _Nullable
  • オブジェクトがid *タイプの場合、より適切に使用するとid _Nullable * _Nonnull、状況に応じて異なります(_Nullable id * _Nullableタイプが必要な場合があります)。
  • オブジェクトがNSObject *タイプの場合、次のように、ポインタの後に注釈を付ける必要がありますNSObject * _Nullable * _Nonnull

注意

_Nonnullそして_Nullableポインタまたは後に使用されるべきであるid(Appleがコード例ではないAAPLListItem * _Nullable)が、非下線形態nonnullnullable開き括弧の後に使用することができます。

ただし、一般的なケースでは、これらの注釈を書くためのより良い方法があります。メソッド宣言内では、型が単純なオブジェクトまたはブロックポインターである限り、アンダースコアなしのフォームnullablenonnull開き括弧の直後に使用できます。

「nullabilityとObjective-C」で詳細を確認してください

安全のため、このルールにはいくつかの例外があります。

  • typedefタイプには通常、固有のnull可能性はありません。コンテキストに応じて、null可能またはnull可能ではない可能性があります。したがって、監査対象領域内であっても、typedef型はであるとは見なされませんnonnull
  • などのより複雑なポインタ型にid *は、明示的に注釈を付ける必要があります。たとえば、null許容オブジェクト参照へのnull不可ポインタを指定するには、を使用します_Nullable id * _Nonnull
  • 特定の型NSError **は、メソッドパラメータを介してエラーを返すために頻繁に使用されるため、常にnull可能なNSError参照へのnull可能なポインタであると見なされます。

_Nullable id * _Nonnull混乱することができ、id _Nullable * _Nonnullより良く理解されます。

_Nonnullそして_Nullable、ポインタの後に使用したりすべきであるid(AppleがサンプルコードではありませんAAPLListItem * _Nullable


弱いプロパティの場合、_Nullableが適用されます。
Dongjin Suh

3

次のようにすることもできます:

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

それはあなたがもっと好きな構文に依存します。


2

ヘッダーファイルで補完を定義するには、これを行いました

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

もちろん、私は受け入れられた答えに同意します。


0

アップル開発者ブログから:コア:_Nullableおよび_Nonnull

型が単純なオブジェクトまたはブロックポインターである限り、開き括弧の直後に null可能およびnull以外のアンダースコアなしの形式を使用できます。

アンダースコアなしのフォームは、アンダースコア付きのフォームよりも優れてい ますが、ヘッダーのすべてのタイプに適用する必要があります


そうですが、アンダースコア以外の(ナイスな)ブロックはブロック宣言では機能しません
Paul Bruneau

-2

これがNSError **のケースで使用したものです。

-(BOOL) something:(int)number withError:(NSError *__autoreleasing  __nullable * __nullable)error;

1
Appleは、のために言ったNSError **、あなたはそのNULL入力属性を指定する必要がありません。
DawnSong 2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.