Переход к информации о версии ARC
Automatic Reference Counting (ARC) является функцией компилятора, обеспечивающей автоматическое управление памятью объектов Objective C. Вместо того, чтобы иметь необходимость думать о сохраняют и выпускают операции, ARC позволяет Вам концентрироваться на интересном коде, графах объектов и отношениях между объектами в Вашем приложении.
Сводка
ARC работает путем добавления кода во время компиляции, чтобы гарантировать, чтобы объекты жили настолько же долго по мере необходимости, но больше. Концептуально, это следует тем же соглашениям управления памятью как подсчет ссылки на руководство (описанный в Усовершенствованном Руководстве по программированию управления памятью) путем добавления, что надлежащее управление памятью зовет Вас.
Для компилятора для генерации корректного кода ARC ограничивает методы, которые можно использовать и как Вы используете бесплатное образование моста (см. Бесплатные Соединенные мостом Типы). ARC также представляет новые пожизненные спецификаторы для ссылок на объект и объявленных свойств.
ARC поддерживается в Xcode 4.2 для OS X v10.6 и v10.7 (64-разрядные приложения) и для iOS 4 и iOS 5. Слабые ссылки не поддерживаются в OS X v10.6 и iOS 4.
XCode обеспечивает инструмент, автоматизирующий механические детали преобразования ARC (такие как удаление retain
и release
вызовы), и помогает Вам устранить проблемы, которые мигрант не может обработать автоматически (выберите Edit> Refactor> Convert to Objective-C ARC). Инструмент миграции преобразовывает все файлы в проекте использовать ARC. Можно также принять решение использовать ARC на основе на файл, если более удобно для Вас использовать ссылку на руководство, значащую некоторые файлы.
См. также:
Обзор ARC
Вместо Вас имеющий необходимость помнить, когда использовать retain
, release
, и autorelease
, ARC оценивает пожизненные требования Ваших объектов и автоматически вставляет надлежащее управление памятью, зовет Вас во время компиляции. Компилятор также генерирует надлежащий dealloc
методы для Вас. В целом, если Вы только используете ARC, традиционные соглашения о присвоении имен Какао важны, только если необходимо взаимодействовать с кодом, использующим подсчет ссылки на руководство.
Полная и корректная реализация a Person
класс мог бы быть похожим на это:
@interface Person : NSObject |
@property NSString *firstName; |
@property NSString *lastName; |
@property NSNumber *yearOfBirth; |
@property Person *spouse; |
@end |
@implementation Person |
@end |
(Свойства объектов strong
по умолчанию; strong
атрибут описан в ARC, Представляет Новые Пожизненные Спецификаторы.)
Используя ARC, Вы могли реализовать изобретенный метод как это:
- (void)contrived { |
Person *aPerson = [[Person alloc] init]; |
[aPerson setFirstName:@"William"]; |
[aPerson setLastName:@"Dudney"]; |
[aPerson setYearOfBirth:[[NSNumber alloc] initWithInteger:2011]]; |
NSLog(@"aPerson: %@", aPerson); |
} |
ARC заботится об управлении памятью так, чтобы ни один Person
ни NSNumber
объекты пропущены.
Вы могли также безопасно реализовать a takeLastNameFrom:
метод Person
как это:
- (void)takeLastNameFrom:(Person *)person { |
NSString *oldLastname = [self lastName]; |
[self setLastName:[person lastName]]; |
NSLog(@"Lastname changed from %@ to %@", oldLastname, [self lastName]); |
} |
ARC гарантирует это oldLastName
не освобожден перед NSLog
оператор.
ARC осуществляет новые правила
Для работы ARC навязывает некоторые новые правления, не присутствующие при использовании других режимов компилятора. Правила предназначаются для обеспечения полностью надежной модели управления памятью; в некоторых случаях они просто осуществляют наиболее успешную практику в некоторых других, они упрощают Ваш код или являются очевидными заключениями Вашего не необходимость иметь дело с управлением памятью. Если Вы нарушаете эти правила, Вы получаете непосредственную ошибку времени компиляции, не тонкую ошибку, которая может стать очевидной во время выполнения.
Вы не можете явно вызвать
dealloc
, или реализуйте или вызовитеretain
,release
,retainCount
, илиautorelease
.Запрет расширяется на использование
@selector(retain)
,@selector(release)
, и т.д.Можно реализовать a
dealloc
метод, если необходимо управлять ресурсами кроме выпуска переменных экземпляра. Вы не имеете к (действительно, Вы не можете) выпускать переменные экземпляра, но Вы, возможно, должны вызвать[systemClassInstance setDelegate:nil]
на системных классах и другом коде, не компилирующемся с помощью ARC.Пользовательский
dealloc
методы в ARC не требуют вызова к[super dealloc]
(это фактически приводит к ошибке компилятора). Объединение в цепочку к супер автоматизировано и осуществлено компилятором.Можно все еще использовать
CFRetain
,CFRelease
, и другие связанные функции с Базовыми Объектами стиля основы (см. Управляющее Бесплатное Образование моста).Вы не можете использовать
NSAllocateObject
илиNSDeallocateObject
.Вы создаете использование объектов
alloc
; время выполнения заботится об освобождении объектов.Вы не можете использовать объектные указатели в структурах C.
Вместо того, чтобы использовать a
struct
, можно создать класс Objective C для управления данными вместо этого.Нет никакого случайного кастинга между
id
иvoid *
.Необходимо использовать специальные броски, говорящие компилятор об объектном времени жизни. Необходимо сделать это для кастинга между объектами Objective C и Базовыми типами Основы, которые Вы передаете как аргументы функции. Для получения дополнительной информации посмотрите Управляющее Бесплатное Образование моста.
Вы не можете использовать
NSAutoreleasePool
объекты.ARC обеспечивает
@autoreleasepool
блоки вместо этого. Они имеют преимущество того, чтобы быть более эффективным, чемNSAutoreleasePool
.Вы не можете использовать зоны памяти.
Нет никакой потребности использовать
NSZone
больше — они проигнорированы современным временем выполнения Objective C так или иначе.
Для разрешения взаимодействия с ручным кодом сохранять-выпуска ARC налагает ограничение на именование метода:
Вы не можете дать средству доступа начинающееся имя
new
. Это поочередно означает, что Вы не можете, например, объявить свойство, имя которого начинается новый, если Вы не указываете различного метода get:// Won't work:
@property NSString *newTitle;
// Works:
@property (getter=theNewTitle) NSString *newTitle;
ARC представляет новые пожизненные спецификаторы
ARC представляет несколько новых пожизненных спецификаторов для объектов и слабых ссылок. Слабая ссылка не расширяет время жизни объекта, на который это указывает на, и автоматически становится nil
когда нет никаких сильных ссылок к объекту.
Необходимо использовать в своих интересах эти спецификаторы для управления графами объектов в программе. В частности ARC не принимает меры против циклов сильной ссылки (ранее известный, как сохраняют циклы — посмотрите Практическое управление памятью). Разумное использование слабых отношений поможет гарантировать, чтобы Вы не создавали циклы.
Атрибуты свойства
Ключевые слова weak
и strong
представлены, поскольку новое заявленное свойство приписывает, как показано в следующих примерах.
// The following declaration is a synonym for: @property(retain) MyClass *myObject; |
@property(strong) MyClass *myObject; |
// The following declaration is similar to "@property(assign) MyClass *myObject;" |
// except that if the MyClass instance is deallocated, |
// the property value is set to nil instead of remaining as a dangling pointer. |
@property(weak) MyClass *myObject; |
Под ARC, strong
значение по умолчанию для типов объектов.
Переменные спецификаторы
Вы используете следующие пожизненные спецификаторы для переменных точно так же, как Вы были бы, скажем, const
.
__strong |
__weak |
__unsafe_unretained |
__autoreleasing |
__strong
значение по умолчанию. Объект остается «живым», пока существует сильный указатель на него.__weak
указывает ссылку, не поддерживающую ссылочный объект. Слабая ссылка установлена вnil
когда нет никаких сильных ссылок к объекту.__unsafe_unretained
указывает ссылку, не поддерживающую ссылочный объект и не установленную вnil
когда нет никаких сильных ссылок к объекту. Если объект, на который это ссылается, освобожден, указатель оставляют, свисая.__autoreleasing
используется для обозначения параметров, передающихся ссылкой (id *
) и автовыпущены по возврату.
Необходимо украсить переменные правильно. При использовании спецификаторов в объявлении переменной объекта правильный формат:
ClassName * qualifier variableName; |
например:
MyClass * __weak myWeakReference; |
MyClass * __unsafe_unretained myUnsafeReference; |
Другие варианты являются технически неправильными, но «прощены» компилятором. Для понимания проблемы посмотрите http://cdecl .org/.
Заботьтесь при использовании __weak
переменные на штабеле. Рассмотрите следующий пример:
NSString * __weak string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]]; |
NSLog(@"string: %@", string); |
Несмотря на то, что string
используется после начального присвоения, нет никакой другой сильной ссылки к строковому объекту во время присвоения; это поэтому сразу освобождено. Оператор журнала показывает это string
имеет нулевое значение. (Компилятор обеспечивает предупреждение в этой ситуации.)
Также необходимо заботиться с объектами, переданными ссылкой. Следующий код будет работать:
NSError *error; |
BOOL OK = [myObject performOperationWithError:&error]; |
if (!OK) { |
// Report the error. |
// ... |
Однако ошибочное объявление неявно:
NSError * __strong e; |
и объявление метода обычно было бы:
-(BOOL)performOperationWithError:(NSError * __autoreleasing *)error; |
Компилятор поэтому переписывает код:
NSError * __strong error; |
NSError * __autoreleasing tmp = error; |
BOOL OK = [myObject performOperationWithError:&tmp]; |
error = tmp; |
if (!OK) { |
// Report the error. |
// ... |
Несоответствие между локальным объявлением переменных (__strong
) и параметр (__autoreleasing
) заставляет компилятор создавать временную переменную. Можно получить исходный указатель путем объявления параметра id __strong *
когда Вы берете адрес a __strong
переменная. Альтернативно можно объявить переменную как __autoreleasing
.
Используйте пожизненные спецификаторы для предотвращения циклов сильной ссылки
Можно использовать пожизненные спецификаторы для предотвращения циклов сильной ссылки. Например, обычно если у Вас есть график объектов, расположенных в родительско-дочерней иерархии, и родители должны относиться к их дочерним элементам и наоборот, тогда Вы делаете отношение родителя дочернему элементу сильными и отношение дочернего элемента к родителю слабый. Другие ситуации могут быть более тонкими, особенно когда они включают блочные объекты.
В режиме подсчета ссылки на руководство, __block id x;
имеет эффект не сохранения x
. В режиме ARC, __block id x;
значения по умолчанию к сохранению x
(точно так же, как все другие значения). Для получения поведения режима подсчета ссылки на руководство под ARC Вы могли использовать __unsafe_unretained __block id x;
. Как имя __unsafe_unretained
подразумевает, однако, имение несохраненной переменной опасно (потому что оно может свиснуть), и поэтому обескуражен. Две лучших опции состоят в том, чтобы или использовать __weak
(если Вы не должны поддерживать iOS 4 или OS X v10.6), или установите __block
значение к nil
повредить сохранить цикл.
Следующий фрагмент кода иллюстрирует эту проблему с помощью образца, иногда использующегося в подсчете ссылки на руководство.
MyViewController *myController = [[MyViewController alloc] init…]; |
// ... |
myController.completionHandler = ^(NSInteger result) { |
[myController dismissViewControllerAnimated:YES completion:nil]; |
}; |
[self presentViewController:myController animated:YES completion:^{ |
[myController release]; |
}]; |
Как описано, вместо этого, можно использовать a __block
спецификатор и набор myController
переменная к nil
в обработчике завершения:
MyViewController * __block myController = [[MyViewController alloc] init…]; |
// ... |
myController.completionHandler = ^(NSInteger result) { |
[myController dismissViewControllerAnimated:YES completion:nil]; |
myController = nil; |
}; |
Также можно использовать временный файл __weak
переменная. Следующий пример иллюстрирует простую реализацию:
MyViewController *myController = [[MyViewController alloc] init…]; |
// ... |
MyViewController * __weak weakMyViewController = myController; |
myController.completionHandler = ^(NSInteger result) { |
[weakMyViewController dismissViewControllerAnimated:YES completion:nil]; |
}; |
Для нетривиальных циклов, однако, необходимо использовать:
MyViewController *myController = [[MyViewController alloc] init…]; |
// ... |
MyViewController * __weak weakMyController = myController; |
myController.completionHandler = ^(NSInteger result) { |
MyViewController *strongMyController = weakMyController; |
if (strongMyController) { |
// ... |
[strongMyController dismissViewControllerAnimated:YES completion:nil]; |
// ... |
} |
else { |
// Probably nothing... |
} |
}; |
В некоторых случаях можно использовать __unsafe_unretained
если класс не __weak
совместимый. Это может, однако, стать непрактичным для нетривиальных циклов, потому что это может быть твердо или невозможно проверить это __unsafe_unretained
указатель является все еще актуальными вопросами и неподвижными точками к тому же рассматриваемому объекту.
ARC использует новый оператор для управления пулами автовыпуска
Используя ARC, Вы не можете управлять пулами автовыпуска непосредственно с помощью NSAutoreleasePool
класс. Вместо этого Вы используете @autoreleasepool
блоки:
@autoreleasepool { |
// Code, such as a loop that creates a large number of temporary objects. |
} |
Эта простая структура позволяет компилятору рассуждать о состоянии подсчета ссылок. На записи продвинут пул автовыпуска. На нормальном выходе (повреждение, возвратитесь, goto, провалитесь, и т.д.), пул автовыпуска выталкивается. Для совместимости с существующим кодом, если выход вследствие исключения, не выталкивается пул автовыпуска.
Этот синтаксис доступен во всех режимах Objective-C. Это более эффективно, чем использование NSAutoreleasePool
класс; Вы поэтому призваны принять его вместо использования NSAutoreleasePool
.
Образцы для управления выходами становятся непротиворечивыми через платформы
Образцы для объявления выходов в iOS и OS X изменяются с ARC и становятся непротиворечивыми через обе платформы. Образец, который необходимо обычно принимать: выходы должны быть weak
, за исключением тех от Владельца Файла к объектам верхнего уровня в файле пера (или сцена раскадровки), который должен быть strong
.
Полная подробная информация предоставлена в Файлах Пера в Руководстве по программированию Ресурса.
Переменные штабеля Инициализируются с нолем
Используя ARC, сильный, слабый, и автовыпускающий переменные штабеля, теперь неявно инициализируются с nil
. Например:
- (void)myMethod { |
NSString *name; |
NSLog(@"name: %@", name); |
} |
зарегистрирует нуль для значения имени вместо, возможно, катастрофического отказа.
Используйте флаги компилятора, чтобы включить и отключить ARC
Вы включаете ARC с помощью нового -fobjc-arc
флаг компилятора. Можно также принять решение использовать ARC на основе на файл, если более удобно для Вас использовать ссылку на руководство, значащую некоторые файлы. Для проектов, использующих ARC как подход по умолчанию, можно отключить ARC для определенного файла с помощью нового -fno-objc-arc
флаг компилятора для того файла.
ARC поддерживается в Xcode 4.2 и более позднем OS X v10.6 и позже (64-разрядные приложения) и для iOS 4 и позже. Слабые ссылки не поддерживаются в OS X v10.6 и iOS 4. Нет никакой поддержки ARC в Xcode 4.1 и ранее.
Управление бесплатным образованием моста
Во многих приложениях Какао необходимо использовать Базовые Объекты стиля основы, ли от самой Базовой платформы Основы (такой как CFArrayRef
или CFMutableDictionaryRef
) или от платформ, принимающих Базовые соглашения Основы, такие как Базовая Графика (Вы могли бы использовать типы как CGColorSpaceRef
и CGGradientRef
).
Компилятор автоматически не управляет временами жизни Базовых объектов Основы; необходимо вызвать CFRetain
и CFRelease
(или соответствующие специфичные для типа варианты), как продиктовано Базовыми правилами управления памятью Основы (см. Руководство по программированию управления памятью для Базовой Основы).
Если Вы бросаете между Objective C и Базовыми Объектами стиля основы, необходимо сказать компилятор о семантике владения объекта с помощью любого бросок (определенный в objc/runtime.h
) или Базовый макрос Стиля основы (определенный в NSObject.h
):
__bridge
передает указатель между Objective C и Базовой Основой без передачи права собственности.__bridge_retained
илиCFBridgingRetain
бросает указатель Objective C на Базовый указатель Основы и также передает владение Вам.Вы ответственны за вызов
CFRelease
или связанная функция для отказа от владения объекта.__bridge_transfer
илиCFBridgingRelease
перемещает указатель неObjective C на Objective C и также передает владение ARC.ARC ответственен за отказ от владения объекта.
Например, если у Вас был код как это:
- (void)logFirstNameOfPerson:(ABRecordRef)person { |
NSString *name = (NSString *)ABRecordCopyValue(person, kABPersonFirstNameProperty); |
NSLog(@"Person's first name: %@", name); |
[name release]; |
} |
Вы могли заменить его:
- (void)logFirstNameOfPerson:(ABRecordRef)person { |
NSString *name = (NSString *)CFBridgingRelease(ABRecordCopyValue(person, kABPersonFirstNameProperty)); |
NSLog(@"Person's first name: %@", name); |
} |
Компилятор обрабатывает объекты CF, возвращенные из методов какао
Компилятор понимает методы Objective C, возвращающиеся, Базовые типы Основы следуют историческим соглашениям о присвоении имен Какао (см. Усовершенствованное Руководство по программированию управления памятью). Например, компилятор знает что, в iOS, CGColor, возвращенный CGColor
метод UIColor
не принадлежит. Необходимо все еще использовать надлежащий бросок типа, как проиллюстрировано этим примером:
NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]]; |
[colors addObject:(id)[[UIColor lightGrayColor] CGColor]]; |
Бросьте параметры функции Используя ключевые слова владения
Когда Вы бросаете между Objective C и Базовыми объектами Основы в вызовах функции, необходимо сказать компилятор о семантике владения переданного объекта. Правила владения для Базовых объектов Основы - указанные в Базовых правилах управления памятью Основы (см. Руководство по программированию управления памятью для Базовой Основы); правила для объектов Objective C указаны в Усовершенствованном Руководстве по программированию управления памятью.
В следующем фрагменте кода массив передал CGGradientCreateWithColors
функция требует надлежащего броска. Владение объекта, возвращенного arrayWithObjects:
не передается функции, таким образом бросок __bridge
.
NSArray *colors = <#An array of colors#>; |
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations); |
Фрагмент кода показан в контексте в следующей реализации метода. Заметьте также использование Базовых функций управления памятью Основы, где продиктовано Базовыми правилами управления памятью Основы.
- (void)drawRect:(CGRect)rect { |
CGContextRef ctx = UIGraphicsGetCurrentContext(); |
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceGray(); |
CGFloat locations[2] = {0.0, 1.0}; |
NSMutableArray *colors = [NSMutableArray arrayWithObject:(id)[[UIColor darkGrayColor] CGColor]]; |
[colors addObject:(id)[[UIColor lightGrayColor] CGColor]]; |
CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (__bridge CFArrayRef)colors, locations); |
CGColorSpaceRelease(colorSpace); // Release owned Core Foundation object. |
CGPoint startPoint = CGPointMake(0.0, 0.0); |
CGPoint endPoint = CGPointMake(CGRectGetMaxX(self.bounds), CGRectGetMaxY(self.bounds)); |
CGContextDrawLinearGradient(ctx, gradient, startPoint, endPoint, |
kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation); |
CGGradientRelease(gradient); // Release owned Core Foundation object. |
} |
Общие вопросы при преобразовании проекта
При миграции существующих проектов Вы, вероятно, столкнетесь с различными проблемами. Вот некоторые общие вопросы, вместе с решениями.
Вы не можете вызвать
retain
,release
, илиautorelease
.Это - функция. Вы также не можете записать:
while ([x retainCount]) { [x release]; }
Вы не можете вызвать
dealloc
.Вы обычно вызываете
dealloc
если Вы реализуете одиночный элемент или заменяете объект вinit
методы. Для одиночных элементов используйте совместно используемый образец экземпляра. Вinit
методы, Вы не должны вызыватьdealloc
больше, когда Вы перезапишете, потому что будет освобожден объектself
.Вы не можете использовать
NSAutoreleasePool
объекты.Используйте новое
@autoreleasepool{}
создайте вместо этого. Это вызывает блочную структуру на Вашем пуле автовыпуска и приблизительно в шесть раз быстрее, чемNSAutoreleasePool
.@autoreleasepool
даже работы в коде не-ARC. Поскольку@autoreleasepool
настолько быстрее, чемNSAutoreleasePool
, много старых “взломов производительности” могут просто быть заменены безусловным@autoreleasepool
.Мигрант обрабатывает простое использование
NSAutoreleasePool
, но это не может обработать сложные условные случаи или случаи, где переменная определяется в организации нового@autoreleasepool
и используемый после него.ARC требует, чтобы Вы присвоили результат
[super init]
кself
вinit
методы.Следующее недопустимо в ARC
init
методы:[super init];
Простая фиксация должна изменить его на:
self = [super init];
Надлежащая фиксация должна сделать это и проверить результат на
nil
перед продолжением:self = [super init];
if (self) {
...
Вы не можете реализовать пользовательский
retain
илиrelease
методы.Пользовательская реализация
retain
илиrelease
методы повреждают слабые указатели. Существует несколько общих причин желания обеспечить пользовательские реализации:Производительность.
Не делайте этого больше; реализация
retain
иrelease
дляNSObject
намного быстрее теперь. Если Вы все еще находите проблемы, ошибки файла.Реализовать пользовательскую слабую систему указателя.
Использовать
__weak
вместо этого.Реализовать singleton-класс.
Используйте совместно используемый образец экземпляра вместо этого. Также используйте класс вместо методов экземпляра, избегающий иметь необходимость выделить объект вообще.
«Присвоенные» переменные экземпляра становятся сильными.
Перед ARC переменным экземпляра непринадлежали ссылки — непосредственно присвоение объекта к переменной экземпляра не расширяло время жизни объекта. Для создания свойства сильным Вы обычно реализовывали или синтезировали методы доступа, вызвавшие надлежащие методы управления памятью; напротив, Вы, возможно, реализовали методы доступа как те, которые, как показывают в следующем примере, поддержали слабое свойство.
@interface MyClass : Superclass {
id thing; // Weak reference.
}
// ...
@end
@implementation MyClass
- (id)thing {
return thing;
}
- (void)setThing:(id)newThing {
thing = newThing;
}
// ...
@end
С ARC переменные экземпляра являются сильными ссылками по умолчанию — присвоение объекта к переменной экземпляра непосредственно расширяет время жизни объекта. Когда переменная экземпляра предназначается, чтобы быть слабой, инструмент миграции не в состоянии определить. Для поддержания того же поведения как прежде необходимо отметить переменную экземпляра, как являющуюся слабым, или использовать заявленное свойство.
@interface MyClass : Superclass {
id __weak thing;
}
// ...
@end
@implementation MyClass
- (id)thing {
return thing;
}
- (void)setThing:(id)newThing {
thing = newThing;
}
// ...
@end
Или:
@interface MyClass : Superclass
@property (weak) id thing;
// ...
@end
@implementation MyClass
@synthesize thing;
// ...
@end
Вы не можете использовать сильный
id
s в структурах C.Например, следующий код не скомпилирует:
struct X { id x; float y; };
Это вызвано тем, что
x
значения по умолчанию к строго сохраненному и компилятор не могут безопасно синтезировать весь код, требуемый заставить его работать правильно. Например, если Вы передаете указатель на одну из этих структур через некоторый код, заканчивающий тем, что делал afree
, каждыйid
должен был бы быть выпущен передstruct
освобожден. Компилятор не может надежно сделать этого, настолько сильногоid
s в структурах запрещены полностью в режиме ARC. Существует несколько возможных решений:Используйте объекты Objective C вместо структур.
Это считается наиболее успешной практикой так или иначе.
Если использование объектов Objective C является субоптимальным, (возможно, Вы хотите плотный массив этих структур), тогда рассматривают использование a
void*
вместо этого.Это требует использования явных бросков, описанных ниже.
Отметьте ссылку на объект как
__unsafe_unretained
.Этот подход может быть полезен для полуобщих образцов как это:
struct x { NSString *S; int X; } StaticArray[] = {
@"foo", 42,
@"bar, 97,
...
};
Вы объявляете структуру как:
struct x { NSString * __unsafe_unretained S; int X; }
Это может быть проблематично и небезопасно, если объект мог бы быть выпущен из-под указателя, но это очень полезно для вещей, которые, как известно, являются вокруг навсегда как литералы постоянной строки.
Вы не можете непосредственно бросить между
id
иvoid*
(включая Базовые типы Основы).Это обсуждено более подробно в Управлении Бесплатным Образованием моста.
Часто задаваемые вопросы
Как я думаю о ARC? Куда это помещает сохранение/выпущение?
Попытайтесь прекратить думать о том, куда сохранить/выпустить вызовы помещаются и думают о Ваших алгоритмах приложения вместо этого. Думайте о “сильных и слабых” указателях в Ваших объектах, о монопольном использовании объекта, и о возможном сохраняют циклы.
Я должен все еще записать dealloc методы для своих объектов?
Возможно.
Поскольку ARC не автоматизирует malloc
/free
, управление временем жизни Базовых объектов Основы, дескрипторов файлов, и т.д., Вы все еще освобождаете такие ресурсы путем записи a dealloc
метод.
Вы не имеете к (действительно не может) выпускать переменные экземпляра, но Вы, возможно, должны вызвать [self setDelegate:nil]
на системных классах и другом коде, не компилирующемся с помощью ARC.
dealloc
методы в ARC не требуют — или позволяют — вызов [super dealloc]
; объединение в цепочку к супер обрабатывается и осуществляется временем выполнения.
Сохраняют циклы, все еще возможные в ARC?
Да.
ARC автоматизирует, сохраняют/выпускают, и наследовался, проблема сохраняют циклы. К счастью, код, перемещенный на ARC редко, начинает протекать, потому что свойства уже объявляют, являются ли свойства сдерживающими или нет.
Как делают блоки работают в ARC?
Блоки “просто работают” при передаче блоков штабель в режиме ARC, такой как в возврате. Вы больше не имеете к Копии блокирования вызова.
Одна вещь знать является этим NSString * __block myString
сохраняется в режиме ARC, не возможно висячем указателе. Для получения предыдущего поведения использовать __block NSString * __unsafe_unretained myString
или (лучше все еще) использование __block NSString * __weak myString
.
Я могу разработать приложения для OS X с ARC с помощью Snow Leopard?
Нет. Версия Snow Leopard Xcode 4.2 не поддерживает ARC вообще на OS X, потому что это не включает 10,7 SDK. Xcode 4.2 для Snow Leopard действительно поддерживает ARC для iOS, хотя, и Xcode 4.2 для Льва поддерживает и OS X и iOS. Это означает необходимость в системе Льва для создавания приложения ARC, работающего на Snow Leopard.
Я могу создать массив C сохраненных указателей под ARC?
Да, Вы можете, как проиллюстрировано этим примером:
// Note calloc() to get zero-filled memory. |
__strong SomeClass **dynamicArray = (__strong SomeClass **)calloc(entries, sizeof(SomeClass *)); |
for (int i = 0; i < entries; i++) { |
dynamicArray[i] = [[SomeClass alloc] init]; |
} |
// When you're done, set each entry to nil to tell ARC to release the object. |
for (int i = 0; i < entries; i++) { |
dynamicArray[i] = nil; |
} |
free(dynamicArray); |
Существует много аспектов для замечания:
Необходимо будет записать
__strong SomeClass **
в некоторых случаях, потому что значение по умолчанию__autoreleasing SomeClass **
.Выделенная память должна быть заполнена нулями.
Необходимо установить каждый элемент в
nil
прежде, чем освободить массив (memset
илиbzero
не будет работать).Необходимо избежать
memcpy
илиrealloc
.
ARC является медленным?
Это зависит от того, что Вы измеряете, но обычно «нет». Компилятор эффективно устраняет многих посторонних retain
/release
вызовы и много усилия инвестировали в ускорение времени выполнения Objective C в целом. В частности общий “возврат сохранить/автовыпустить объектный” образец намного быстрее и фактически не помещает объект в пул автовыпуска, когда вызывающая сторона метода является кодом ARC.
Одна проблема для знания - то, что оптимизатор не выполняется в общих настройках отладочного процесса, поэтому ожидайте видеть намного больше retain
/release
трафик в -O0
чем в -Os
.
Выполняет работу ARC в режиме ObjC ++?
Да. Можно даже поместить сильный/слабый id
s в классах и контейнерах. Компилятор ARC синтезирует retain
/release
логика в конструкторах копии и деструкторах и т.д. для создания этой работы.
Какие классы не поддерживают слабые ссылки?
Вы не можете в настоящее время создавать слабые ссылки на экземпляры следующих классов:
NSATSTypesetter
, NSColorSpace
, NSFont
, NSMenuView
, NSParagraphStyle
, NSSimpleHorizontalTypesetter
, и NSTextView
.
Для заявленных свойств необходимо использовать assign
вместо weak
; для переменных необходимо использовать __unsafe_unretained
вместо __weak
.
Кроме того, Вы не можете создать слабые ссылки из экземпляров NSHashTable
, NSMapTable
, или NSPointerArray
под ARC.
Что я должен сделать при разделении на подклассы NSCell или другого класса, использующего NSCopyObject?
Ничто специальное. ARC заботится о случаях, где необходимо было ранее добавить дополнительный, сохраняет явно. С ARC все методы копии должны просто скопировать по переменным экземпляра.
Я могу выбрать из ARC определенные файлы?
Да.
Когда Вы перемещаете проект использовать ARC, -fobjc-arc
флаг компилятора установлен как значение по умолчанию для всех исходных файлов Objective C. Можно отключить ARC для определенного класса с помощью -fno-objc-arc
флаг компилятора для того класса. В XCode, на целевой вкладке Build Phases, открывают Исходную группу Компиляции для раскрытия списка исходного файла. Дважды щелкните по файлу, для которого Вы хотите установить флаг, войти -fno-objc-arc
в раскрывающейся панели затем нажмите Done.
GC (Сборка «мусора») осуждается на Mac?
Сборка «мусора» осуждается у Пумы OS X v10.8 и будет удалена в будущей версии OS X. Автоматический Подсчет ссылок является рекомендуемой заменяющей технологией. Помочь в миграции существующих приложений, инструмента миграции ARC в Xcode 4.3 и более поздней миграции поддержек собравших «мусор» приложений OS X к ARC.