wake-up-neo.com

Objective-C Block-Eigenschaft mit Xcode-Code-Vervollständigung

Kann eine Objective-C-Blockeigenschaft definiert werden, aber in Xcode 4 noch der vollständige Code abgeschlossen werden?

Wenn ich den Block mit einem Typedef definiere:

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

und definieren Sie dann die Eigenschaft:

@property (nonatomic, copy) CompletionBlock completionBlock;

und dann @synthesize die Eigenschaft Ich bekomme beim Aufrufen des Setterers keinen vollständigen Code-Abschluss. Xcode verwendet das typedef, und aus diesem Grund verwendet die Code-Vervollständigung nicht die vollständige Blocksyntax mit den Blockparametern, sondern das typedef.

Wenn ich einen Methodenprototyp im Header definiere, der die vollständige Blocksyntax anstelle des Typedefs verwendet:

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

und dann verwende ich @synthesize, der bereitgestellte Setter kommt fast der vollständigen Codeabschluss-Syntax nahe, lässt aber die Parameternamen aus:

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

Schließlich, wenn ich versuche, @synthesize zu überschreiben und dann die Setterimplementierung zu überschreiben oder den Prototyp in den Header zu setzen:

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

Es wird eine Warnung ausgegeben, die besagt, dass der Eigenschaftstyp nicht mit dem Zugriffstyp übereinstimmt. Egal wie ich versuche, die Syntax zu verfeinern, ich kann nicht gleichzeitig eine Block-Eigenschaft und einen Setter definieren, der die vollständige Syntax für die Code-Vervollständigung hat. Kann ich meinen Kuchen haben und auch essen?

Vielen Dank!

29
Andrew

Sie können Ihren Kuchen definitiv essen und auch essen, wenn Sie bereit sind, eine zusätzliche Codezeile zu Ihrer Klassenschnittstelle hinzuzufügen.

Definieren Sie zunächst einen Block mit einem Typedef und erstellen Sie eine Eigenschaft wie in Ihrer Frage:

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

...

@property (nonatomic, copy) CompletionBlock completionBlock;

Als Nächstes wissen wir, wie MobileOverload in seiner Antwort darauf hinwies, dass Xcode eine korrekte Code-Vervollständigung für typedef-Blöcke liefert, wenn sie in einer eigenständigen Methodendeklaration verwendet werden. Fügen wir also eine explizite Deklaration für den Setter von completionBlock hinzu:

- (void)setCompletionBlock:(CompletionBlock)completionBlock;

Beim Aufruf löst diese Methode die von der Eigenschaft angegebene Setter-Methode auf. Da wir es jedoch explizit in der Klassenschnittstelle definiert haben, sieht Xcode es und wendet den Code vollständig aus.

Wenn Sie also alle drei Zeilen einbeziehen, sollten Sie das gewünschte Ergebnis erhalten. Dieses Verhalten ist eindeutig ein Nachteil von Xcode, da es keinen Grund gibt, warum ein Setter, der in einer @property-Anweisung definiert ist, eine andere Code-Vervollständigung hat als dieselbe selbst definierte Methode.

34
Matt

Wenn Sie Ihre Blöcke als Argument an eine Methode in Ihrer Klasse übergeben, können Sie eine fantastische Code-Vervollständigung erhalten. In der Header-Datei habe ich den Block so geschrieben

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

Dann konnte ich es als Argument für meine Methode verwenden, die ich auch in diesem Klassenheader deklariert habe.

-(void)doThisWithBlock:(MyCompletionBlock)block;

In der m-Datei habe ich die Methode angegeben

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

und als ich ihn anrufen wollte, bekam ich den Code-Abschluss wie folgt. CodeCompletion1

CodeCompletion2

Hoffentlich beantwortet das Ihre Frage.

4
MobileOverlord

Ok, also habe ich einen Zwischenfall gefunden, der zu Warnungen/Fehlern führt ... und macht eigentlich Dinge einfacher lesen/kürzer schreiben usw.

definieren Sie ein Makro mit unserer "Abkürzung" und verwenden Sie dann das vollständige Format in der Eigenschaftsdeklaration wie ...

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

anschließend können Sie auf diese Art von Argumenten usw. verweisen.

+ (void)addInputBlock:(TINP)termDidReadString;

und voilá ... Ihr Code wird nicht nur TINIER sein !! Aber Code-Vervollständigung funktioniert wie ein Zauber ...

enter image description here

1
Alex Gray

Ich verstehe keine vollständigen Code-Vervollständigungen, aber Sie können Code-Snippets verwenden, um Code-Vervollständigung zu erhalten, und Sie können Platzhalter in Code-Snippets <#PLACE HOLDER #>. Verwenden. Ich hoffe, das hilft Ihnen 

0
Apps 4 U