带有 Xcode 代码完成功能的 Objective-C 块属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9121466/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-14 23:11:59  来源:igfitidea点击:

Objective-C Block Property with Xcode code completion

iosobjective-cxcodexcode4objective-c-blocks

提问by Andrew

Is it possible to define an Objective-C block property but still have full-code completion in Xcode 4?

是否可以在 Xcode 4 中定义一个 Objective-C 块属性但仍然有完整的代码完成?

If I use a typedef to define the block:

如果我使用 typedef 来定义块:

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

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

and then define the property:

然后定义属性:

@property (nonatomic, copy) CompletionBlock completionBlock;

@property (nonatomic, copy) CompletionBlock completionBlock;

and then @synthesizethe property I don't get full code completion when calling the 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.

然后@synthesize属性我在调用 setter 时没有得到完整的代码完成。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);

@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 *)) { ... }

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

Finally, if I try to @synthesizeand then override the setter implementation or put the prototype in the header:

最后,如果我尝试@synthesize覆盖 setter 实现或将原型放在标题中:

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

- (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. Can I have my cake and eat it too?

发出警告,指出属性类型与访问器类型不匹配。无论我如何尝试修改语法,我都无法同时定义块属性和具有完整代码完成语法的 setter。我可以吃蛋糕也吃吗?

Thanks!

谢谢!

回答by Matt

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. So, let's add an explicit declaration for the setter of completionBlock:

接下来,正如 MobileOverload 在他的回答中指出的那样,我们知道如果在独立方法声明中使用,Xcode 会为 typedef 的块提供正确的代码完成。因此,让我们为 的 setter 添加显式声明completionBlock

- (void)setCompletionBlock:(CompletionBlock)completionBlock;

When called, this method resolves to the setter method declared by the property. However, because we explicitly defined it in the class interface, Xcode sees it and applies full code completion.

调用时,此方法解析为属性声明的 setter 方法。但是,因为我们在类接口中明确定义了它,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 @propertystatement should have different code completion than the same method defined on its own.

因此,如果您包含所有这三行,您应该会得到所需的结果。这种行为显然是 Xcode 的一个缺点,因为没有理由为什么在@property语句中定义的 setter应该具有与自己定义的相同方法不同的代码完成。

回答by MobileOverlord

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

当我去调用它时,我得到了这样的代码完成。 代码完成1

CodeCompletion2

代码完成2

Hopefully this answers your question.

希望这能回答你的问题。

回答by Alex Gray

Ok so I figured out a stopgap way of doing this that does't result in warnings / errors... andactually makes things easierto 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!! but code completion will work, like a charm...

瞧……你的代码不仅会更小!!但是代码完成会起作用,就像一个魅力......

enter image description here

在此处输入图片说明

回答by Apps 4 U

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#> . Hope this will help you

我不知道完整的代码完成,但您可以使用代码片段来获得类似行为的代码完成,并且您可以在代码片段中使用占位符 <#PLACE HOLDER#> 。希望能帮到你