Простое приложение для документов, вызывающее исключение при возврате к сохраненному в Mac OS X 10.7 Lion

У меня есть простое приложение для документов, основанное на шаблоне документа, которое выдает исключение, когда в Mac OS X 10.7 выбран пункт меню «Вернуться к сохраненному -> Последняя открытая версия».

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

Я понимаю, что это, вероятно, ошибка в Lion, но мне нужно найти обходной путь.

См. ниже исключение и все содержимое (очень маленькое) моего подкласса NSDocument.

Этапы воспроизведения

  • открыть любой документ
  • введите один символ в текстовое представление
  • выберите Файл -> Вернуться к сохраненному
  • нажмите Последняя открытая версия

Исключение

2011-09-04 07:10:29.182 myapp[15433:707] *** -[NSPathStore2 stringByAppendingPathExtension:]: nil argument
2011-09-04 07:10:29.191 myapp[15433:707] (
  0   CoreFoundation                      0x00007fff89c2b986 __exceptionPreprocess + 198
  1   libobjc.A.dylib                     0x00007fff90c6ed5e objc_exception_throw + 43
  2   CoreFoundation                      0x00007fff89c2b7ba +[NSException raise:format:arguments:] + 106
  3   CoreFoundation                      0x00007fff89c2b744 +[NSException raise:format:] + 116
  4   Foundation                          0x00007fff86d2b172 -[NSPathStore2 stringByAppendingPathExtension:] + 112
  5   AppKit                              0x00007fff9148f8c3 -[NSDocument _preserveCurrentVersionForReason:error:] + 579
  6   AppKit                              0x00007fff9147655b __-[NSDocument _revertToVersion:preservingFirst:error:]_block_invoke_3 + 99
  7   Foundation                          0x00007fff86ef28c3 __-[NSFileCoordinator coordinateReadingItemAtURL:options:error:byAccessor:]_block_invoke_1 + 113
  8   Foundation                          0x00007fff86ef2f34 -[NSFileCoordinator(NSPrivate) _invokeAccessor:orDont:thenRelinquishAccessClaimForID:] + 202
  9   Foundation                          0x00007fff86d98a28 -[NSFileCoordinator(NSPrivate) _coordinateReadingItemAtURL:options:error:byAccessor:] + 663
  10  Foundation                          0x00007fff86ef284c -[NSFileCoordinator coordinateReadingItemAtURL:options:error:byAccessor:] + 79
  11  AppKit                              0x00007fff91484b41 __-[NSDocument _revertToVersion:preservingFirst:error:]_block_invoke_1 + 347
  12  AppKit                              0x00007fff914901e3 -[NSDocument performSynchronousFileAccessUsingBlock:] + 42
  13  AppKit                              0x00007fff9148fc90 -[NSDocument _revertToVersion:preservingFirst:error:] + 125
  14  AppKit                              0x00007fff91476cf9 -[NSDocument _revertToDiscardRecentChangesPreservingFirst:error:] + 43
  15  AppKit                              0x00007fff91477094 __-[NSDocument _revertToDiscardRecentChangesThenContinue:]_block_invoke_3 + 164
  16  AppKit                              0x00007fff91474851 __-[NSDocument performSynchronousFileAccessUsingBlock:]_block_invoke_1 + 19
  17  AppKit                              0x00007fff91475bda -[NSDocument continueFileAccessUsingBlock:] + 227
  18  AppKit                              0x00007fff91490413 -[NSDocument _performFileAccessOnMainThread:usingBlock:] + 466
  19  AppKit                              0x00007fff9149023f -[NSDocument performSynchronousFileAccessUsingBlock:] + 134
  20  AppKit                              0x00007fff91495891 __-[NSDocument _revertToDiscardRecentChangesThenContinue:]_block_invoke_2 + 301
  21  AppKit                              0x00007fff914909a9 -[NSDocument _something:wasPresentedWithResult:soContinue:] + 21
  22  AppKit                              0x00007fff91381bee -[NSAlert didEndAlert:returnCode:contextInfo:] + 93
  23  AppKit                              0x00007fff9138e356 -[NSApplication endSheet:returnCode:] + 275
  24  AppKit                              0x00007fff91381ab4 -[NSAlert buttonPressed:] + 265
  25  CoreFoundation                      0x00007fff89c1b11d -[NSObject performSelector:withObject:] + 61
  26  AppKit                              0x00007fff911dd852 -[NSApplication sendAction:to:from:] + 139
  27  AppKit                              0x00007fff911dd784 -[NSControl sendAction:to:] + 88
  28  AppKit                              0x00007fff911dd6af -[NSCell _sendActionFrom:] + 137
  29  AppKit                              0x00007fff911dcb7a -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 2014
  30  AppKit                              0x00007fff9125c57c -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 489
  31  AppKit                              0x00007fff911db786 -[NSControl mouseDown:] + 786
  32  AppKit                              0x00007fff911a666e -[NSWindow sendEvent:] + 6280
  33  AppKit                              0x00007fff9113ef19 -[NSApplication sendEvent:] + 5665
  34  AppKit                              0x00007fff910d542b -[NSApplication run] + 548
  35  AppKit                              0x00007fff9135352a NSApplicationMain + 867
  36  myapp                               0x00000001000018d2 main + 34
  37  myapp                               0x00000001000018a4 start + 52
)

