Использование указателя структуры в качестве @property - PullRequest
2 голосов
/ 23 сентября 2011

Я хочу использовать struct указатель в качестве @property, но я не уверен, как мне его освободить.

Вот что у меня сейчас:

.h:

@property (nonatomic, assign) InfoStruct * info;

.m:

@synthesize info; 
- (id)init {
    self = [super init];
    if (self) {
        self.info = (struct InfoStruct *) malloc(sizeof(struct InfoStruct));
    }
    return self;
}

-(void)dealloc {
    free(info);
    [super dealloc];
}

Может ли приведенный выше код вызвать какие-либо проблемы? Это правильно? Кажется, работает нормально, но я думаю, что мне нужно подтверждение.

Ответы [ 4 ]

5 голосов
/ 23 сентября 2011

Это должно работать просто отлично. @property помеченный assign может обрабатывать обычные типы данных C, будь то числовые примитивы или указатели. Тот факт, что вы указываете на структуру, не меняет этого.

Просто будьте осторожны с вашей памятью, потому что похоже, что ваше свойство доступно для чтения и записи, и любой, кто присваивает ваше свойство, может не осознавать, что ваш объект «владеет» им (например, вызывает free() в -dealloc и требует free() -ing старое значение свойства, если вы присваиваете ему новое значение). Если у вас нет причин хотеть, чтобы это свойство было доступно для чтения и записи, вы можете пометить его readonly.

5 голосов
/ 23 сентября 2011

Это зависит от того, как вы используете экземпляры этого класса.Например:

SomeClass *obj = [SomeClass new];
// never assign an address to obj.info
[obj release];

будет в порядке.

Однако, поскольку вы объявили это свойство для чтения-записи, вам необходимо принять во внимание владение объектом, на который указываетэта структура.

Например, в:

SomeClass *obj = [SomeClass new];
obj.info = someInfo;
[obj release];

объект, который вы выделили в -init, не освобождается (вы его пропускаете), а объект указываетк someInfo освобождается.Вы можете изменить установщик свойства на что-то вроде:

- (void)setInfo:(InfoStruct *)newInfo {
    if (newInfo != info) {
        free(info); // free previous object
        info = newInfo;
    }
}

, и в этом случае присваивание всегда освобождает предыдущий объект, если присваиваемое значение не совпадает с предыдущим значением.Это означает, что ваш класс фактически владеет объектом, адрес которого присваивается свойству.

Если вы решите, что класс не должен отвечать за освобождение объектов, отличных от того, который создан в -init, вещи получаютсянемного сложнее.Если info назначен какой-либо адрес, отличный от адреса исходного info, созданного в -init, клиентскому коду необходимо освободить obj.info перед присвоением ему нового значения.Например:

SomeClass *obj = [SomeClass new];
free(obj.info);
obj.info = someInfo;
[obj release];

Это проблематично, потому что у вас есть код вне класса, освобождающий память, используемую объектом этого класса, что довольно навязчиво.И, если класс не отвечает за освобождение объектов, отличных от созданного в -init, вам необходимо сохранить дополнительное состояние, указывающее, что -dealloc освобождает только info, если info не изменилось послеобъект был инициализирован.

Также, как отметил Джим, правильное имя метода - dealloc.

0 голосов
/ 23 сентября 2011

Мы ничего не знаем о вашем InfoStruct. Если он содержит только примитивные типы, то достаточно вызвать free(info). Однако, если он имеет указатели на другие типы, которые вы выделяете память для использования malloc, то free(info) не освободит эти объекты и у вас будет утечка памяти.

0 голосов
/ 23 сентября 2011

Этот метод должен называться dealloc, а не destroy.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...