Рассмотрение этого некоторое время теперь и не понимание, почему этот простой бит кода бросает ошибку. Сокращенный для краткости:
NSMutableString *output;
...
@property (nonatomic, retain) NSMutableString *output;
...
@synthesize output;
...
// logs "output start" as expected
output = [NSMutableString stringWithCapacity:0];
[output appendString:@"output start"];
NSLog(@"%@", output);
...
// error happens here
// this is later on in a different method
[output appendString:@"doing roll for player"];
Кто-либо может определить мою ошибку?
Решение на самом деле связано с удержанием, как указывает пользователь invariant. Метод класса:
output = [NSMutableString stringWithCapacity:0];
возвращает autorelease
NSMutableString. При присвоении его моему выходному свойству - похоже, даже с флагом retain - он его не сохранил. Решением было присвоить его самому, а не автоосвобождать:
output = [[NSMutableString alloc] initWithCapacity:0];
Тогда retain сработал. Любое объяснение причин было бы очень желательно.
Редактировать
Разобрался почему. Я обращался к переменным экземпляра напрямую, а не через геттер/сеттер, который я синтезировал. Больше информации в моем блоге.
Измените строку
output = [NSMutableString stringWithString:@"начало вывода"]
на
[self setOutput:[NSMutableString stringWithString:@"output start"]]
(или self.output = ...
, если вам больше нравится такая нотация).
Хотя вы объявили свойство, вы не используете сеттер, поэтому вы не сохраняете строку.