#objective-c #memory-management #objective-c-blocks
#objective-c #управление памятью #objective-c-blocks
Вопрос:
Если у меня есть класс:
@interface A : NSObject
{
BOOL b;
id c;
}
@end
и ссылка b
и c
в блоке, блок сохраняется self
автоматически? Или просто b
и c
? О c
, это может быть сохранено само по себе, но как насчет b
?
Ответ №1:
Ответ Билла не совсем корректен:
Если у вас есть экземпляр A
и создайте блок внутри этого экземпляра следующим образом:
^{
b = YES;
}
Затем self
сохраняется (при копировании блока). b
не const
копируется, потому что b
на него строго ссылается self
, и только self
находится const
в пределах блока.
С другой стороны, если вы делаете:
BOOL aBool = YES;
^{
aBool = NO;
c = [[NSObject alloc] init];
}
Опять же, self
копируется const
(и сохраняется при копировании самого блока), и назначение c
разрешено. Однако присвоение aBOOL
не разрешено, поскольку значение aBool
скопировано. const
Другими словами, компилятор распознает, что b
и c
являются ivar, и будет сохранять self
вместо ivar напрямую.
Один из способов подумать об этом, который помогает мне понять, что происходит, — это помнить, что объект на самом деле является просто причудливой структурой, что означает, что технически вы можете получить доступ к ivars через оператор arrow: ->
Итак, когда вы обращаетесь к ivars:
b = YES;
эквивалентно:
self->b = YES;
В этом свете имеет смысл, почему вы должны сохранить self
, но b
это не const
так. Это потому, что b
это лишь небольшая часть «общей картины», и для того, чтобы получить b
, вы обязательно должны также включить все self
(поскольку копирование части структуры на самом деле не имеет смысла в этом контексте).
Комментарии:
1. в дополнение к этому, когда я передаю ‘self-> b’ методу, принадлежащему другому классу / экземпляру, или даже функции — скажите ‘foo(self-> b)’. foo объявляется как ‘foo(id SomeObject)’, а внутри foo находится всего один оператор ‘[SomeObject retain]’. В этом случае будет ли сохраняться только ‘b’ через ‘SomeObject’ или количество сохранений ‘self’ также увеличится? В моем понимании, как только ‘foo’ получит указатель на ‘b’ через ‘SomeObject’, он не узнает о ‘self’ и, следовательно, не сохранит ‘self’, только ‘b’. Это сомнение, которое у меня было с момента начала работы над ObjC — никогда не было возможности / необходимости его очищать!
2. будет сохранен только @Dev
b
Ответ №2:
Код из блока был бы полезен для ответа, но предполагая, что у вас есть что-то вроде этого;
^(A *a) {
[a doSomething];
}
a
будет сохранен блоком и освобожден, когда блок будет освобожден. С b
и c
ничего необычного не произойдет.
Если у вас есть что-то вроде;
^(id c, BOOL b) {
[c doSomethingElse];
}
Тогда блок c
будет сохранен и b
будет записан блоком как const
значение (т. Е. вы получите ошибку компилятора за выполнение b = NO
)
Более подробную информацию смотрите в документах;
Комментарии:
1. Спасибо! Я получил разъяснение по этим деталям 🙂
2. Оба этих примера показывают, что блок сохраняет что-то, переданное в качестве параметра блоку, а не захваченное из окружающей области. В документах нет ясности по этому вопросу, но я бы ожидал, что объекты, переданные в качестве параметров, не будут сохраняться неявно, поскольку они не определены до фактического вызова блока. Я что-то упускаю?
3. @Би Джей Гомер, ты прав. Примеры неверны. Но описания верны. Я не знаю, что произошло. Я ставлю 1 вместо выбора в качестве ответа.
4. @BJ Homer, я прочитал документацию о блоке, и этот ответ больше не выглядит правильным. developer.apple.com/library/ios/#documentation/cocoa/Conceptual /…