Копировать блок между объектами
Я всегда думал, что copy
просто скопировать объект. В случае блоков все немного по-другому, но я очень удивлен, как это работает в следующем случае.
У меня есть и экземпляр objectA
а также objectB
следующего класса:
@interface MyObject : NSObject
@property(nonatomic, copy) void (^myHandler)(CGFloat progress);
@property(nonatomic) CGFloat progress;
@end
objectA
пустой. objectB
имеет установленные значения. В какой-то момент приложения я хочу отказаться objectB
и оставить только objectA
так что мне нужно ввести эти два значения objectB
в objectA
:
MyObject *objectA = [MyObject new];
if (nowIWantToGetRidOfB) {
objectA.progress = objectB.progress;
objectA.myHandler = objectB.myHandler;
objectB.myHandler = nil;
objectB = nil; // that's just an example to show it gets released after this code
}
Я ожидаю, что блок будет скопирован в новый objectA
экземпляр и objectB
быть выпущенным (потому что нет ссылки, указывающей на это).
Но вместо этого ничего не происходит. Блок, даже если и должен, никогда больше не оценивается. Должен ли я скопировать его по-другому? Может кто-нибудь объяснить, что и почему происходит, или указать на какую-то документацию, которая это объяснит?
-- редактировать --
Фрагмент, как установлен блок:
MyObject *objectB = [MyObject new];
objectB.progress = 0.5f;
[objectB setProgressHandler:^(CGFloat progress) {
NSLog(@"example");
}];
1 ответ
Помимо вопроса в моем комментарии, это, вероятно, не работает в любом случае.
Блоки - это не только фрагмент кода, но и замыкания. Это означает, что они делают снимок момента времени, когда они были созданы. Если такой блок относится к objectB
во время создания, после копирования они все равно будут ссылаться на этот объект, даже если вы сохраните блок или его копию в objectA
, (Объекты экземпляра не имеют идентификаторов, однако, я думаю, я понимаю, что вы имеете в виду.)
Итак, имея этот код:
MyObject *objectB = …;
objectB.handler = ^(CGFloat progress)
{
… objectB …
}
Что-то будет сделано с objectB
, После копирования (здесь явно) …
MyObject *objectA = …;
objectA.handler = objectB.handler;
... это все то же самое: что-то будет сделано с objectB
потому что он все еще ссылается на блок.