简体   繁体   English

具有Xcode代码完成的Objective-C Block属性

[英]Objective-C Block Property with Xcode code completion

Is it possible to define an Objective-C block property but still have full-code completion in Xcode 4? 是否可以定义Objective-C块属性但在Xcode 4中仍然具有完整代码完成?

If I use a typedef to define the block: 如果我使用typedef来定义块:

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

and then define the property: 然后定义属性:

@property (nonatomic, copy) CompletionBlock completionBlock;

and then @synthesize the property I don't get full code completion when calling the setter. 然后@synthesize属性我在调用setter时没有得到完整的代码完成。 Xcode will use the typedef and because of this, the code completion doesn't use the full block syntax complete with block parameters, it uses the typedef. Xcode将使用typedef,因此,代码完成不使用完整块语法完成块参数,它使用typedef。

If I define a method prototype in the header that uses the full block syntax instead of the typedef: 如果我在标头中定义了一个使用完整块语法而不是typedef的方法原型:

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

and then I use @synthesize , the provided setter comes close to using the full code completion syntax but crucially it leaves out the parameter names: 然后我使用@synthesize ,提供的setter接近使用完整的代码完成语法,但关键是它省略了参数名称:

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

Finally, if I try to @synthesize and then override the setter implementation or put the prototype in the header: 最后,如果我尝试@synthesize然后覆盖setter实现或将原型放在标题中:

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

A warning is raised stating that the property type does not match the accessor type. 会出现一条警告,指出属性类型与访问者类型不匹配。 No matter how I try to finagle the syntax, I'm not able to both define a block property and a setter that has the full syntax for code completion. 无论我如何尝试使用语法,我都无法定义块属性和具有完整代码完成语法的setter。 Can I have my cake and eat it too? 我可以吃蛋糕吗?

Thanks! 谢谢!

You can definitely have your cake and eat it too, if you are willing to add one extra line of code to your class interface. 如果你愿意为你的类界面添加一行额外的代码,你绝对可以吃蛋糕并吃掉它。

First, define block with a typedef and create a property like you did in your question: 首先,使用typedef定义块并像创建问题一样创建属性:

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

...

@property (nonatomic, copy) CompletionBlock completionBlock;

Next, as MobileOverload pointed out in his answer, we know that Xcode provides correct code completion for typedef'd blocks if used in a standalone method declaration. 接下来,正如MobileOverload在他的回答中指出的那样,我们知道如果在独立的方法声明中使用,Xcode为typedef'd块提供了正确的代码完成。 So, let's add an explicit declaration for the setter of completionBlock : 所以,让我们为completionBlock的setter添加一个显式声明:

- (void)setCompletionBlock:(CompletionBlock)completionBlock;

When called, this method resolves to the setter method declared by the property. 调用时,此方法解析为属性声明的setter方法。 However, because we explicitly defined it in the class interface, Xcode sees it and applies full code completion. 但是,因为我们在类接口中明确定义了它,所以Xcode会看到它并应用完整的代码完成。

So, if you include all three of those lines you should get the desired result. 因此,如果您包含所有这三行,您应该得到所需的结果。 This behavior is clearly a shortcoming of Xcode, as there is no reason why a setter defined in a @property statement should have different code completion than the same method defined on its own. 这种行为显然是Xcode的一个缺点,因为没有理由为什么@property语句中定义的setter应该具有与它自己定义的相同方法不同的代码完成。

You can get some fancy looking code completion when passing your blocks as an argument to a method in your class. 将块作为参数传递给类中的方法时,可以获得一些奇特的代码完成。 In the header file I typedef'd the block like this 在头文件中,我像这样键入了块

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

Then I was able to use it as an argument to my method that I have also declared in this class header. 然后我能够使用它作为我的方法的参数,我也在这个类头中声明了。

-(void)doThisWithBlock:(MyCompletionBlock)block;

In the m file I declared the method 在m文件中我声明了方法

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

and when I went to call it I got fancy code completion like this. 当我去打电话时,我得到了这样的花哨代码。 CodeCompletion1

CodeCompletion2

Hopefully this answers your question. 希望这能回答你的问题。

Ok so I figured out a stopgap way of doing this that does't result in warnings / errors... and actually makes things easier to read / shorter to type, etc. 好了,所以我想通了,这样做的权宜方式简化版,导致警告/错误...... 实际上使事情变得更容易阅读/短打字等

define a macro with our "abbreviation", and then use the full format in the property declaration like... 使用我们的“缩写”定义一个宏,然后在属性声明中使用完整格式,如...

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

subsequently.. you can then reference that "kind" of argument, etc like.. 随后..你可以参考那种“善意”的论点等...

+ (void)addInputBlock:(TINP)termDidReadString;

and voilá... not only will your code be TINIER!! 并且瞧...你的代码不仅会是TINIER !! but code completion will work, like a charm... 但代码完成将起作用,就像一个魅力......

在此输入图像描述

I dont know about full code completions but you can use code snippets to get code completion like behavior and you can use place holders in code snippets <#PLACE HOLDER#> . 我不知道完整的代码完成,但你可以使用代码片段来获得代码完成行为,你可以在代码片段中使用占位符<#PLACE HOLDER#>。 Hope this will help you 希望对你有帮助

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM