2010-02-28 2 views
2

Мне показалось, что я получаю управление памятью какао, но, кстати, у меня есть чему поучиться.Вопросы управления памятью

Взгляните на этот класс я писал:

Word.h

#import <UIKit/UIKit.h> 


@interface Word : NSObject { 
    NSString *word; 
    NSMutableArray *wordArray; 
} 

@property (nonatomic ,retain) NSString *word; 
@property (nonatomic ,retain) NSMutableArray *wordArray; 

@end 

Word.m

#import "Word.h" 


@implementation Word 

@synthesize word, wordArray; 

- (void)setWord:(NSString *)aWord { 
    NSMutableArray *newValue = [[NSMutableArray alloc] init]; 
    self.wordArray = newValue; 
    [newValue release]; 

    for (int i = 0 ;i < [aWord length] ;i++) { 
     NSString *character = [[NSString alloc] init]; 
     character = [NSString stringWithFormat:@"%C",[aWord characterAtIndex:i]]; 
     [wordArray addObject:character]; 
     //[character release]; 
    } 
} 

- (void)dealloc { 
    [word release]; 
    [wordArray release]; 
    [super dealloc]; 
} 

@end 

Как вы можете видеть, я заполняю массив, когда устанавливаю строку. Я делаю это в цикле for, вытаскивая символ строки и помещая их в новую выделенную строку. Затем я помещаю эту строку в массив, а затем я должен освободить строку. И вот здесь я делаю это неправильно, потому что я выпускаю значение, которое я вставляю в массив. когда позже я пытаюсь использовать массив, его нет.

Как мне это сделать? он чувствует себя неправильно, чтобы сделать «характер» собственностью и освободить его в dealloc, потому что он просто временный.

ответ

6

Прежде всего, вам не нужно назначать новый NSStringcharacter, так как вы сразу же перезаписываете его другим объектом. Помните, что это указатель, поэтому, когда вы назначаете его, вы не меняете объект, на который он указывает, а только указываете его на другой объект. Таким образом, объект, который вы выделили и изначально присвоенный character, просочился на следующую строку, когда мы потеряли указатель на него.

Теперь stringWithFormat возвращает строку с автореализацией, которую затем указывает на character. Этот объект не должен быть выпущен вами, но это то, что происходит в пропущенной строке. Так что цикл будет лучше, так как:

for (int i = 0 ;i < [aWord length] ;i++) { 
     NSString* character = [NSString stringWithFormat:@"%C",[aWord characterAtIndex:i]]; 
     [wordArray addObject:character]; 
} 
+0

Так ли пул авторезистов сливается, когда экземпляр класса мертв, могу ли я быть уверенным, что автореферат не высвободит мой объект слишком рано? – Oscar

+2

Пул автореферации освобождается в цикле выполнения, то есть вне вашего обычного кода. Он не будет запускаться посреди одного из ваших методов. Редактирование: если вы используете фоновые потоки, где это может быть проблемой, вам нужно настроить локальный пул авторесурсов по этой причине. Но это не проблема. –

+0

Хорошо, спасибо за помощь :) – Oscar

3

Помимо заботы управления памятью, вы знаете, что вы переопределить функцию сеттера для word собственности?

Когда вы @synthesize ваше имущество слово, то и присваивателя методы генерируются за кулисами так уже есть функции для - (void)setWord:(NSString *)aWord; и - (NSString *)word; Вы можете прочитать об этом в Objective-C primer или Programming Language documentation.

Поскольку вы создали функцию (void)setWord:(NSString *)aWord;, это переопределяет созданный сеттер. Поскольку вы фактически не устанавливаете переменную word, ваша собственность «сломана».

В качестве примера, возможно, перепишем его в виде:

#import "Word.h" 

@implementation Word 

@synthesize word, wordArray; 

- (void)setWord:(NSString *)aWord { 
    // set the word iVar 
    if (aWord != word) { 
     [aWord retain]; // I prefer [aWord copy]; 
     [word release]; 
     word = aWord; 
    } 

    NSMutableArray *newValue = [[NSMutableArray alloc] init]; 

    for (int i = 0 ;i < [aWord length] ;i++) { 
     NSString *character = [NSString stringWithFormat:@"%C",[aWord characterAtIndex:i]]; 
     [wordArray addObject:character]; 

    } 
    // Now that you have created the newArray, set it to the property 
    self.wordArray = newValue; 
    [newValue release]; 
} 

- (void)dealloc { 
    [word release]; 
    [wordArray release]; 
    [super dealloc]; 
} 

@end 

Редактировать

Почему я написал, что я предпочел [aWord copy] над [aWord retain]? Потому что я бы объявила свойства как copy, а не retain.

Мутируемость может быть болью.Предположим, что вместо передачи NSString* в aWord вместо этого передается NSMutableString*. Это возможно, потому что NSMutableString является подклассом NSString. Предположим также, что другая часть программы изменила значение этой строки (в конце концов, это mutable). Теперь мы изменили свойство класса Word извне. Это нарушает инкапсуляцию.

Имеет смысл использовать @property (copy)… для классов коллекции.

Вы можете прочитать хороший ответ here.

+0

Хорошая точка. Я не понимаю ваш комментарий («Я предпочитаю [aWord copy]»). Объявление свойства говорит 'keep', поэтому оно должно быть сохранено, не так ли? –

+0

Стивен, я расширил свой ответ. – Abizern

+0

Это очень интересно, я никогда не использовал причину копирования, я никогда не был уверен, что он делает. Благодаря! – Oscar