Почему я должен сохранить / скопировать эту строку NSString? - PullRequest
0 голосов
/ 16 ноября 2011

Недавно я переписал некоторый код в одном из моих классов, который дал мне ошибку с NSString. Вот что у меня сейчас:

Заголовок моего класса:

@interface MyViewController : UITableViewController {
   NSString *myString;
}

@property (nonatomic, retain) NSString *myString; // Or copy instead of retain.

@end

И реализовано несколько методов:

- (void)viewDidLoad {
    myString = @"This is";

    if (something) {
        myString = [NSString stringWithFormat:@"%@ a string.", myString]; // *1
    }

    [myString retain]; // <-- Why do I have to retain/copy here?
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row == 0) {
        /* Some code for creating a UITextView called myTextView */
        // ..and then setting the text property:
        myTextView.text = myString; // <-- Crashes here if I don't retain/copy in viewDidLoad.
    }
}

После некоторой отладки я решил сохранить / скопировать строку NSString.

Почему я должен сохранять / копировать строку NSString в viewDidLoad, если я хочу использовать ее позже?

Кроме того, я заметил, что если я удалю строку, помеченную * 1, мне не нужно сохранять / копировать.

Ответы [ 3 ]

1 голос
/ 16 ноября 2011

Один из способов лучше понять это - поставить префикс вашего личного атрибута с подчеркиванием _myString и сохранить ваше свойство как myString - это упростит задачу определения используемого атрибута или свойства.

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

Если вы поставили префикс вПоместите их, вы всегда будете знать, что _myString нужно будет сохранить при назначении, а myString сохранит автоматически.

Строка в * 1 заменяет значение myString новой строкой и по какой-то причинеэто значение автоматически высвобождается перед обработкой вашего кода во втором методе.Я не могу вспомнить точную причину, но я думаю, что это не происходит для первого назначения, потому что вы создаете строковый литерал с @ "This is", который не выпускается автоматически.

Надеюсь, это поможет.

1 голос
/ 16 ноября 2011

Если вы используете метод синтезированного сеттера для присвоения переменной, он автоматически сохранит для вас NSString:

if (something) {
    self.myString = [NSString stringWithFormat:@"%@ a string.", myString]; // *1
}
0 голосов
/ 17 ноября 2011

Вы можете использовать средства доступа к сохраненным свойствам, которые будут автоматически освобождаться / сохраняться

- (void)viewDidLoad {
    self.myString = @"This is";
    if (something) {
        self.myString = [NSString stringWithFormat:@"%@ a string.", myString]; // *1
    }
    // no need to retain
}

Причина, по которой он не вылетает при удалении строки, помеченной * 1, заключается в том, что myString все еще указывает на @"This is", что является литералом, которое находится в углу памяти на протяжении всей продолжительности программы и никогда уничтожен, следовательно, эта ячейка памяти остается действительной.

...