Непонятная кодировка исключения в NSTextStorage - PullRequest
20 голосов
/ 07 декабря 2011

У меня есть подкласс NSDocument для простого текстового редактора (с использованием нового шаблона приложения на основе документов Lion, с небольшим количеством настроек), и я сталкиваюсь со странной ошибкой при загрузке содержимого файла в текстовое хранилище.

Вот мой код:

- (void)loadTextContentIntoStorage
{
  if (!self.textStorage || !textContentToLoad)
    return;

  ...

  [self.textStorage beginEditing];

//  NSLog(@"storage: %@ length: %lu textContent: %@", self.textStorage, (unsigned long)self.textStorage.length, textContentToLoad);
//  [self.textStorage replaceCharactersInRange:NSMakeRange(0, self.textStorage.length) withString:textContentToLoad];
  [self.textStorage replaceCharactersInRange:NSMakeRange(0, 0) withString:@"hello world"];

  ..

  [self.textStorage endEditing];
}

Ошибка возникает, когда я:

  • запускаю приложение в Xcode (как отладочная сборка)
  • открываю любой документ
  • выйти из приложения (не закрывая документ)
  • снова запустить приложение из XCode

Вылетает в -replaceCharactersInRange:withString: с «Невозможно преобразовать байты в строке 0x10004d430 в_NSCStringEncoding ".

Но это происходит только при каждом втором запуске приложения (при третьем запуске не произойдет сбой, и автоматически откроет документразбился при попытке открыть в прошлый раз).Это также происходит только тогда, когда я запускаю приложение из Xcode.Релизные сборки никогда не ломались при запуске.

Я думал, что это может быть проблема с кодировкой в ​​системе автосохранения, но она даже вылетает, когда я закомментирую этот код и просто загружаю строку @ "hello world" впросмотр текста (как показано в приведенном выше коде).Точно так же, закомментированный NSLog() не показывает ничего странного.Хранение текста допустимо (загружено из файла xib), длина хранения текста равна 0, а textContent - это содержимое открываемого файла.

--- EDIT --

Я узнал, что эта проблема каким-то образом связана с правом com.apple.security.app-sandbox.Если права / песочница включены , то мое приложение не вылетает .Если права доступа или функция песочницы приложения отключены , то мое приложение аварийно завершает работу при каждом втором запуске, пытаясь восстановить ранее открытые документы.

Я только заметил, что это происходит при сборке /запустить изнутри xcode, потому что это была моя единственная конфигурация сборки с отключенной песочницей.

--- / EDIT ---

У кого-нибудь есть идеи?Далее следует полное исключение, а полный исходный код находится на github: https://github.com/abhibeckert/Dux/blob/master/Dux/DuxTextView.m

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Unable to convert bytes in string 0x10004d430 to _NSCStringEncoding'
*** First throw call stack:
(
    0   CoreFoundation                      0x00007fff84afb286 __exceptionPreprocess + 198
    1   libobjc.A.dylib                     0x00007fff88991d5e objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff84afb0ba +[NSException raise:format:arguments:] + 106
    3   CoreFoundation                      0x00007fff84afb044 +[NSException raise:format:] + 116
    4   Foundation                          0x00007fff835bfae4 copyFromStringToStorage + 262
    5   Foundation                          0x00007fff835bf979 -[NSBigMutableString replaceCharactersInRange:withString:] + 1000
    6   Foundation                          0x00007fff835bc3f7 -[NSConcreteMutableAttributedString replaceCharactersInRange:withString:] + 375
    7   AppKit                              0x00007fff86149e14 -[NSConcreteTextStorage replaceCharactersInRange:withString:] + 81
    8   Dux                                 0x0000000100002f9a -[MyTextDocument loadTextContentIntoStorage] + 1338
    9   Dux                                 0x00000001000022a0 -[MyTextDocument windowControllerDidLoadNib:] + 640
    10  AppKit                              0x00007fff860f1328 -[NSWindowController _windowDidLoad] + 667
    11  AppKit                              0x00007fff860e89a3 -[NSWindowController window] + 109
    12  AppKit                              0x00007fff8615d761 -[NSDocument windowForSheet] + 86
    13  AppKit                              0x00007fff860e82c4 -[NSDocument _shouldShowAutosaveButtonForWindow:] + 50
    14  AppKit                              0x00007fff860e7fbb -[NSWindowController setDocument:] + 237
    15  AppKit                              0x00007fff8629c9b6 -[NSDocument makeWindowControllers] + 139
    16  AppKit                              0x00007fff8615d555 -[NSDocument(NSPersistentUISupport) restoreDocumentWindowWithIdentifier:state:completionHandler:] + 90
    17  AppKit                              0x00007fff8615d4aa -[NSDocumentControllerPersistentRestoration loadedDocument:forAutoID:] + 179
    18  AppKit                              0x00007fff8615cfbe __-[NSDocumentController reopenDocumentForURL:withContentsOfURL:display:completionHandler:]_block_invoke_8 + 187
    19  AppKit                              0x00007fff86148e14 __-[NSDocumentController reopenDocumentForURL:withContentsOfURL:display:completionHandler:]_block_invoke_5 + 163
    20  AppKit                              0x00007fff86148d5f __-[NSDocumentController reopenDocumentForURL:withContentsOfURL:display:completionHandler:]_block_invoke_4 + 697
    21  AppKit                              0x00007fff86148aa1 -[NSDocumentController _openDocumentWithContentsOfURL:usingProcedure:] + 530
    22  AppKit                              0x00007fff8614868d __-[NSDocumentController reopenDocumentForURL:withContentsOfURL:display:completionHandler:]_block_invoke_3 + 242
    23  libdispatch.dylib                   0x00007fff8bbbe8ba _dispatch_call_block_and_release + 18
    24  libdispatch.dylib                   0x00007fff8bbc072a _dispatch_main_queue_callback_4CF + 308
    25  CoreFoundation                      0x00007fff84a904dc __CFRunLoopRun + 1724
    26  CoreFoundation                      0x00007fff84a8fae6 CFRunLoopRunSpecific + 230
    27  HIToolbox                           0x00007fff8852f3d3 RunCurrentEventLoopInMode + 277
    28  HIToolbox                           0x00007fff8853663d ReceiveNextEventCommon + 355
    29  HIToolbox                           0x00007fff885364ca BlockUntilNextEventMatchingListInMode + 62
    30  AppKit                              0x00007fff85ef23f1 _DPSNextEvent + 659
    31  AppKit                              0x00007fff85ef1cf5 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 135
    32  AppKit                              0x00007fff85eee62d -[NSApplication run] + 470
    33  AppKit                              0x00007fff8616d80c NSApplicationMain + 867
    34  Dux                                 0x0000000100001e32 main + 34
    35  Dux                                 0x0000000100001e04 start + 52
    36  ???                                 0x0000000000000003 0x0 + 3
)

