Почему я получаю «Попытка изменить неизменный объект с помощью replaceOccurferencesOfString:», когда все переменные изменяемы - PullRequest
2 голосов
/ 04 ноября 2011

Довольно простой код, который, я могу сказать, работал так, как задумано в Xcode 4.1, но ломается в Xcode 4.2.Вот код ошибки:

-(void)mergeDevData2Email:(NSMutableString *)target codeArray:(NSArray *)array1 valueArray:(NSArray *)array2 {
NSUInteger n = 0;

for (NSMutableString *aCode in array1) {
    if ([array2 count] > n) {
        NSMutableString *arg = [array2 objectAtIndex:(NSUInteger)n];

        NSLog(@"Target isKindOf NSMutableString: %@", ([target isKindOfClass:[NSMutableString class]]) ? @"YES" :@"NO");
        NSLog(@"aCode isKindOf NSMutableString: %@", ([aCode isKindOfClass:[NSMutableString class]]) ? @"YES" :@"NO");
        NSLog(@"arg isKindOf NSMutableString: %@", ([arg isKindOfClass:[NSMutableString class]]) ? @"YES" :@"NO");

        [target replaceOccurrencesOfString:aCode withString:arg options:NSLiteralSearch range:NSMakeRange(0, [target length])];
        n++;
    }
    else {
        break;
    }
}
}

Это то, что отображает NSLogs:

2011-11-03 15: 42: 59.967 TestProg [30413: c503] Цель isKindOf NSMutableString: ДА

2011-11-03 15: 42: 59.968 TestProg [30413: c503] aCode isKindOf NSMutableString: ДА

2011-11-03 15: 42: 59.969 TestProg [30413: c503] arg isKindOfNSMutableString: YES

Когда я выполняю строку кода [target replaceOcurances ..., с которой я сталкиваюсь, -

Программный полученный сигнал: "SIGABRT".

Со следующимжурнал консоли -

2011-11-03 15: 43: 26.828 TestProg [30413: c503] * Завершение работы приложения из-за невыполненного исключения «NSInvalidArgumentException», причина: «Попытка изменить неизменяемыйобъект с replaceOccurferencesOfString: withString: options: range: '

Мой вопрос: ГДЕ я пытаюсь изменить неизменный объект?Во-вторых, почему это хорошо работает в Xcode 4.1?Конечно, все игроки выглядели изменчивыми для Xcode 4.1.Какая разница в Xcode 4.2?Мне здесь не хватает чего-то тонкого.

Ответы [ 3 ]

3 голосов
/ 04 ноября 2011

Я подозреваю, что некоторые строки не являются действительно изменяемыми (вероятно, "target", поскольку именно эту строку вы пытаетесь изменить).Это действительно смутило меня и на некоторое время, но «isKindOf:» не делает различий между изменяемыми и неизменяемыми строками.Я полагаю, что ваши запросы NSLog будут возвращать YES, даже если строки не являются изменяемыми.

Если вы остановитесь в отладчике, вы сможете проверить объекты и определить, являются ли они действительно изменяемыми или нет ("реальный""имена классов должны показываться вместе с объектом).

Насколько это работало в 4.1, а не в 4.2, трудно сказать.Может случиться так, что какая-то системная подпрограмма возвращает NSString, использованную для возврата NSMutableString, но больше не возвращает.

Если я прав, вам нужно будет подняться в стек, чтобы выяснить, откуда пришла цель.В какой-то момент он мог быть преобразован из строки NSString в строку NSMutableString.

0 голосов
/ 04 ноября 2011

Переменная, переданная в "target", была определена и везде использовалась как NSMutableString. В ОДНОМ месте в методе, вызванном до обсуждаемого метода, переменная была загружена из содержимого файла, и в этом методе я из-за отсутствия опыта использовал выражение:

self.messageBody = fileContents;

fileContents был строкой NSString. К сожалению.

Это, очевидно, создало новую ячейку памяти для messageBody с другим адресом памяти и не было изменяемым. Вопрос - делает ли это на самом деле новый объект? Если так, я думаю, это также привело к утечке памяти, поскольку первый экземпляр больше не мог быть освобожден.

Поэтому, когда я выполнил обсуждаемый метод, объект, на который ссылается «target», больше не был изменяемым, и мой оператор replaceOccurancesOfString потерпел крах.

Это не отвечает на аномалию того, почему он работал так, как хотелось бы в Xcode 4.1, но правильно падал в Xcode 4.2. Я столкнулся с этим из-за конструктивного подталкивания Рона. Спасибо.

0 голосов
/ 04 ноября 2011

Проверьте документы Apple для isKindOfClass: .

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

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

Вполне возможно, что они изменили тип, возвращаемый изкластер классов в этом случае между SDK.

...