1) Создайте в Xcode проект типа Cocoa Application.
2) Щёлкните на проект DocBasedAppExample, далее на target DocBasedAppExample, перейдите на вкладку Info, и раскройте пункт Document Types.
Измените Name DocumentType на что-то более осмысленное, например, на Plain Text.
3) Добавьте в Document.xib текстовое поле NSTextView в котором будет отображаться содержимое текстового файла.
#import <Cocoa/Cocoa.h> @interface Document : NSDocument @property (assign) IBOutlet NSTextView *textView; @end
4) Далее нужно реализовать метод dataOfType:error: класса Document, который по умолчанию выглядит так:
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError { // Insert code here to write your document to data of the specified type. If outError != NULL, ensure that you create and set an appropriate error when returning nil. // You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead. NSException *exception = [NSException exceptionWithName:@"UnimplementedMethod" reason:[NSString stringWithFormat:@"%@ is unimplemented", NSStringFromSelector(_cmd)] userInfo:nil]; @throw exception; return nil; }
Требуется имплементация этого метода.
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError { if ([typeName compare:@"Plain Text"] == NSOrderedSame) { return [_textView.textStorage.string dataUsingEncoding:NSUTF8StringEncoding]; } NSLog(@"ERROR: dataOfType typeName=%@", typeName); *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:nil]; return nil; }
5) Далее нужно реализовать метод readFromData:ofType:error: класса Document, который по умолчанию выглядит так:
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
// Insert code here to read your document from the given data of the specified type. If outError != NULL, ensure that you create and set an appropriate error when returning NO.
// You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead.
// If you override either of these, you should also override -isEntireFileLoaded to return NO if the contents are lazily loaded.
NSException *exception = [NSException exceptionWithName:@"UnimplementedMethod" reason:[NSString stringWithFormat:@"%@ is unimplemented", NSStringFromSelector(_cmd)] userInfo:nil];
@throw exception;
return YES;
}
Требуется имплементация этого метода.
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError { if ([typeName compare:@"Plain Text"] != NSOrderedSame) { NSLog(@"** ERROR ** readFromData typeName=%@", typeName); *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL]; return NO; } // end if NSDictionary *zDict = [NSDictionary dictionaryWithObjectsAndKeys:NSPlainTextDocumentType, NSDocumentTypeDocumentAttribute, nil]; NSDictionary *zDictDocAttributes; NSError *zError = nil; NSAttributedString * zNSAttributedStringObj = [[NSAttributedString alloc]initWithData:data options:zDict documentAttributes:&zDictDocAttributes error:&zError]; if (zError != nil) { NSLog(@"Error readFromData: %@",[zError localizedDescription]); return NO; } // end if fileContents = [zNSAttributedStringObj string]; return YES; }
Так как компонент NSTextView во время выполнения метода readFromData:ofType:error: оказывается еще неинициализированным, то нам понадобилась глобальная переменная fileContents.
#import "Document.h" @implementation Document { NSString *fileContents; } - (id)init { self = [super init]; if (self) { // Add your subclass-specific initialization here. fileContents = @""; } return self; } - (void)windowControllerDidLoadNib:(NSWindowController *)aController { [super windowControllerDidLoadNib:aController]; // Add any code here that needs to be executed once the windowController has loaded the document's window. _textView.string = fileContents; }
Пост написан на основе этой статьи.