Just trying to get a handle on blocks. I get the concept. They're like function pointers, but they're actually objects; you can declare a block variable and assign it a block value; call it like a function; they get "frozen in time," for lack of a term, when they get executed, etc. I've created a few blocks and run them successfully, in a few different formats, but when it comes to using them in a method--either with a typedef or without--I'm having a lot of trouble. For example, here's an object interface I created, just to get a handle on the syntax. I have almost no idea how to implement it.
只是想试试块。我明白了。它们就像函数指针,但它们实际上是对象;你可以声明一个块变量并为它赋值一个块值;把它称为功能;他们得到“及时冻结”,缺乏一个术语,当他们被执行时等等。我已经创建了几个块并以几种不同的格式成功运行它们,但是当它在方法中使用时 - - 使用typedef或不使用 - 我遇到了很多麻烦。例如,这是我创建的对象接口,只是为了获得语法句柄。我几乎不知道如何实现它。
// AnObject.h
#import <Foundation/Foundation.h>
// The idea with the block and the method below is for the block to take
// an int, multiply it by 3, and return a "tripled" int. The method
// will then repeat: this process however many times the user wants via
// the howManyTimes parameter and return that value in the form of an int.
typedef int (^triple)(int);
@interface AnObject : NSObject
{
int num;
}
-(int)repeat:(int)howManyTimes withBlock:(triple)someBlock;
@end
Here's what I have for an implementation, so far:
到目前为止,这是我实现的内容:
#import "AnObject.h"
@implementation AnObject
@synthesize num;
-(int)repeat:(int)howManyTimes withBlock:(triple)someBlock {
for (int i = 0; i <= howManyTimes; i++) {
// What the heck am I supposed to put here? I'm baffled by the
// syntax over and over again.
}
}
@end
I know I'm not addressing the instance variable yet. Again, this is a rough draft, just trying to get a handle on how blocks work. Am I even declaring this method right? I'm reading Big Nerd Ranch's Objective-C Programming, Mike Clark's article on blocks from Pragmatic Studio, and several SO threads. Can't find anything relevant. Thanks.
我知道我还没有解决实例变量。再次,这是一个粗略的草案,只是试图了解块如何工作。我甚至宣布这种方法对吗?我正在阅读Big Nerd Ranch的Objective-C编程,Mike Clark关于Pragmatic Studio中的块的文章,以及几个SO线程。找不到任何相关的东西。谢谢。
EDIT: XCode 4.3.2, if it matters.
编辑:XCode 4.3.2,如果重要的话。
FURTHER EDIT: Ok. Using BJ's (slightly modified) example, I think I've come up with a really complicated way of multiplying 5 by 3. :)
进一步编辑:好的。使用BJ(稍加修改)的例子,我想我已经提出了一种将5乘以3的非常复杂的方法。:)
// BJ's implementation:
-(int)repeat:(int)howManyTimes withBlock:(Triple)someBlock {
int blockReturnValue;
for (int i = 0; i <= howManyTimes; i++) {
blockReturnValue = someBlock(i);
}
return blockReturnValue;
}
Main:
...
@autoreleasepool
{
AnObject *obj = [[AnObject alloc] init];
NSLog(@"%d", [obj repeat: 5 withBlock: ^ (int number) {
return number * 3;
}]);
}
return 0;
...
And the output is:
输出是:
15
Now, it's kicking back 15, because the block I defined as an argument is run only once, right? It multiplies "number," which is 5 in this case, by 3 and freezes that answer, right? I'm sure I just created a completely useless method, and I don't yet understand how to utilize the benefits/features of a block. Am I correct?
现在,它正在回击15,因为我定义为参数的块只运行一次,对吧?它将“数字”(在这种情况下为5)乘以3并冻结该答案,对吧?我确定我刚刚创建了一个完全没用的方法,我还不知道如何利用块的优点/功能。我对么?
/********************* UPDATE *********************/
/ *********************更新********************* /
UPDATE: I understand what you're saying, CRD. Just a correction though, for any new programmers who might be reading this, getting a different output and going, "Que?" Your for loop should be either:
更新:我明白你在说什么,CRD。但是,对于任何可能正在阅读此内容的新程序员来说,只需要进行修正,获得不同的输出并继续“Que?”你的for循环应该是:
for (int i = 0; i < howManyTimes; i++)
value = someBlock(value);
...or...
(i = 1; i <= howManyTimes; i++)
...to get the answer 243.
......得到答案243。
And, yes, this is exactly what I was initially trying to do with this code. At least that's what I thought was supposed to be happening. Turns out the author's intent wasn't to triple a number, store that value, triple the stored value, store that...etc., but rather just to print x * 3 for numbers 1-5 (3, 6, 9, 12, 15).
而且,是的,这正是我最初尝试使用此代码的原因。至少那是我认为应该发生的事情。原来,作者的意图不是将数字加倍,存储该值,存储值增加三倍,存储......等等,而只是为数字1-5打印x * 3(3,6,9, 12,15)。
Here is the finished product. I just typedef'd a block that takes an int and returns an int, called Tripler. I also changed the name of the argument from "someBlock" to "triple" to more clearly indicate the intended use of the block. I think those are the only changes to the code.
这是成品。我只是输入一个带有int的块并返回一个名为Tripler的int。我还将参数的名称从“someBlock”更改为“triple”以更清楚地指示块的预期用途。我认为这些是对代码的唯一更改。
/******************** interface ********************/
#import <Foundation/Foundation.h>
typedef int (^Tripler)(int);
@interface AnObject : NSObject
-(void)iterateFromOneTo:(int)number withBlock:(Tripler)triple;
@end
/******************** implementation ********************/
#import "AnObject.h"
@implementation AnObject
-(void)iterateFromOneTo:(int)number withBlock:(Tripler)triple {
for (int i = 1; i <= number; i++) {
NSLog(@"%d", triple(i));
}
}
@end
/******************** main.m ********************/
#import "AnObject.h"
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
@autoreleasepool
{
AnObject *obj = [[AnObject alloc] init];
[obj iterateFromOneTo:5 withBlock:^(int number) {
return number * 3;
}];
}
return 0;
}
As you can probably imagine, the resulting output is:
您可以想象,结果输出是:
2012-05-05 17:10:13.418 Untitled 2[71735:707] 3
2012-05-05 17:10:13.445 Untitled 2[71735:707] 6
2012-05-05 17:10:13.446 Untitled 2[71735:707] 9
2012-05-05 17:10:13.446 Untitled 2[71735:707] 12
2012-05-05 17:10:13.447 Untitled 2[71735:707] 15
I was making it a lot more complicated than it needed to be. Sorry for explaining it so poorly in the OP. Thanks for your help! /thread? :)
我让它变得比它需要的复杂得多。很抱歉在OP中解释得太差了。谢谢你的帮助! /线? :)
3 个解决方案
#1
7
Just call the block like a regular C function.
只需像普通的C函数一样调用块。
-(int)repeat:(int)howManyTimes withBlock:(triple)someBlock {
for (int i = 0; i <= howManyTimes; i++) {
int blockReturnValue = someBlock(i);
// do something with blockReturnValue
}
}
Update after your "further edit"
“进一步编辑”后更新
No, the block you passed in as an argument is run five times, each pass through the for loop.
不,您作为参数传入的块运行五次,每次都通过for循环。
- The first time, it invokes the block with
1
as the argument, and gets back3
. It stores that inblockReturnValue
, then goes on to the next iteration of the loop. - The second time, it invokes the block with
2
as the argument, and gets back6
. It stores that inblockReturnValue
, completely overwriting the value we stored there in the previous pass. - The third time, it inbokes the block with
3
as the argument, and gets back9
. Again, it overwrites the value inblockReturnValue
. - The fourth time, we store
12
inblockReturnValue
. - The fifth time, we store
15
inblockReturnValue
.
第一次,它调用带有1作为参数的块,然后返回3.它将它存储在blockReturnValue中,然后继续循环的下一次迭代。
第二次,它调用带有2作为参数的块,然后返回6.它将它存储在blockReturnValue中,完全覆盖我们在前一遍中存储的值。
第三次,它以3作为参数来阻止块,然后返回9.再次,它覆盖了blockReturnValue中的值。
第四次,我们在blockReturnValue中存储了12个。
第五次,我们在blockReturnValue中存储了15个。
Then we exit the for loop, and return 15. So yes, you're correct that you've made a pointless method to multiply by 3. But you're doing it in a way that also does a bunch of useless calculations.
然后我们退出for循环,并返回15.所以是的,你是正确的,你已经做了一个无意义的方法乘以3.但你这样做的方式也做了一堆无用的计算。
#2
8
From reading your question I understood, or maybe misunderstood, that your intention was to produce the result of applying your block n times; e.g. if you applied a tripling function twice you'd get the original value multiplied by nine.
从阅读你的问题我理解,或者可能被误解,你的意图是产生你的块的n次结果;例如如果你应用了两次三倍函数,你会得到原始值乘以9。
Just in case it helps, here is the code to do that:
万一它有帮助,这里有代码:
@interface AnObject
typedef int (^monadic)(int); // an function which takes an int and return an int
- (int) repeat:(int)howManyTimes for:(int)value withBlock:(monadic)someBlock;
@end
@implementation AnObject
- (int) repeat:(int)howManyTimes for:(int)value withBlock:(monadic)someBlock
{
for (int i = 0; i < howManyTimes; i++)
value = someBlock(value);
return value;
}
@end
Now call this with:
现在打电话给:
AnObject *myObject = [AnObject new];
int z = [myObject repeat:5
for:1
withBlock: ^(int number)
{
return number * 3;
}
];
and z
will have the value 243
.
和z将具有值243。
#3
1
@import Foundation;
typedef int(^MyBlockType)(int);
@implementation NSObject(extra)
+ (int)invokeBlock:(MyBlockType)block withArgument:(int)arg
{
return block(arg);
}
@end;
int main() {
@autoreleasepool {
NSLog(@"executeBlock(3) returns %d",
[NSObject invokeBlock:^(int param) { return param * param; } withArgument:3]);
} return 0;
}
#1
7
Just call the block like a regular C function.
只需像普通的C函数一样调用块。
-(int)repeat:(int)howManyTimes withBlock:(triple)someBlock {
for (int i = 0; i <= howManyTimes; i++) {
int blockReturnValue = someBlock(i);
// do something with blockReturnValue
}
}
Update after your "further edit"
“进一步编辑”后更新
No, the block you passed in as an argument is run five times, each pass through the for loop.
不,您作为参数传入的块运行五次,每次都通过for循环。
- The first time, it invokes the block with
1
as the argument, and gets back3
. It stores that inblockReturnValue
, then goes on to the next iteration of the loop. - The second time, it invokes the block with
2
as the argument, and gets back6
. It stores that inblockReturnValue
, completely overwriting the value we stored there in the previous pass. - The third time, it inbokes the block with
3
as the argument, and gets back9
. Again, it overwrites the value inblockReturnValue
. - The fourth time, we store
12
inblockReturnValue
. - The fifth time, we store
15
inblockReturnValue
.
第一次,它调用带有1作为参数的块,然后返回3.它将它存储在blockReturnValue中,然后继续循环的下一次迭代。
第二次,它调用带有2作为参数的块,然后返回6.它将它存储在blockReturnValue中,完全覆盖我们在前一遍中存储的值。
第三次,它以3作为参数来阻止块,然后返回9.再次,它覆盖了blockReturnValue中的值。
第四次,我们在blockReturnValue中存储了12个。
第五次,我们在blockReturnValue中存储了15个。
Then we exit the for loop, and return 15. So yes, you're correct that you've made a pointless method to multiply by 3. But you're doing it in a way that also does a bunch of useless calculations.
然后我们退出for循环,并返回15.所以是的,你是正确的,你已经做了一个无意义的方法乘以3.但你这样做的方式也做了一堆无用的计算。
#2
8
From reading your question I understood, or maybe misunderstood, that your intention was to produce the result of applying your block n times; e.g. if you applied a tripling function twice you'd get the original value multiplied by nine.
从阅读你的问题我理解,或者可能被误解,你的意图是产生你的块的n次结果;例如如果你应用了两次三倍函数,你会得到原始值乘以9。
Just in case it helps, here is the code to do that:
万一它有帮助,这里有代码:
@interface AnObject
typedef int (^monadic)(int); // an function which takes an int and return an int
- (int) repeat:(int)howManyTimes for:(int)value withBlock:(monadic)someBlock;
@end
@implementation AnObject
- (int) repeat:(int)howManyTimes for:(int)value withBlock:(monadic)someBlock
{
for (int i = 0; i < howManyTimes; i++)
value = someBlock(value);
return value;
}
@end
Now call this with:
现在打电话给:
AnObject *myObject = [AnObject new];
int z = [myObject repeat:5
for:1
withBlock: ^(int number)
{
return number * 3;
}
];
and z
will have the value 243
.
和z将具有值243。
#3
1
@import Foundation;
typedef int(^MyBlockType)(int);
@implementation NSObject(extra)
+ (int)invokeBlock:(MyBlockType)block withArgument:(int)arg
{
return block(arg);
}
@end;
int main() {
@autoreleasepool {
NSLog(@"executeBlock(3) returns %d",
[NSObject invokeBlock:^(int param) { return param * param; } withArgument:3]);
} return 0;
}