是否有可能使用标准属性语法将块作为属性?
ARC有什么变化吗?
是否有可能使用标准属性语法将块作为属性?
ARC有什么变化吗?
当前回答
Disclamer
这并不是“好的答案”,因为这个问题明确地要求objective - c。苹果在WWDC14上介绍了Swift,我想分享一下在Swift中使用block(或闭包)的不同方式。
你好,迅速
在Swift中,你有很多方法来传递一个相当于函数的块。
我找到了三个。
为了理解这一点,我建议你在操场上测试这一小段代码。
func test(function:String -> String) -> String
{
return function("test")
}
func funcStyle(s:String) -> String
{
return "FUNC__" + s + "__FUNC"
}
let resultFunc = test(funcStyle)
let blockStyle:(String) -> String = {s in return "BLOCK__" + s + "__BLOCK"}
let resultBlock = test(blockStyle)
let resultAnon = test({(s:String) -> String in return "ANON_" + s + "__ANON" })
println(resultFunc)
println(resultBlock)
println(resultAnon)
Swift,针对闭包进行了优化
由于Swift针对异步开发进行了优化,苹果在闭包方面投入了更多精力。 首先,函数签名可以被推断出来,所以你不必重写它。
通过数字访问参数
let resultShortAnon = test({return "ANON_" + $0 + "__ANON" })
带有命名的参数推断
let resultShortAnon2 = test({myParam in return "ANON_" + myParam + "__ANON" })
后关闭
只有当block是最后一个参数时,这种特殊情况才有效,它被称为尾随闭包
下面是一个例子(与推断签名合并以显示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!")
}
}
其他回答
您可以遵循下面的格式,并在类中使用testingObjectiveCBlock属性。
typedef void (^testingObjectiveCBlock)(NSString *errorMsg);
@interface MyClass : NSObject
@property (nonatomic, strong) testingObjectiveCBlock testingObjectiveCBlock;
@end
更多信息请看这里
你好,迅速
补充@Francescu的回答。
添加额外参数:
func test(function:String -> String, param1:String, param2:String) -> String
{
return function("test"+param1 + param2)
}
func funcStyle(s:String) -> String
{
return "FUNC__" + s + "__FUNC"
}
let resultFunc = test(funcStyle, "parameter 1", "parameter 2")
let blockStyle:(String) -> String = {s in return "BLOCK__" + s + "__BLOCK"}
let resultBlock = test(blockStyle, "parameter 1", "parameter 2")
let resultAnon = test({(s:String) -> String in return "ANON_" + s + "__ANON" }, "parameter 1", "parameter 2")
println(resultFunc)
println(resultBlock)
println(resultAnon)
@ property(副本)无效
@property (copy)void (^doStuff)(void);
实际的苹果文档,它精确地说明了使用什么:
苹果doco。
你的。h文件:
// 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();
}
注意过时的示例代码。
对于现代(2014+)系统,这是正确的和文档化的方法。
@property (nonatomic, copy) void (^simpleBlock)(void);
@property (nonatomic, copy) BOOL (^blockWithParamter)(NSString *input);
如果你要在几个地方重复同一个块,请使用类型def
typedef void(^MyCompletionBlock)(BOOL success, NSError *error);
@property (nonatomic) MyCompletionBlock completion;
下面是一个如何完成这样一个任务的例子:
#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),并将你的块更改为:
^ (id obj1, id obj2)
{
return rand();
};
2012年3月12日编辑:
对于ARC,不需要进行特定的更改,因为ARC将为您管理这些块,只要它们被定义为副本。你也不需要在析构函数中将属性设置为nil。
如需更多阅读,请查看以下文件: http://clang.llvm.org/docs/AutomaticReferenceCounting.html