Ответы [ 3 ]

5 голосов
/ 02 апреля 2012

Признаюсь, этот вопрос меня озадачил довольно давно.Я думаю, что наконец-то нашел репро.

Просматривая код GNUstep , имитирующий это поведение , я нашел следующий исходный код:

if (enc == NSASCIIStringEncoding
    && isByteEncoding(internalEncoding))
    {
      unsigned  i;

      if (bytes > self->_count)
    {
      bytes = self->_count;
    }
      for (i = 0; i < bytes; i++)
    {
      unsigned char c = self->_contents.c[i];

      if (c > 127)
        {
          [NSException raise: NSCharacterConversionException
              format: @"unable to convert to encoding"];
        }
      buffer[i] = c;
    }
      buffer[bytes] = '\0';
      if (bytes < self->_count)
    {
      return NO;
    }
      return YES;
    }
...

Очевидно, этот код не совпадает с вашим сообщением об ошибке. Однако, Я заметил это из вашего сообщения об ошибке:

reason: 'Unable to convert bytes in string 0x10004d430 to_NSCStringEncoding'

Ну, мы все знаем, что такое строка C * , и если вы используете неправильный метод кодирования (например, Wide, где ожидается ASCII или наоборот), вы столкнетесь именно с этой проблемой.Таким образом: вы пытались варьировать типы данных ASCII и Wide в своем приложении, чтобы решить эту проблему?

Из-за того, как часто это происходит, очень вероятно, что это обработанный случай в изолированной программной среде приложения.Однако я пока не могу найти документацию на этот счет.Это должно быть что-то явно отмеченное sandboxd, как я поднял в вопросе об ошибках.

1 голос
/ 27 мая 2015

Я получил то же исключение на 10.9.2.

 Unable to convert bytes in string 0x60800026cd40 to _NSCStringEncoding
 (
    0   CoreFoundation                      0x00007fff8dec825c __exceptionPreprocess + 172
    1   libobjc.A.dylib                     0x00007fff81de0e75 objc_exception_throw + 43
    2   CoreFoundation                      0x00007fff8dec810c +[NSException raise:format:] + 204
    3   Foundation                          0x00007fff8d94dd2b copyFromStringToStorage + 223
    4   Foundation                          0x00007fff8d94db9e -[NSBigMutableString replaceCharactersInRange:withString:] + 1081
    5   Foundation                          0x00007fff8d94d738 -[NSConcreteMutableAttributedString replaceCharactersInRange:withAttributedString:] + 296
    6   AppKit                              0x00007fff88d7889c -[NSConcreteTextStorage replaceCharactersInRange:withAttributedString:] + 77
    9   myApp                            0x00000001035d3fff myApp + 12287
    10  CoreFoundation                      0x00007fff8de96e0c __CFNOTIFICATIONCENTER_IS_CALLING_OUT_TO_AN_OBSERVER__ + 12
    11  CoreFoundation                      0x00007fff8dd8a82d _CFXNotificationPost + 2893
    12  Foundation                          0x00007fff8d8f8e4a -[NSNotificationCenter postNotificationName:object:userInfo:] + 68
    13  AppKit                              0x00007fff88b99cde -[NSApplication finishLaunching] + 440
    14  AppKit                              0x00007fff88b997f3 -[NSApplication run] + 128
    15  AppKit                              0x00007fff88b84783 NSApplicationMain + 940
    16  libdyld.dylib                       0x00007fff81aa65fd start + 1
    17  ???                                 0x0000000000000001 0x0 + 1
)

Я использовал NSTextStorage в applicationWillFinishLaunching. Я переместил это в applicationDidFinishLaunching и оно работает нормально.

0 голосов
/ 16 августа 2012

Это, похоже, ошибка в OS X 10.7 (Lion). С нулевыми изменениями в моем коде сбой больше не происходит на OS X 10.8 (Mountain Lion) в соответствии с Xcode 4.4.1.

...