Blok tabanlı API yönteminde boş olmayan ve boş değer atanabilir Objective-C anahtar kelimeleri nasıl kullanılır?


106

Aşağıdaki yöntemi düşünün

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

Yeni nonnullve nullable ek açıklamalı anahtar kelimelerle onu aşağıdaki gibi zenginleştirebiliriz:

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

ancak şu uyarıyı da alıyoruz:

İşaretçide boş değer atanabilirlik türü belirticisi eksik (__nonnull veya __nullable)

Üçüncü parametreye (birinci blok) atıfta bulunur.

Dokümantasyon blok parametreleri nullability nasıl belirleneceği örneklerle kapsamaz. Aynen ifade eder

Tip basit bir nesne veya blok işaretçisi olduğu sürece, altı çizilmemiş formları açık bir parantezden hemen sonra null yapılabilir ve boş olmayan biçimler kullanabilirsiniz.

Blok için iki anahtar kelimeden birini (herhangi bir konumda) şanssız olarak koymayı denedim. Ayrıca alt çizgi önekli varyantları ( __nonnullve __nullable) denedi .

Bu nedenle sorum şu: Blok parametreleri için boş değer atanabilirlik anlamını nasıl belirleyebilirim?

Yanıtlar:


128

Bu işe yarıyor gibi görünüyor

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

Hem blok hem de parametreleri için boş değer atanabilirliği belirtmeniz gerekir ...

DÜZENLEME: Daha fazla bilgi için bkz. Swift Blog


Bu türle nasıl çalışır NSError **? Derleyiciyi mutlu edemiyorum.
duhanebel

3
Hızlı bloga göre: 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=25
user1687195

@duhanebel Cevap, stackoverflow.com/questions/33198597/… adresinde verilmiştir : (NSError * _Nullable * _Nullable) error
Elise van Looij

33

Göre Apple Blog ( "Nullability ve Objective-C") , kullanabilirsiniz

NS_ASSUME_NONNULL_BEGINve NS_ASSUME_NONNULL_END.

Bu bölgeler içinde, herhangi bir basit işaretçi türü olduğu varsayılacaktır nonnull. Daha sonra nullableboş değer atanabilir nesne ekleyebilirsiniz .

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
  • eğer hata olduğunu NSError **türde olması gerektiğiniNSError * _Nullable * _Nullable
  • nesne id *tür ise, daha iyi kullanım id _Nullable * _Nonnull, bağlıdır (bir _Nullable id * _Nullabletür isteyebilirsin ).
  • nesne NSObject *tür ise, işaretçiden sonra açıklama koymanız gerekir, bunun gibiNSObject * _Nullable * _Nonnull

Not

_Nonnullve _Nullableişaretçi veya id(örnek kodda Apple yapar) sonra kullanılmalıdır AAPLListItem * _Nullable, ancak altı çizilmemiş formlar nonnullve nullableaçık bir parantezden sonra kullanılabilir.

Bununla birlikte, yaygın durumda, bu ek açıklamaları yazmanın çok daha hoş bir yolu vardır: yöntem bildirimlerinde, altı çizilmemiş formları nullableve nonnullaçık bir parantezin hemen ardından, tür basit bir nesne veya blok işaretçisi olduğu sürece kullanabilirsiniz.

"Nullability ve Objective-C" de daha fazlasını kontrol edin

Güvenlik açısından, bu kuralın birkaç istisnası vardır:

  • typedeftürler genellikle doğal bir boş değer atanabilirliğe sahip değildir; bağlama bağlı olarak kolayca null yapılabilir veya null yapılamaz olabilirler. Bu nedenle, typedeftürlerin nonnulldenetlenen bölgelerde bile olduğu varsayılmaz .
  • Gibi daha karmaşık işaretçi türleri id *açıkça belirtilmelidir. Örneğin, boş değer atanabilir bir nesne başvurusuna yönelik boş değer atanamayan bir işaretçi belirtmek için kullanın _Nullable id * _Nonnull.
  • Belirli bir tür NSError **, yöntem parametreleri aracılığıyla hata döndürmek için o kadar sık ​​kullanılır ki, her zaman null atanabilir bir NSErrorbaşvuruya null atanabilir bir işaretçi olduğu varsayılır .

_Nullable id * _NonnullKarışabilir, id _Nullable * _Nonnulldaha iyi anlamaktır.

_Nonnullve _Nullableişaretçiden sonra kullanılmalıdır veya id(Apple örnek kodda yaparAAPLListItem * _Nullable )


Zayıf özellik için _Nullable uygulandı.
Dongjin Suh

3

Ayrıca şunu da yapabilirsiniz:

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

Yalnızca hangi sözdizimini daha çok sevdiğine bağlıdır.


2

Bir başlık dosyasında tamamlamaları tanımlamak için bunu yaptım

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

Tabii ki, kabul edilen cevaba katılıyorum.


0

Apple geliştirici blogundan : Çekirdek: _Nullable ve _Nonnull

Tip basit bir nesne veya blok işaretçisi olduğu sürece, altı çizilmemiş formları açık bir parantezden hemen sonra null yapılabilir ve boş olmayan şekilde kullanabilirsiniz .

Altı çizilmemiş formlar altı çizili olanlardan daha güzeldir, ancak yine de başlığınızdaki her tür için bunları uygulamanız gerekir .


Evet ama alt çizgi olmayan (daha güzel) olanlar blok bildirimlerinde çalışmıyor
Paul Bruneau

-2

İşte NSError ** vakası için kullandım:

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

1
As Apple , için söylenemez NSError **, onun nullability belirtmek gerek yok.
DawnSong
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.