Проблема со stringByAppendingString и сохранением количества

#objective-c

#objective-c

Вопрос:

Мне нужно объединить некоторые строки.

 NSString * sportName = [[NSString alloc ]initWithString:@""];
sportName = [sportName stringByAppendingString:[someObject getString]];
// can be more stringByAppendingString
...
[sportName release];
  

Но что-то странное для меня — дать команду «построить и проанализировать»:

в строке:

 sportName = [sportName stringByAppendingString:[someObject getString]]; 
  

ошибка:
Метод возвращает объект Objective-C с числом сохранений 0 (ссылка, не являющаяся владельцем)

в строке:

 [sportName release];
  

ошибка:
Неправильное уменьшение количества ссылок на объект, который на данный момент не принадлежит вызывающей стороне

Я использую его для заполнения моего TableView, и он разбивается после загрузки : (.

Ответ №1:

 NSString * sportName = [[NSString alloc ]initWithString:@""];
sportName = [sportName stringByAppendingString:[someObject getString]];
  

Во 2-й строке вы получаете новую строку, которая присваивается обратно spotName . Таким образом, выделенная строка в первой строке является утечкой. Я не понимаю, зачем вам нужно добавлять в пустую строку. Добавление к @"" практически не дает эффекта. И если у вас есть какая-то непустая строка, вы можете создать ее как автоматически выпущенную строку вместо alloc. Вот так:

 // create an autoreleased string
NSString * sportName = @"my_string";
// this will return a new string which is also autoreleased
sportName = [sportName stringByAppendingString:[someObject getString]];
// all subsequent call to stringByAppendingString will return autoreleased string
//so no need to release spotName
  

И если вам нужно сохранить spotName , вы можете сохранить это или использовать свойство.

Комментарии:

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

2. @Romula, я не уверен, почему вы отменили принятие после того, как приняли его один раз. У вас возникли еще какие-либо проблемы?

Ответ №2:

ну, зачем вам нужно выделять (и таким образом сохранять) вашу строку, если вы используете ее только внутри метода (как кажется)…

попробуйте это:

 NSString * sportName = @"";
  

вместо вашего «alloc»:

и удалите строку освобождения…

Ответ №3:

Вы в первую очередь становитесь владельцем спортивного имени, отправляя alloc (или new, copy, mutableCopy, retain). Теперь у вас есть новый экземпляр, который вы должны выпустить позже.

stringByAppendingString возвращает автоматически выпущенную строку, которую вы присваиваете sportName. Ссылка потеряна и никогда не может быть выпущена.

Посмотрите на адреса памяти:

 NSString *sportName = [[NSString alloc ]initWithString:@"baa"];
NSLog(@"<%p> %@", sportName, sportName);
sportName = [sportName stringByAppendingString:@" foo"];
NSLog(@"<%p> %@", sportName, sportName);
  

Вывод:

 2011-05-20 08:19:08.675 foo[1262:207] <0x3038> baa
2011-05-20 08:19:08.677 foo]1262:207] <0x4e40bd0> baa foo
  

имя спортсмена было перезаписано.

Вы можете исправить это, введя tmp или используя строковый литерал:

 NSString *sportName = @"baa";
  

или

 ...
NSString *tmp = [sportName stringByAppendingString:@" foo"];
  

Комментарии:

1. Вы являетесь владельцем sportName из-за alloc , а не из-за init.