Objective-C Language
Управление памятью
Поиск…
Автоматический подсчет ссылок
С автоматическим подсчетом ссылок (ARC) компилятор вставляет инструкции retain
, release
и autorelease
там, где они необходимы, поэтому вам не нужно писать их самостоятельно. Он также пишет для вас методы dealloc
.
Пример программы из Manual Memory Management выглядит так: ARC:
@interface MyObject : NSObject {
NSString *_property;
}
@end
@implementation MyObject
@synthesize property = _property;
- (id)initWithProperty:(NSString *)property {
if (self = [super init]) {
_property = property;
}
return self;
}
- (NSString *)property {
return property;
}
- (void)setProperty:(NSString *)property {
_property = property;
}
@end
int main() {
MyObject *obj = [[MyObject alloc] init];
NSString *value = [[NSString alloc] initWithString:@"value"];
[obj setProperty:value];
[obj setProperty:@"value"];
}
Вы по-прежнему можете переопределить метод dealloc для очистки ресурсов, которые не обрабатываются ARC. В отличие от использования ручного управления памятью, вы не вызываете [super dealloc]
.
-(void)dealloc {
//clean up
}
Сильные и слабые ссылки
Слабая ссылка выглядит как одна из них:
@property (weak) NSString *property;
NSString *__weak variable;
Если у вас слабое отношение к объекту, то под капотом:
- Вы не сохраняете его.
- Когда он будет освобожден, каждая ссылка на него будет автоматически установлена на
nil
По умолчанию ссылки на объекты всегда сильны. Но вы можете явно указать, что они сильны:
@property (strong) NSString *property;
NSString *__strong variable;
Сильная ссылка означает, что, хотя эта ссылка существует, вы сохраняете объект.
Управление памятью вручную
Это пример программы, написанной с ручным управлением памятью. Вы действительно не должны писать свой код, как это, если по какой-то причине вы не можете использовать ARC (например, если вам нужно поддерживать 32-разрядный). В примере избегается нотация @property
чтобы проиллюстрировать, как вам приходилось писать геттеры и сеттеры.
@interface MyObject : NSObject {
NSString *_property;
}
@end
@implementation MyObject
@synthesize property = _property;
- (id)initWithProperty:(NSString *)property {
if (self = [super init]) {
// Grab a reference to property to make sure it doesn't go away.
// The reference is released in dealloc.
_property = [property retain];
}
return self;
}
- (NSString *)property {
return [[property retain] autorelease];
}
- (void)setProperty:(NSString *)property {
// Retain, then release. So setting it to the same value won't lose the reference.
[property retain];
[_property release];
_property = property;
}
- (void)dealloc {
[_property release];
[super dealloc]; // Don't forget!
}
@end
int main() {
// create object
// obj is a reference that we need to release
MyObject *obj = [[MyObject alloc] init];
// We have to release value because we created it.
NSString *value = [[NSString alloc] initWithString:@"value"];
[obj setProperty:value];
[value release];
// However, string constants never need to be released.
[obj setProperty:@"value"];
[obj release];
}
Правила управления памятью при использовании ручного подсчета ссылок.
Эти правила применяются только в том случае, если вы используете ручной подсчет ссылок!
У вас есть любой объект, который вы создаете
Вызвав метод, имя которого начинается с
alloc
,new
,copy
илиmutableCopy
. Например:NSObject *object1 = [[NSObject alloc] init]; NSObject *object2 = [NSObject new]; NSObject *object3 = [object2 copy];
Это означает, что вы несете ответственность за освобождение этих объектов, когда вы закончите с ними.
Вы можете взять собственность на объект, используя
Чтобы взять собственность за объект, вы вызываете метод сохранения.
Например:
NSObject *object = [NSObject new]; // object already has a retain count of 1 [object retain]; // retain count is now 2
Это имеет смысл только в некоторых редких ситуациях.
Например, когда вы реализуете метод доступа или метод init, чтобы получить право собственности:
- (void)setStringValue:(NSString *)stringValue { [_privateStringValue release]; // Release the old value, you no longer need it [stringValue retain]; // You make sure that this object does not get deallocated outside of your scope. _privateStringValue = stringValue; }
Когда вы больше не нуждаетесь в этом, вы должны отказаться от собственности на свой объект
NSObject* object = [NSObject new]; // The retain count is now 1 [object performAction1]; // Now we are done with the object [object release]; // Release the object
Вы не должны отказываться от права собственности на объект, который у вас нет.
Это означает, что когда вы не взяли на себя ответственность за объект, вы его не отпустите.
Autoreleasepool
Autoreleasepool - это блок кода, который освобождает каждый объект в блоке, который получил сообщение автозапуска.
Пример:
@autoreleasepool { NSString* string = [NSString stringWithString:@"We don't own this object"]; }
Мы создали строку без права собственности. Метод
NSString
stringWithString:
должен убедиться, что строка правильно освобождена после того, как она больше не нужна. Перед возвратом метода вновь созданная строка вызывает метод авторекламы, поэтому ему не нужно владеть строкой.Так
stringWithString:
:+ (NSString *)stringWithString:(NSString *)string { NSString *createdString = [[NSString alloc] initWithString:string]; [createdString autorelease]; return createdString; }
Необходимо использовать блоки autoreleasepool, потому что у вас иногда есть объекты, которыми вы не владеете (четвертые правила не всегда применяются).
Автоматический подсчет ссылок автоматически учитывает правила, поэтому вам не нужно.