简体   繁体   English

Objective-C块参数

[英]Objective-C block parameters

Say we have this block: 假设我们有这个块:

int (^aBlock)(BOOL) = ^(BOOL param) { ...

My current understanding of this is: the first int is the return type, (^aBlock)(BOOL) gives the name of the method and the type of its parameter, and = ^(BOOL param) is the parameter's name inside the block ... plus the parameter's type again? 我目前对此的理解是:第一个int是返回类型, (^aBlock)(BOOL)给出方法的名称及其参数的类型,而= ^(BOOL param)是块内的参数名称。 ..再次加上参数的类型?

Why is the syntax such that we have to list the parameter type twice? 为什么语法必须列出参数类型两次? Could the two types ever be different? 这两种类型可能会有所不同吗?

It is not quite "listing the parameter type twice", you are in the first case declaring the type of a block variable , and in the second case you are defining a block literal . 它不是“两次列出参数类型”,你在第一种情况下声明一个块变量类型 ,在第二种情况下你定义一个块文字 Then you are assigning the literal to the value of the variable. 然后,您将文字分配给变量的值。 You could even do something like this, which is equivalent and better illustrates the fact that these are really two totally independent declarations, despite being associated with an assign statement: 你甚至可以做这样的事情,这是相同的,并且更好地说明了这些事实上是两个完全独立的声明,尽管与assign语句相关联:

id thisBlock = ^id (id x, NSUInteger idx) {
    NSLog(@"x = %@",x);
    return x;
};

id (^thatBlock)(id obj, NSUInteger index) = thisBlock;

The fact that they are independent of each other means it's probably not even correct to attempt to provide some kind of transference or inheritance of typing information from the left hand side of the expression to the right. 它们彼此独立的事实意味着尝试从表达式的左侧向右侧提供某种类型的输入信息的转移或继承可能是不正确的。 And yes, the types can be different - consider this code compiles and executes just fine: 是的,类型可以是不同的 - 考虑这个代码编译并执行得很好:

id (^thatBlock)(NSArray *, NSDictionary *, NSString *) = ^id (id x, id y, id z) {
    NSLog(@"x = %@",x);
    return x;
};

thatBlock(@[],@{},@"");

Hope this helps! 希望这可以帮助!

Why is the syntax such that we have to list the parameter type twice? 为什么语法必须列出参数类型两次?

The block is designed in this way, and so you can do it like this: 块是以这种方式设计的,所以你可以这样做:

int (^aBlock)(BOOL);

aBlock = ^(BOOL param) {
  ...
};

It just likes 它只是喜欢

- (int)aMethodWithParam:(BOOL)param;

- (int)aMethodWithParam:(BOOL)param {
  ...
}

Could the two types ever be different? 这两种类型可能会有所不同吗?

Nope, and what's more, the order of the types should be the same, ie: 不,而且类型的顺序应该是相同的,即:

int (^aBlock)(BOOL, NSString*) = ^(BOOL param, NSString *aString) {
  ...
};

And here's a clear figure for block: 这里有一个清晰的数字块:

图片

The code snippet you have given isn't a block declaration: it's a block declaration and a block definition. 您给出的代码片段不是块声明:它是块声明块定义。 First, you declare an identifier named aBlock : 首先,声明一个名为aBlock的标识符:

int (^aBlock)(BOOL)

then you define a block: 然后你定义一个块:

^(BOOL param) { ...

Both of these are parsed and evaluated separately. 这两个都是分别解析和评估的。 Since you are assigning one to the other, the compiler does a type-check to make sure that the expression on the left hand side (your aBlock declaration) is of the same type as the expression on the right hand side (the block definition). 由于您要将一个分配给另一个,因此编译器会进行类型检查以确保左侧的表达式(您的aBlock声明)与右侧的表达式(块定义)的类型相同。

So, the answer is, these parts need to be evaluated separately. 因此,答案是,这些部分需要单独评估。 Since the block definition is being compiled on its own, you have to include the type of param , because otherwise the compiler won't know what type it should be. 由于块定义是自己编译的,因此必须包含param的类型,否则编译器将不知道它应该是什么类型。 (Yes, you could make an exception in this case, and look across the assignment, but everywhere else in the C language you declare an identifier by giving a type first, so why do it differently here?) (是的,你可以在这种情况下做一个例外,并查看作业,但是在C语言的其他地方你通过首先给出一个类型来声明一个标识符,那么为什么在这里有不同的呢?)

But -- you may say -- if that's true why didn't I have to define the return type ( int ) on the right-hand side? 但是 - 您可能会说 - 如果这是真的,为什么我不必在右侧定义返回类型( int )?

Very astute of you. 非常精明的你。 The answer is that, when writing a block expression, you don't need to define the return type, because the compiler can infer it from the return statement (or lack thereof) inside the block. 答案是,在编写块表达式时,您不需要定义返回类型,因为编译器可以从块内的return语句(或缺少语句)推断它。

(So why do you have to include return types with function definitions? Well, history, I guess. Programming language definitions were created by imperfect humans.) (那么为什么你必须包含带有函数定义的返回类型?嗯,历史,我猜。编程语言定义是由不完美的人创建的。)

According to Ry's Objective C Tutorial : 根据Ry的Objective C教程

Blocks use all the same mechanics as normal functions. 块使用与普通函数相同的所有机制。 You can declare a block variable just like you would declare a function. 您可以像声明函数一样声明块变量。

 NSInteger (^BlocksAddition)(NSInteger x,NSInteger y)=^NSInteger(NSInteger x, NSInteger y){

    return x+y;
};

NSUInteger result=BlocksAddition(4,5);
NSLog(@"Addition Result:%d",result);

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

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