Блокирует автоматическое сохранение, влияет ли это даже на ivar в self?

#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 )

Более подробную информацию смотрите в документах;

http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW1

Комментарии:

1. Спасибо! Я получил разъяснение по этим деталям 🙂

2. Оба этих примера показывают, что блок сохраняет что-то, переданное в качестве параметра блоку, а не захваченное из окружающей области. В документах нет ясности по этому вопросу, но я бы ожидал, что объекты, переданные в качестве параметров, не будут сохраняться неявно, поскольку они не определены до фактического вызова блока. Я что-то упускаю?

3. @Би Джей Гомер, ты прав. Примеры неверны. Но описания верны. Я не знаю, что произошло. Я ставлю 1 вместо выбора в качестве ответа.

4. @BJ Homer, я прочитал документацию о блоке, и этот ответ больше не выглядит правильным. developer.apple.com/library/ios/#documentation/cocoa/Conceptual /…