Короткий ответ: объекты всегда размещаются в куче, а не в стеке.
Хотя это далеко не вся история. В Objective-C блоки также являются полноценными объектами Objective-C. Они отличаются тем, что иногда находятся в стеке. В частности, блоки, созданные с синтаксисом блочного литерала и ссылающиеся на окружающую область, находятся в стеке. Вы даже можете увидеть это, если проверите их класс, который будет (приватным) NSStackBlock
. Если вы скопируете их с помощью Block_copy()
или -copy
, результирующая копия будет в куче (NSMallocBlock
).
Одним из следствий этого является то, что блоки, размещенные в стеке, действительны только до конца области, в которой они были созданы. До ARC (а также IIRC в ранней версии ARC) это означало, что вам приходилось копировать блоки, которые вы хотели использовать, за пределы их области создания, чтобы они были в куче. ARC обрабатывает это за вас в большинстве случаев, а также означает, что труднее предсказать, находится ли блок в стеке или в куче.
Эта небольшая тестовая программа показывает это (компилировать с выключенным ARC):
#import <Foundation/Foundation.h>
// Compile this without ARC.
int main(int argc, char *argv[]) {
@autoreleasepool {
NSMutableString *string = [NSMutableString stringWithString:@"foo"];
void(^stackBlock)() = ^{
[string setString:@"bar"];
};
NSLog(@"stackBlock class: %@", NSStringFromClass([stackBlock class]));
void(^heapBlock)() = [[stackBlock copy] autorelease];
NSLog(@"heapBlock class: %@", NSStringFromClass([heapBlock class]));
}
}
Выход:
stackBlock class: __NSStackBlock__
heapBlock class: __NSMallocBlock__
(Просто для ясности: вам определенно не следует использовать проверку NSStackBlock
/NSMallocBlock
в реальном коде. Это частные классы деталей реализации. Этот код предназначен только для демонстрации.)
person
Andrew Madsen
schedule
18.12.2013