objective c - keywords - Cómo usar palabras clave Objective-C no nulas y anulables en el método API basado en bloques
meta name keywords (6)
De acuerdo con el Blog de Apple ("Nulabilidad y Objetivo-C") , puede usar
NS_ASSUME_NONNULL_BEGIN
y
NS_ASSUME_NONNULL_END
.
Dentro de estas regiones, se supondrá que cualquier tipo de puntero simple no es
nonnull
.
Luego, puede agregar
nullable
para objeto nullable, que como
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
-
si el
error
es del tipo
NSError **
, debe serNSError * _Nullable * _Nullable
-
si el objeto es
id *
type, mejor useid _Nullable * _Nonnull
, depende (puede ser que desee un_Nullable id * _Nullable
type). -
si el objeto es del tipo
NSObject *
, necesita poner una anotación después del puntero, como esteNSObject * _Nullable * _Nonnull
Nota
_Nonnull
y
_Nullable
deben usarse después del puntero o
id
(Apple lo hace en el código de ejemplo
AAPLListItem * _Nullable
), pero las formas no subrayadas
nonnull
y
nonnull
pueden usarse después de un paréntesis abierto.
Sin embargo, en el caso común, hay una forma mucho más agradable de escribir estas anotaciones: dentro de las declaraciones de métodos, puede usar los formularios no subrayados que se pueden
nullable
y nononnull
inmediatamente después de un paréntesis abierto, siempre que el tipo sea un objeto simple o un puntero de bloque.
ver más en "Nulabilidad y Objetivo-C"
Por seguridad, hay algunas excepciones a esta regla:
typedef
tipostypedef
no suelen tener una nulabilidad inherente; pueden ser fácilmente anulables o no anulables según el contexto. Por lo tanto, no se supone que los tipostypedef
sean nononnull
, incluso dentro de las regiones auditadas.- Los tipos de puntero más complejos como
id *
deben anotar explícitamente. Por ejemplo, para especificar un puntero no anulable a una referencia de objeto anulable, use_Nullable id * _Nonnull
.- El tipo particular
NSError **
se usa con tanta frecuencia para devolver errores a través de parámetros del método que siempre se supone que es un puntero anulable a una referenciaNSError
anulable.
El
_Nullable id * _Nonnull
puede confundirse,
id _Nullable * _Nonnull
es una mejor comprensión.
_Nonnull
y
_Nullable
deben usarse después del puntero o
id
(Apple lo hace en el código de ejemplo
AAPLListItem * _Nullable
)
Considere el siguiente método
- (void)methodWithArg:(NSString *)arg1 andArg:(NSString *)arg2 completionHandler:(void (^)(NSArray *results, NSError *error))completionHandler;
Con las nuevas
palabras clave de anotación
no
nonnull
y
nullable
podemos enriquecerla de la siguiente manera:
- (void)methodWithArg:(nonnull NSString *)arg1 andArg:(nullable NSString *)arg2 completionHandler:(void (^)(NSArray *results, NSError *error))completionHandler;
pero también recibimos esta advertencia:
Al puntero le falta un especificador de tipo de anulabilidad (__nulo o nulo)
Se refiere al tercer parámetro (el bloque uno).
La documentación no cubre con ejemplos cómo especificar la nulabilidad de los parámetros de bloque. Dice textualmente
Puede usar las formas no subrayadas anulables y no nulas inmediatamente después de un paréntesis abierto, siempre que el tipo sea un objeto simple o un puntero de bloque.
Intenté poner una de las dos palabras clave para el bloque (en cualquier posición) sin suerte.
También probé las variantes prefijadas de subrayado (
__nonnull
y
__nullable
).
Por lo tanto, mi pregunta es: ¿cómo puedo especificar la semántica de nulabilidad para los parámetros de bloque?
Del blog de desarrolladores de Apple: The Core: _Nullable y _Nonnull
puede usar las formas no subrayadas anulables y no nulas inmediatamente después de un paréntesis abierto , siempre que el tipo sea un objeto simple o un puntero de bloque.
Los formularios no subrayados son más bonitos que los subrayados, pero aún así necesitará aplicarlos a cada tipo en su encabezado .
Esto es lo que he usado para el caso NSError **:
-(BOOL) something:(int)number withError:(NSError *__autoreleasing __nullable * __nullable)error;
Esto parece estar funcionando
- (void)methodWithArg:(nonnull NSString *)arg1
andArg:(nullable NSString *)arg2 completionHandler:(nullable void (^)
(NSArray * _Nullable results, NSError * _Nonnull error))completionHandler
Debe especificar la nulabilidad tanto para el bloque como para sus parámetros ...
EDITAR: para obtener más información, consulte Swift Blog
Para definir las terminaciones en un archivo de encabezado hice esto
typedef void (^PublicEventsHandler) (BOOL success, NSArray * _Nullable publicEvents);
Por supuesto, estoy de acuerdo con la respuesta aceptada.
También puedes hacer así:
- (id __nullable)methodWithArg:(NSString * __nullable)arg1
andArg:(NSString * __nonnull)arg2
completionHandler:(void (^ __nonnull)(NSArray * __nonnull results, NSError * __nullable error))completionHandler;
Solo depende de la sintaxis que más te guste.