// Here is a block as a property:
//
// Someone passes you a block. You "hold on to it",
// while you do other stuff. Later, you use the block.
//
// The property 'doStuff' will hold the incoming block.
@property (copy)void (^doStuff)(void);
// Here's a method in your class.
// When someone CALLS this method, they PASS IN a block of code,
// which they want to be performed after the method is finished.
-(void)doSomethingAndThenDoThis:(void(^)(void))pleaseDoMeLater;
// We will hold on to that block of code in "doStuff".
这是你的.m文件:
-(void)doSomethingAndThenDoThis:(void(^)(void))pleaseDoMeLater
{
// Regarding the incoming block of code, save it for later:
self.doStuff = pleaseDoMeLater;
// Now do other processing, which could follow various paths,
// involve delays, and so on. Then after everything:
[self _alldone];
}
-(void)_alldone
{
NSLog(@"Processing finished, running the completion block.");
// Here's how to run the block:
if ( self.doStuff != nil )
self.doStuff();
}
let resultShortAnon = test({return "ANON_" + $0 + "__ANON" })
使用命名的参数推断
let resultShortAnon2 = test({myParam in return "ANON_" + myParam + "__ANON" })
尾随关闭
这种特殊情况只有在块是最后一个参数时才有效,它被称为尾随闭包
这是一个例子(与推断签名合并以显示Swift权力)
let resultTrailingClosure = test { return "TRAILCLOS_" + $0 + "__TRAILCLOS" }
最后:
使用所有这些功能,我要做的是混合尾随闭包和类型推断(为了可读性而命名)
PFFacebookUtils.logInWithPermissions(permissions) {
user, error in
if (!user) {
println("Uh oh. The user cancelled the Facebook login.")
} else if (user.isNew) {
println("User signed up and logged in through Facebook!")
} else {
println("User logged in through Facebook!")
}
}
0
以下是您将如何完成此任务的示例:
#import <Foundation/Foundation.h>
typedef int (^IntBlock)();
@interface myobj : NSObject
{
IntBlock compare;
}
@property(readwrite, copy) IntBlock compare;
@end
@implementation myobj
@synthesize compare;
- (void)dealloc
{
// need to release the block since the property was declared copy. (for heap
// allocated blocks this prevents a potential leak, for compiler-optimized
// stack blocks it is a no-op)
// Note that for ARC, this is unnecessary, as with all properties, the memory management is handled for you.
[compare release];
[super dealloc];
}
@end
int main () {
@autoreleasepool {
myobj *ob = [[myobj alloc] init];
ob.compare = ^
{
return rand();
};
NSLog(@"%i", ob.compare());
// if not ARC
[ob release];
}
return 0;
}
现在,如果你需要改变比较类型,唯一需要改变的是 typedef int (^IntBlock)() . 如果需要将两个对象传递给它,请将其更改为: typedef int (^IntBlock)(id, id) ,并将块更改为:
8 回答
Hello, Swift
补充@Francescu回答的内容 .
添加额外参数:
如果您要在几个地方重复相同的块,请使用类型def
为了后人/完整性的缘故......以下是两个如何实现这种荒谬的多功能“做事方式”的完整例子 . @Robert的答案很简洁,也很正确,但在这里我还要展示实际“定义”块的方法 .
愚蠢?是 . 有用? Hells yeah. 这是一种不同的,"more atomic"设置属性的方法..以及一个非常有用的类......
这说明了通过访问器设置块属性(尽管在init内部,这是一种令人沮丧的冒险行为......)与第一个示例的"nonatomic" "getter"机制相比 . 在任何一种情况下...... "hardcoded"实现总是可以被覆盖,每个实例..一个lá..
另外..如果你想在一个类别中添加一个块属性...说你想使用一个Block而不是一些老式的目标/动作“动作”...你可以使用相关的值,好吧..关联块 .
现在,当你创建一个按钮时,你不必设置一些
IBAction
戏剧 . 只需关联创建时要完成的工作......这种模式可以应用于Cocoa API的OVER和OVER . 使用属性可以使代码的相关部分更加紧密,消除错综复杂的委托范例,并利用对象的力量,而不仅仅是作为哑巴"containers" .
当然你可以使用块作为属性 . 但要确保它们被声明为 @property(copy) . 例如:
在MRC中,捕获上下文变量的块在 stack 中分配;它们将在堆栈帧被破坏时被释放 . 如果复制它们,将在 heap 中分配一个新块,该块可以在堆栈帧被加载后稍后执行 .
对于Swift,只需使用闭包:example.
在Objective-C中,
@property(copy)void(^ doStuff)(void);
就这么简单 .
Apple的文档,充分解释了这个问题:
Apple doco.
在你的.h文件中:
这是你的.m文件:
小心过时的示例代码 .
使用现代(2014)系统,执行此处显示的内容 . 就这么简单 . 希望它可以帮到某人 . 2013年圣诞快乐!
免责声明
这不是“好答案”,因为这个问题明确要求ObjectiveC . 当Apple在WWDC14上介绍Swift时,我想分享在Swift中使用块(或闭包)的不同方法 .
你好,斯威夫特
你有很多方法可以在Swift中传递一个等效于函数的块 .
我发现了三个 .
为了理解这一点,我建议你在游乐场测试这段小代码 .
Swift,针对封口进行了优化
由于Swift针对异步开发进行了优化,因此Apple在闭包方面的工作量更大 . 首先是可以推断出函数签名,因此您不必重写它 .
按号码访问参数
使用命名的参数推断
尾随关闭
这种特殊情况只有在块是最后一个参数时才有效,它被称为尾随闭包
这是一个例子(与推断签名合并以显示Swift权力)
最后:
使用所有这些功能,我要做的是混合尾随闭包和类型推断(为了可读性而命名)
以下是您将如何完成此任务的示例:
现在,如果你需要改变比较类型,唯一需要改变的是
typedef int (^IntBlock)()
. 如果需要将两个对象传递给它,请将其更改为:typedef int (^IntBlock)(id, id)
,并将块更改为:我希望这有帮助 .
编辑2012年3月12日:
对于ARC,不需要进行任何特定更改,因为ARC将为您管理块,只要它们被定义为副本即可 . 您也不需要在析构函数中将属性设置为nil .
欲了解更多信息,请查看此文件:http://clang.llvm.org/docs/AutomaticReferenceCounting.html
您可以按照以下格式使用,也可以使用类中的
testingObjectiveCBlock
属性 .欲了解更多信息,请查看here