ObjC:委托与块的内存使用情况?

hzx*_*zxu 5 delegates objective-c ios objective-c-blocks

我正在比较Objective-C中委托与块的内存占用,以解决同样的问题.例如,有一个工人阶级做了一些工作:

// delegate
@protocol WorkerDelegate : NSObject
- (void)workHasBeenDone;
@end

// block
typedef void (^WorkerBlock)();

@interface Worker : NSObject

@property (nonatomic, weak) id<WorkerDelegate> delegate;

@property (nonatomic, copy) WorkerBlock block;

- (void)doTheWork;

@end
Run Code Online (Sandbox Code Playgroud)

代码是不言自明的,为了知道工作何时完成,我可以使用委托或块:

@implementation MyObject

- (void)workHasBeenDone
{
    [self doCleanUp];
}

- (void)entryMethod
{
    Worker *worker = [Worker new];
    worker.delegate = self;
    // or:
    worker.block = ^{[self doCleanUp];};
    [worker doTheWork];
}

@end
Run Code Online (Sandbox Code Playgroud)

据我所知,在上面的代码中,self作为代理,是在内存中; 并且它block被复制到堆上,但我不确定,哪个内存占用更好?

现在我需要一些工人:

Worker *workerA = ... // created and set delegate OR block for completion notification
Worker *workerB = ... // created and set delegate OR block for completion notification
Worker *workerC = ... // created and set delegate OR block for completion notification
...

NSDictionary *workers = @{
    "jobA": workerA,
    "jobB": workerB,
    ...
};
Run Code Online (Sandbox Code Playgroud)

在这种情况下,块看起来更干净,但是,它是否有更好,相同或更差的内存占用?

非常感谢!

ric*_*ter 10

块是一个ObjC对象,因此它具有相同的内存使用量.你正在思考多个问题的正确道路Worker- 如果你想对所有问题进行同样的清理,会发生什么?

有代表:

workerA.delegate = workerB.delegate = workerC.delegate = self;

//...

- (void)workHasBeenDoneWithWorker:(Worker *)worker {
    //...
}
Run Code Online (Sandbox Code Playgroud)

这里有三个对同一对象的弱引用,因此没有额外的存储或所有权要求.并且相同的workHasBeenDoneWithWorker:方法被调用三次.(注意我改变了一点 - 委托方法知道是谁调用它是有好处的,正是因为这个原因:一个对象可以是多个其他对象的委托,它可能想知道它已被委派的工作.)

现在,使用块:

workerA.block = workerB.block = workerC.block = ^{ [self doCleanUp]; };
Run Code Online (Sandbox Code Playgroud)

因为您的块已声明@property (copy),所以这将获得该块的三个副本.即使它的源代码相同,每个的内部和捕获状态也会不同.此外,没有办法(如声明的那样)让块知道它正在做的工作......如果你在参考Worker它所属的块中添加了一个参数,你就必须小心参考周期.内存使用差异很小,但API架构差异更为显着.

一般来说,代表在以下情况下工作良好:

  • 多个委派对象可能共享同一个委托
  • 对于同一委托对象,可能会多次调用相同的委托方法

并且(完成处理程序样式)块在以下情况下运行良好:

  • 工作将完成一次,块将被调用一次,然后块将被丢弃
  • 完成任务与设置任务密切相关,因此块捕获周围状态的能力很有价值