web-dev-qa-db-fra.com

Propriété de bloc Objective-C avec complétion du code Xcode

Est-il possible de définir une propriété de bloc Objective-C tout en ayant l'achèvement du code complet dans Xcode 4?

Si j'utilise un typedef pour définir le bloc:

typedef void (^CompletionBlock)(MyObject *myObj);

puis définissez la propriété:

@property (nonatomic, copy) CompletionBlock completionBlock;

et puis @synthesize la propriété Je ne reçois pas la complétion complète du code lorsque j'appelle le configurateur. Xcode utilisera le typedef et pour cette raison, l'achèvement du code n'utilise pas la syntaxe de bloc complète avec les paramètres de bloc, mais le typedef.

Si je définis un prototype de méthode dans l'en-tête qui utilise la syntaxe de bloc complète au lieu de la typedef:

@property (nonatomic, copy) void (^completionBlock)(MyObject *myObj);

et puis j'utilise @synthesize, le setter fourni s'approche de la syntaxe de complétion de code, mais il omet surtout les noms de paramètres:

[self setCompletionBlock:(void (^)(MyObject *)) { ... }

Enfin, si j’essaie de @synthesize puis de remplacer l’implémentation du setter ou de placer le prototype dans l’en-tête:

- (void)setCompletionBlock:(void (^)(MyObject *myObj))completionBlock {...}

Un avertissement est émis indiquant que le type de propriété ne correspond pas au type d'accesseur. Peu importe la façon dont j'essaie de finaliser la syntaxe, je ne suis pas en mesure de définir à la fois une propriété de bloc et un séparateur qui possède la syntaxe complète pour l'achèvement du code. Puis-je avoir mon gâteau et le manger aussi?

Merci!

29
Andrew

Vous pouvez certainement avoir votre gâteau et le manger aussi, si vous êtes prêt à ajouter une ligne de code supplémentaire à votre interface de classe.

Tout d’abord, définissez block avec un typedef et créez une propriété comme vous l’avez fait dans votre question:

typedef void (^CompletionBlock)(MyObject *myObj);

...

@property (nonatomic, copy) CompletionBlock completionBlock;

Ensuite, comme le souligne MobileOverload dans sa réponse, nous savons que Xcode fournit la complétion de code correcte pour les blocs typedef si elle est utilisée dans une déclaration de méthode autonome. Ajoutons donc une déclaration explicite pour le créateur de completionBlock:

- (void)setCompletionBlock:(CompletionBlock)completionBlock;

Lorsqu'elle est appelée, cette méthode résout la méthode setter déclarée par la propriété. Cependant, comme nous l'avons explicitement défini dans l'interface de classe, Xcode le voit et applique la complétion complète du code.

Donc, si vous incluez ces trois lignes, vous devriez obtenir le résultat souhaité. Ce comportement est clairement une lacune de Xcode, car il n'y a aucune raison pour laquelle un séparateur défini dans une instruction @property devrait avoir une complétion de code différente de celle de la même méthode définie seule.

34
Matt

Vous pouvez obtenir du code de finition assez sophistiqué lorsque vous transmettez vos blocs en tant qu'argument à une méthode de votre classe. Dans le fichier d'en-tête, j'ai tapé le bloc comme ceci

typedef void (^MyCompletionBlock)(id obj1, id obj2);

Ensuite, j'ai pu l'utiliser comme argument pour ma méthode que j'ai également déclarée dans cet en-tête de classe.

-(void)doThisWithBlock:(MyCompletionBlock)block;

Dans le fichier m j'ai déclaré la méthode

-(void)doThisWithBlock:(MyCompletionBlock)block {
    NSLog(@"Something");
}

et quand je suis allé l'appeler, j'ai obtenu un code de finition complet comme celui-ci. CodeCompletion1

CodeCompletion2

J'espère que cela répond à votre question.

4
MobileOverlord

Ok, j’ai donc trouvé une façon de pallier cet inconvénient qui ne donne pas lieu à des avertissements/erreurs ... et rend les choses plus faciles à lire/plus court pour taper, etc.

définir une macro avec notre "abréviation", puis utiliser le format complet dans la déclaration de propriété comme ...

#define TINP NSString*(^)(NSString *typed, const char *raw)
@interface ....
@property (copy) NSString*(^termDidReadString)(NSString *typed, const char *raw);

par la suite .. vous pouvez alors faire référence à ce "type" d'argument, etc. comme ..

+ (void)addInputBlock:(TINP)termDidReadString;

et voila ... non seulement votre code sera TINIER !! mais l'achèvement du code fonctionnera, comme un charme ...

enter image description here

1
Alex Gray

Je ne sais pas comment compléter le code, mais vous pouvez utiliser des extraits de code pour obtenir du code comme comportement et vous pouvez utiliser des espaces réservés dans les extraits de code <#PLACE HOLDER #>. J'espère que cela vous aidera 

0
Apps 4 U