Considérons la méthode suivante
- (void)methodWithArg:(NSString *)arg1 andArg:(NSString *)arg2 completionHandler:(void (^)(NSArray *results, NSError *error))completionHandler;
Avec les nouveaux nonnull
et nullable
mots-clés d'annotation , nous pouvons l'enrichir comme suit:
- (void)methodWithArg:(nonnull NSString *)arg1 andArg:(nullable NSString *)arg2 completionHandler:(void (^)(NSArray *results, NSError *error))completionHandler;
mais nous avons aussi cet avertissement:
Il manque un spécificateur de type nullable au pointeur (__nonnull ou __nullable)
Il fait référence au troisième paramètre (le bloc un).
La documentation ne couvre pas avec des exemples comment spécifier la nullité des paramètres de bloc. Il dit textuellement
Vous pouvez utiliser les formes non soulignées nullable et nonnull immédiatement après une parenthèse ouverte, à condition que le type soit un objet simple ou un pointeur de bloc.
J'ai essayé de mettre l'un des deux mots clés pour le bloc (dans n'importe quelle position) sans aucune chance. Nous avons également essayé les variantes avec préfixe de soulignement (__nonnull
et __nullable
).
Par conséquent, ma question est la suivante: comment puis-je spécifier la sémantique d'invalidité pour les paramètres de bloc?
Cela à l'air de marcher
- (void)methodWithArg:(nonnull NSString *)arg1
andArg:(nullable NSString *)arg2 completionHandler:(nullable void (^)
(NSArray * _Nullable results, NSError * _Nonnull error))completionHandler
Vous devez spécifier la nullabilité du bloc et de ses paramètres ...
EDIT: Pour plus d'informations, voir Swift Blog
Selon Blog Apple ("Nullability and Objective-C") , vous pouvez utiliser
_NS_ASSUME_NONNULL_BEGIN
_ et _NS_ASSUME_NONNULL_END
_.
Dans ces régions, tout type de pointeur simple sera supposé être nonnull
. Ensuite, vous pouvez simplement ajouter nullable
pour un objet nullable, qui
_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 **
_, doit être _NSError * _Nullable * _Nullable
_id *
_, mieux utiliser _id _Nullable * _Nonnull
_, cela dépend (vous voudrez peut-être un type __Nullable id * _Nullable
_).NSObject *
_, vous devez mettre une annotation après le pointeur, comme ceci _NSObject * _Nullable * _Nonnull
_Remarque
__Nonnull
_ et __Nullable
_ doivent être utilisés après le pointeur ou id
(Apple le fait dans l'exemple de code _AAPLListItem * _Nullable
_), mais les formes non soulignées nonnull
et nullable
peut être utilisé après une parenthèse ouverte.
Cependant, dans le cas courant, il existe un moyen bien plus agréable d'écrire ces annotations: dans les déclarations de méthode, vous pouvez utiliser les formes non soulignées
nullable
etnonnull
immédiatement après une parenthèse ouverte, tant que le type est un objet simple ou un pointeur de bloc.
vérifier plus dans "Nullability and Objective-C"
Pour des raisons de sécurité, il existe quelques exceptions à cette règle:
- Les types
typedef
n’ont généralement pas de caractère nullable inhérent - ils peuvent facilement être soit nullables, soit non-nullables en fonction du contexte. Par conséquent, les typestypedef
ne sont pas supposés êtrenonnull
, même dans les régions contrôlées.- Les types de pointeurs plus complexes tels que _
id *
_ doivent être explicitement annotés. Par exemple, pour spécifier un pointeur non nullable sur une référence d'objet nullable, utilisez __Nullable id * _Nonnull
_.- Le type particulier _
NSError **
_ est si souvent utilisé pour renvoyer des erreurs via des paramètres de méthode qu'il est toujours supposé être un pointeur nullable vers une référence nullableNSError
.
Le __Nullable id * _Nonnull
_ peut être confondu, _id _Nullable * _Nonnull
_ est une meilleure compréhension.
_Nonnull
_ ET __Nullable
_ DOIT ÊTRE UTILISÉ APRÈS LE POINTEUR OU id
(APPLE LE FAIT DANS L'EXEMPLE DE CODE _AAPLListItem * _Nullable
)
Vous pouvez aussi faire comme ça:
- (id __nullable)methodWithArg:(NSString * __nullable)arg1
andArg:(NSString * __nonnull)arg2
completionHandler:(void (^ __nonnull)(NSArray * __nonnull results, NSError * __nullable error))completionHandler;
Cela dépend seulement de la syntaxe que vous préférez.
Pour définir les complétions dans un fichier d'en-tête, je l'ai fait
typedef void (^PublicEventsHandler) (BOOL success, NSArray * _Nullable publicEvents);
Bien sûr, je suis d'accord avec la réponse acceptée.
De Apple blog de développeur : Le noyau: _Nullable et _Nonnull
vous pouvez utiliser les formes non soulignées nullable et nonnull immédiatement après une parenthèse ouverte , tant que le type est un objet simple ou un pointeur de bloc.
Les formulaires non soulignés sont plus agréables que ceux sous soulignés, mais vous devez toujours les appliquer à chaque type de votre en-tête .