Я сталкиваюсь с повторяющимся сбоем при вызове -performFetch на моем NSFetchedResultsController, что ПОКАЗЫВАЕТСЯ как сбой, связанный с данными:
NSFetchedResultsController *aFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:sectionnamekeypath
cacheName:cacheName];
aFetchedResultsController.delegate = self;
NSError *error = nil;
if (NO == [aFetchedResultsController performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
Он падает при вызове PerformFetch(). Я включил проверку зомби, и он напечатал:
*** -[CFString isNSString__]: message sent to deallocated instance 0x12c6071d0
Я проверил все строки в своей функции и не могу найти строку с таким адресом. Я использовал NSLog() для всех строк вместе с их адресами. Я полагал, что это сломается на любой строке NSLog(), которая ссылается на рассматриваемую строку, но все они по-прежнему действительны.
Это заставляет меня думать, что это проблема внутри NSFetchedResultsController.performFetch(), но трудно представить, что у них есть такая ошибка. Итак, что еще я могу сделать, чтобы узнать, что это за строка?
Я не сталкивался с такими проблемами с тех пор, как мы перешли на ARC. Я не уверен, как выяснить, откуда взялась эта строка.
КАЖЕТСЯ, что это связано с данными. Мое приложение извлекает данные с нашего сервера, импортирует их в Core Data, а затем использует NSFetchedResultsController для отображения данных в UITableView. Я могу войти в систему как разные пользователи, загрузить их данные, а FRC извлекает и работает нормально. Но когда я вхожу в систему как этот конкретный пользователь, происходит сбой. Этот пользователь является одним из наших самых больших пользователей, и его набор данных состоит из тысяч и тысяч записей, поэтому я не могу легко просматривать его, чтобы визуально найти вещи, которые могут быть странными. Провожу дальнейшее тестирование и обновлю это, если найду какую-либо новую информацию.
Я убежден, что это ошибка Apple, и я попытаюсь сократить ее до небольшого и повторяемого примера. Я сузил 4000 записей до 3, которые приведут к сбою. В одной из записей есть умные кавычки в одной из строк (это не должно быть проблемой, но это единственная странность). В двух других нет ничего странного. Если в моей базе данных есть A+B+C, она падает. Если у меня есть какая-либо комбинация только двух, она работает нормально.
Это хорошее исследование. Если бы вы могли убедиться, что умные кавычки вызывают сбой, вы могли бы обойти это, немного очистив входящие данные перед их использованием.
@TomHarrington У меня ушла вся ночь и все утро, но я действительно нашел проблему, и совершенно ошеломляюще, что это могло быть проблемой. Путь ключа моего имени раздела ссылался на функцию, которая вернет первую букву имени в верхнем регистре в записи (таким образом, разделы будут A, B, C, D и т. д.). Функция -uppercaseString давала мне ссылку, которая в итоге оказалась зомби.
Я понятия не имею, как это могло быть проблемой, и, возможно, кто-то, кто понимает взаимосвязь между NSString и CFString, мог бы объяснить это мне.
Мой FRC (NSFetchedResultsController) передал sectionNameKeyPath
инициализатору, чтобы он автоматически разбивал результаты на соответствующие разделы для моего табличного представления.
sectionNameKeyPath
был namefirstletter
, который является методом, который я определил в базовом классе всех моих объектов Core Data.
В моем методе -namefirstletter
у меня был этот код в конце:
NSString *uppercasefirstletter = [firstletter uppercaseString];
return uppercasefirstletter;
Этот код работает более 6 лет, никогда не было проблем. Но это внезапно проблема, поэтому мне интересно, было ли изменение в последней версии iOS или что-то в этом роде. Теперь, когда я выполняю свой FRC с приведенным выше кодом в моей функции sectionNameKeyPath, он каждый раз падает.
Однако это исправило это:
NSString *uppercasefirstletter = [NSString stringWithString:[firstletter uppercaseString]];
return uppercasefirstletter;
Теперь работает каждый раз.
-uppercaseString
возвращает мне неправильно управляемую ссылку? Кто-нибудь может мне это объяснить?
Я бы поэкспериментировал с танцем [NSString stringWithString:...]
перед вызовом uppercaseString. Это тоже решает проблему? В этом случае, я думаю, вы могли бы вместо этого прикрепить его к чему-нибудь с помощью firstLetter
.
Поскольку проблема воспроизводима, вы, вероятно, могли бы использовать инструмент распределения, чтобы исследовать освобожденный экземпляр и выяснить, почему это произошло. Однако, имея обходной путь, я бы его понял, если бы вы не хотели копать так глубоко.
Кроме того, я предлагаю сообщить об ошибке в Apple и опубликовать номер здесь, потому что у меня есть ощущение, что некоторым людям будет интересно узнать об этом.
Похоже, это известная ошибка iOS 16.1 и 16.2: https://developer.apple.com/forums/thread/717047
Я почти уверен, что если бы это был ваш код, вы бы видели его в каждом случае, а не только в одном. Если это не вылетит без включенных зомби, я зарегистрирую ошибку в Apple и двинусь дальше.