Каково количество сохраненных 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. Это потому, что NSStringS обрабатываются иначе, чем большинство объектов. Это одна из причин, почему 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]); "

Этот метод считается "устаревшим" и никогда не должен использоваться при доставке, кстати, производственный код

Другие вопросы по тегам