是否有可能使用标准属性语法将块作为属性?

ARC有什么变化吗?


当前回答

下面是一个如何完成这样一个任务的例子:

#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

其他回答

@ 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+)系统,这是正确的和文档化的方法。

下面是一个如何完成这样一个任务的例子:

#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

你好,迅速

补充@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)

您可以遵循下面的格式,并在类中使用testingObjectiveCBlock属性。

typedef void (^testingObjectiveCBlock)(NSString *errorMsg);

@interface MyClass : NSObject
@property (nonatomic, strong) testingObjectiveCBlock testingObjectiveCBlock;
@end

更多信息请看这里

当然,您可以使用块作为属性。但是要确保它们被声明为@property(copy)。例如:

typedef void(^TestBlock)(void);

@interface SecondViewController : UIViewController
@property (nonatomic, copy) TestBlock block;
@end

在MRC中,捕获上下文变量的块分配在堆栈中;当堆栈帧被销毁时,它们将被释放。如果复制了它们,将在堆中分配一个新的块,该块可以在堆栈帧弹出后执行。