web-dev-qa-db-ja.com

ブロックベースのAPIメソッドでnull以外のnull可能なObjective-Cキーワードを使用する方法

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

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

新しいnonnullおよびnullable注釈キーワード を使用すると、次のように強化できます。

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

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

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

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

documentation では、ブロックパラメーターのNULL可能性を指定する方法の例は説明していません。逐語的

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

ブロックの2つのキーワードの1つを(任意の位置に)運を出さずに置いてみました。アンダースコアの接頭辞付きバリアント(__nonnullおよび__nullable)も試してみました。

したがって、私の質問は次のとおりです。ブロックパラメーターにnullabilityセマンティクスを指定するにはどうすればよいですか。

92

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

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

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

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

112
Fabio Ritrovato

Apple Blog( "Nullability and Objective-C") によると、使用できます

NS_ASSUME_NONNULL_BEGINおよびNS_ASSUME_NONNULL_END

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

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
  • errorNSError **タイプの場合、NSError * _Nullable * _Nullableである必要があります
  • オブジェクトがid *型の場合、id _Nullable * _Nonnullを使用する方が適切です。これは依存します(_Nullable id * _Nullable型が必要な場合があります)。
  • オブジェクトがNSObject *型の場合、このNSObject * _Nullable * _Nonnullのように、ポインターの後に注釈を付ける必要があります

_Nonnullおよび_Nullableは、ポインターまたはidの後に使用する必要があります(AppleはサンプルコードAAPLListItem * _Nullableで使用します)が、下線のない形式nonnullおよびnullableは、括弧の後に使用できます。

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

"Nullability and 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で使用します)

28
likid1412

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

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

それはあなたがより好きな構文に依存します。

3
OlDor

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

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

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

2
Krishna Kumar

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

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

下線のないフォームは下線のあるフォームよりも優れていますが、ヘッダーのすべてのタイプに適用する必要があります

0
Parag Bafna