Каково количество сохраненных iVar и self.iVar в Obj-c?
Это мой код,
import <Foundation/Foundation.h>
@interface SyncObjectInfo : NSObject
{
NSString *strName;
}
@property(nonatomic,retain) NSString *strName;
-(void)returnRetainCount;
@end
#import "SyncObjectInfo.h"
@implementation SyncObjectInfo
@synthesize strName;
-(void)returnRetainCount
{
self.strName=@"name";
strName=@"name";
NSLog(@"Que-1. what is the retainCount of self.strName = ___");
NSLog(@"Que-2. what is the retainCount of strName = ___");
[self.strName retain];
NSLog(@"Que-3. what is the retainCount of self.strName= ___");
}
@end
У меня есть путаница для сохранения счета, так что...
Пожалуйста, дайте мне ответ на вопросы (1,2,3) из -(void)returnRetainCount
метод? и объясните пожалуйста почему?
Спасибо
4 ответа
Я просто изменил ваш пример, чтобы добавить звонки retainCount
в вашем NSLog
заявления. Следует отметить, что retainCount
не особенно полезный метод, и его, как правило, следует избегать.
Смотрите http://whentouseretaincount.com/ для получения дополнительной информации (не забудьте прокрутить вниз для более подробной информации).
Во всяком случае, вот что я бежал. Обратите внимание, что я изменился [self.str retain]
в [self.strName retain]
:
#import <Foundation/Foundation.h>
@interface SyncObjectInfo : NSObject
{
NSString *strName;
}
@property(nonatomic,retain) NSString *strName;
-(void)returnRetainCount;
@end
@implementation SyncObjectInfo
@synthesize strName;
-(void)returnRetainCount
{
NSLog(@"Que-1. what is the retainCount of self.strName = %lu", [self.strName retainCount]);
NSLog(@"Que-2. what is the retainCount of strName = %lu", [strName retainCount]);
[self.strName retain];
NSLog(@"Que-3. what is the retainCount of self.strName= %lu", [self.strName retainCount]);
}
@end
int main(int argc, char *argv[]) {
@autoreleasepool {
SyncObjectInfo *obj = [SyncObjectInfo new];
[obj returnRetainCount];
}
}
Во всех случаях ответ равен 0. Этого следовало ожидать, потому что strName
является nil
и сообщения, отправленные на nil
игнорируются, поэтому призыв к [self.strName retain]
игнорируется
Однако, если я установлю strName
к чему-либо, используя следующий код:
int main(int argc, char *argv[]) {
@autoreleasepool {
SyncObjectInfo *obj = [SyncObjectInfo new];
obj.strName = @"Something";
[obj returnRetainCount];
}
}
Затем при повторном запуске я получаю следующее:
Que-1. what is the retainCount of self.strName = 18446744073709551615
Que-2. what is the retainCount of strName = 18446744073709551615
Que-3. what is the retainCount of self.strName= 18446744073709551615
Счет удержания составляет 18446744073709551615. Это потому, что NSString
S обрабатываются иначе, чем большинство объектов. Это одна из причин, почему retainCount
не очень полезно
Если мы изменим NSString
для NSURL
следующее:
@interface SyncObjectInfo : NSObject
{
NSURL *strName;
}
@property(nonatomic,retain) NSURL *strName;
// snip
int main(int argc, char *argv[]) {
@autoreleasepool {
SyncObjectInfo *obj = [SyncObjectInfo new];
obj.strName = [NSURL URLWithString:@"http://stackru.com"];
[obj returnRetainCount];
}
}
и повторно мы получаем:
Que-1. what is the retainCount of self.strName = 2
Que-2. what is the retainCount of strName = 2
Que-3. what is the retainCount of self.strName= 3
Первые два случая одинаковы. Объект, возвращаемый +URLWithString
сохраняется, но автоматически освобождается, а затем присваивается имуществу и сохраняется снова. В какой-то момент в будущем пул авто-релиза будет сброшен, а количество сохранений уменьшится до 1.
Третье значение, как мы ожидаем, выросло на единицу из-за явного вызова retain
,
Вы понимаете из документации Apple, что число сохранений должно быть 1 (а не 2 в вопросах 1 и 2), технически неверно, но концептуально правильно. Объект был автоматически освобожден (фактически обещание, что объект будет выпущен в ближайшем будущем).
Мы можем исследовать эффекты пула автоматического выпуска, сбрасывая бассейн. Я изменил main
функция для очистки пула автоматического выпуска перед вызовом returnRetainCount
,
int main(int argc, char *argv[]) {
@autoreleasepool {
SyncObjectInfo *obj;
@autoreleasepool {
obj = [SyncObjectInfo new];
obj.strName = [NSURL URLWithString:@"http://stackru.com"];
}
[obj returnRetainCount];
}
}
На этот раз вывод:
Que-1. what is the retainCount of self.strName = 1
Que-2. what is the retainCount of strName = 1
Que-3. what is the retainCount of self.strName= 2
Это больше, чем вы ожидаете. Так что же происходит?
Когда NSURL
Объект создан URLWithString
метод имеет счет сохранения 1. Тем не менее, NSURL
класс должен отказаться от владения объектом. Если это называется release
для этого объекта перед его возвратом счетчик сохранений достигнет 0, и объект будет освобожден до того, как он будет возвращен.
Вместо URLWithString
вызовы методов autorelease
на объекте. Авто-релиз добавляет объект в пул авто-релиза. В принципе, NSURL
передает владение пулу авто-выпуска с пониманием, что пул авто-выпуска освободит объект в какой-то момент в ближайшем будущем (в приложении пул сбрасывается как часть цикла runloop).
В приведенном выше примере объект, возвращаемый URLWithString
имеет счет сохранения 1. Присвоение его свойству увеличивает счет хранения на 1 (теперь он равен 2). Затем мы очищаем пул авто-релиза (оставляя @autoreleasepool { }
блок и количество сохранений падает до 1.
Постоянные строки, подобные этой @"Something"
придется сохранить считать как max unsigned int
,
Потому что вы не можете освободить их, так как они размещены в постоянном пуле строк.
NSLog(@"Que-1. what is the retainCount of self.strName = %lu", [self.strName retainCount]);
retain count normal=2
NSLog(@"Que-2. what is the retainCount of strName = %lu", [strName retainCount]);
retain count self=2
NSLog(@"Que-3. what is the retainCount of self.strName= %lu", [self.strName retainCount]);
retain count self=3
Вы всегда можете найти ответ самостоятельно, задав любой объект Objective C через " retainCount
метод.
ЭГ: " NSLog( @"retain count for strName is %d", [self.strName retainCount]);
"
Этот метод считается "устаревшим" и никогда не должен использоваться при доставке, кстати, производственный код