Подкласс NSDocument

@implementation MyTextDocument

@synthesize textStorage;
@synthesize textView;

+ (BOOL)autosavesInPlace
{
  return YES;
}

- (id)init
{
    self = [super init];
    if (self) {
      self.textStorage = nil;
      self.textView = nil;

      textContentToLoad = [@"" retain];
    }
    return self;
}

- (NSString *)windowNibName
{
  return @"MyTextDocument";
}

- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
  [super windowControllerDidLoadNib:aController];

  self.textStorage = self.textView.textStorage;
  [self loadTextContentIntoStorage];
}

- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
{
  return [self.textStorage.string dataUsingEncoding:NSUTF8StringEncoding];
}

- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
  textContentToLoad = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  if (!textContentToLoad) {
    *outError = [NSError errorWithDomain:NSCocoaErrorDomain code:NSFileReadUnknownError userInfo:nil];
    return NO;
  }

  [self loadTextContentIntoStorage];

  return YES;
}

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

  [self.textStorage beginEditing];
  [self.textStorage replaceCharactersInRange:NSMakeRange(0, self.textStorage.length) withString:textContentToLoad];

  [textContentToLoad release], textContentToLoad = nil;
}

@end

person Abhi Beckert    schedule 03.09.2011    source источник


Ответы (2)


Правильно ли настроен ваш plist, когда дело доходит до типов?

Похоже, что NSDocument передает результат [self fileNameExtensionForType:[self autosavingFileType] saveOperation:NSAutosaveElsewhereOperation] в stringByAppendingPathExtension: (метод, который здесь генерирует исключение). Если ваше приложение возвращает nil для этого выражения, может возникнуть это исключение.

Вам, вероятно, следует сообщить об ошибке в Apple, но пока убедитесь, что ваше приложение возвращает что-то не-nil.

person kperryua    schedule 04.09.2011
comment
Вот оно, спасибо! Я думаю, что мои документы настроены правильно, но для моего приложения (обычного текстового редактора) нет четкого правильного расширения. Я переопределил -fileNameExtensionForType:, чтобы возвращать self.fileURL.pathExtension, если он существует, и @"txt" в противном случае. - person Abhi Beckert; 04.09.2011

Вставьте это в свой класс документа (например, Document.m):

-(NSString*)fileNameExtensionForType:(NSString *)typeName saveOperation:    (NSSaveOperationType)saveOperation
{
    return @"yourAutosaveExtension";
}

Раньше, как сказал kperryua, этот метод не реализовывался и возвращал nil.

person Erik    schedule 22.04.2012