web-dev-qa-db-fra.com

Le pointeur manque un spécificateur de type nullable

Dans Xcode 7 GM j'ai commencé à recevoir cet avertissement:

Il manque un spécificateur de type Nullable au pointeur (_Nonnull, _Nullable ou _Null_unspecified)

Dans la déclaration de fonction suivante (extension NSUserDefaults)

- (void)setObject:(nullable id)value
           forKey:(NSString *)defaultName
    objectChanged:(void(^)(NSUserDefaults *userDefaults, id value))changeHandler
    objectRamains:(void(^)(NSUserDefaults *userDefaults, id value))remainHandler;

Pourquoi cet avertissement est affiché et comment dois-je résoudre le problème?

59
kelin

Vous devez spécifier nullable également pour les gestionnaires/blocs

- (void)setObject:(nullable id)value
           forKey:(nonnull NSString *)defaultName
    objectChanged:(nullable void(^)(NSUserDefaults *userDefaults, id value))changeHandler
    objectRamains:(nullable void(^)(NSUserDefaults *userDefaults, id value))remainHandler;

Pourquoi? C'est dû à Swift. Swift autorise les paramètres facultatifs (?), Ce que ne fait pas Objective-C. Cela sert de pont entre les deux pour le Swift doit savoir ces paramètres sont optionnels. Un 'Nonnull' indiquera au compilateur Swift) que l'argument est l'argument requis. Un nullable qu'il soit optionnel

Pour plus d'informations, consultez: https://developer.Apple.com/Swift/blog/?id=25

55
Ares

Vous pouvez utiliser les macros suivantes autour de blocs de déclarations (fonctions et variables) dans les en-têtes Objective C:

NS_ASSUME_NONNULL_BEGIN 

NS_ASSUME_NONNULL_END

Vous devez ensuite ajouter des annotations pouvant être annulées pour les références pouvant être nulles dans ce bloc. Ceci s'applique aux paramètres de fonction et aux déclarations de variable.

Un péché:

@interface SMLBaseUserDetailsVC : UIViewController < UICollectionViewDelegate>
NS_ASSUME_NONNULL_BEGIN

@property (nonatomic, readonly) IBOutlet UIScrollView *detailsScrollView;
@property (nonatomic, readonly) IBOutlet UICollectionView *photoCV;
@property (nonatomic, weak, readonly) SMLUser *user;
- (IBAction)flagUser:(id)sender;
- (IBAction)closeAction:(nullable id)sender;
- (void) prefetchPhotos;

NS_ASSUME_NONNULL_END

@end

Edit * Le pourquoi ??? En effet, pour qu'une classe objective-c soit interopérable avec Swift, vous devez déclarer la nullabilité de sorte que le compilateur sache traiter les propriétés comme Swift optionnels ou non. Nullable les propriétés Objective C sont appelées optionnelles. in Swift et l’utilisation de ces macros en association avec les déclarateurs nullable pour les propriétés permet au compilateur de les traiter comme des optionnels (les optionnels sont des monads - un objet qui encapsule l’objet ou nil).

54
Kevin

La déclaration de méthode de travail correcte, acceptée par le compilateur:

- (void)setObject:(nullable id)value
           forKey:(nonnull NSString *)defaultName
    objectChanged:(nullable void(^)(NSUserDefaults *_Nonnull userDefaults, id _Nullable value))changeHandler
    objectRamains:(nullable void(^)(NSUserDefaults *_Nonnull userDefaults, id _Nullable value))remainHandler;
14
kelin

Je poste cette réponse pour dire pourquoi devrait ajouter _Nonnull Ou nullable.

Selon ce blog: https://developer.Apple.com/Swift/blog/?id=25

Un des points forts de Swift est qu’il interagit de manière transparente avec le code Objective-C, les deux cadres existants écrits en Objective-C et le code de votre application. Cependant, dans Swift Il existe une forte distinction entre les références facultatives et non facultatives, par exemple NSView contre NSView?, alors que Objective-C représente les deux types de ces deux types sous la forme NSView *. Parce que le compilateur Swift ne peut pas être sûr si un NSView * Particulier est facultatif ou non, le type est amené dans Swift sous forme implicite non emballé facultatif, NSView!.

c'est tout pour Swift.

9
fishtrees

Pour désactiver cet avertissement sur l'ensemble de votre projet

  1. Aller aux paramètres de construction

  2. Assurez-vous que l'onglet "Tous" est affiché et non "De base" ou "Personnalisé"

  3. Rechercher le champ Other Warning Flags

  4. Ajoutez l'indicateur suivant: -Wno-nullability-completeness.

  5. Maintenant, nettoyez et construisez (cmd + shift + k puis cmd + r)

    - remarque, cela peut prendre quelques secondes pour que les avertissements disparaissent même après que vous ayez fini de construire, pour moi cela prend environ 15 secondes pour que xCode se mette à jour complètement

3
Albert Renshaw