我是objective-c和cocoa的新手,并尝试创建一个基于文档的应用程序,该应用程序可以在文件系统中保存和加载自定义类。我的符合nscoding协议的自定义类如下:
NSString * const description = @“description”;
@implementation PhotoItem
@synthesize description = _description;
-(id)init {
if(self = [super init]){
self.description = @"";
}
return self;
}
/* serializing into file */
- (void)encodeWithCoder:(NSCoder *)aCoder {
[aCoder encodeObject:self.description forKey:description];
}
/* deserializing */
- (id)initWithCoder:(NSCoder *)aDecoder {
self.description = [aDecoder decodeObjectForKey:description];
return self;
}
和我的文件:
@implementation AMRDocument
@synthesize imgMainImage = _imgMainImage, lblCreationDate = _lblCreationDate, photo=_photo,
txtDescription = _txtDescription;
- (id)init
{
self = [super init];
if (self) {
self.photo = [[PhotoItem alloc] init];
}
return self;
}
- (NSString *)windowNibName
{
return @"AMRDocument";
}
- (void)windowControllerDidLoadNib:(NSWindowController *)aController
{
NSLog(@"windowControllerDidLoadNib");
[super windowControllerDidLoadNib:aController];
// self.imgMainImage.image = self.photo.image;
[self.txtDescription setString: self.photo.description];
}
+ (BOOL)autosavesInPlace
{
return YES;
}
#pragma mark -saving and loading
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
{
// self.photo.image = self.imgMainImage.image;
// return [NSKeyedArchiver archivedDataWithRootObject:self.photo];
self.photo.description = self.txtDescription.string;
NSData *archivedData = [NSKeyedArchiver archivedDataWithRootObject:self.photo];
return archivedData;
}
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
self.photo = [NSKeyedUnarchiver unarchiveObjectWithData:data];
return YES;
}
- (void)windowWillClose:(NSNotification *)notification {
}
- (IBAction)archiveClicked:(id)sender {
self.photo = [NSKeyedUnarchiver unarchiveObjectWithFile:[@"~/desktop/myphoto1.photo"
stringByExpandingTildeInPath]];
[self.txtDescription setString:self.photo.description];
}
- (IBAction)archiveClicked:(id)sender {
self.photo.description = self.txtDescription.string;
[NSKeyedArchiver archiveRootObject:self.photo toFile:[@"~/desktop/myphoto1.photo"
stringByExpandingTildeInPath]];
}
@end
正如你所看到的,我创建了两个名为archiveClicked和unarchiveClicked的动作,一个用于写入,另一个用于从文件中读取。 它完美无缺。
当我使用命令+ s保存文档时,它也可以成功写入文件,或者至少不会抛出任何异常。但是当我试图打开保存的文件时,它会在弹出窗口中给出以下异常,而不是运行应用程序并从磁盘加载。
Exception Type: EXC_CRASH (SIGABRT)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Application Specific Information:
*** Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: '*** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (PhotoItem)'
terminate called throwing an exception
abort() called
Application Specific Backtrace 1:
0 CoreFoundation 0x00007fff8f715b06 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff912f03f0 objc_exception_throw + 43
2 CoreFoundation 0x00007fff8f7158dc +[NSException raise:format:] + 204
3 Foundation 0x00007fff98a1e8c3 _decodeObjectBinary + 2559
4 Foundation 0x00007fff98a1dd24 _decodeObject + 226
5 Foundation 0x00007fff98a90df3 +[NSKeyedUnarchiver unarchiveObjectWithData:] + 92
6 DocumentBasedApp 0x0000000108e49a11 -[AMRDocument readFromData:ofType:error:] + 113
7 AppKit 0x00007fff8d764527 -[NSDocument readFromURL:ofType:error:] + 546
8 AppKit 0x00007fff8d365348 -[NSDocument _initWithContentsOfURL:ofType:error:] + 135
9 AppKit 0x00007fff8d364ff4 -[NSDocument initWithContentsOfURL:ofType:error:] + 262
10 AppKit 0x00007fff8d78d765 -[NSDocumentController makeDocumentWithContentsOfURL:ofType:error:] + 332
11 AppKit 0x00007fff8d78ce7f __block_global_12 + 230
12 AppKit 0x00007fff8d78ca1b __block_global_8 + 955
13 AppKit 0x00007fff8d78bdba -[NSDocumentController _openDocumentWithContentsOfURL:usingProcedure:] + 593
14 AppKit 0x00007fff8d78c655 __block_global_7 + 273
15 libdispatch.dylib 0x00007fff926b4f01 _dispatch_call_block_and_release + 15
16 libdispatch.dylib 0x00007fff926b10b6 _dispatch_client_callout + 8
17 libdispatch.dylib 0x00007fff926b60c8 _dispatch_main_queue_callback_4CF + 275
18 CoreFoundation 0x00007fff8f6b7b4c __CFRunLoopRun + 1644
19 CoreFoundation 0x00007fff8f6b70e2 CFRunLoopRunSpecific + 290
20 HIToolbox 0x00007fff8df91eb4 RunCurrentEventLoopInMode + 209
21 HIToolbox 0x00007fff8df91b94 ReceiveNextEventCommon + 166
22 HIToolbox 0x00007fff8df91ae3 BlockUntilNextEventMatchingListInMode + 62
23 AppKit 0x00007fff8d44c533 _DPSNextEvent + 685
24 AppKit 0x00007fff8d44bdf2 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 128
25 AppKit 0x00007fff8d4431a3 -[NSApplication run] + 517
26 AppKit 0x00007fff8d3e7bd6 NSApplicationMain + 869
27 DocumentBasedApp 0x0000000108e49652 main + 34
28 libdyld.dylib 0x00007fff8d2647e1 start + 0
我实际上创建了检查我的nscoding函数的正确性的操作,它似乎工作正常,但没有线索,也找不到与我的问题相关的任何内容。 感谢任何帮助。不用说这是我作业的一部分。
修改
此应用程序的名称是“PhotoManager
”。之前我有另一个名为“DocumentBasedApp
”的基于文档的应用程序,该例外以:
Process: DocumentBasedApp [4852]
Path: /Users/USER/Library/Caches/*/DocumentBasedApp.app/Contents/MacOS/DocumentBasedApp
Identifier: com.cjcoax.DocumentBasedApp
Version: 1.0 (1)
Code Type: X86-64 (Native)
Parent Process: launchd [132]
User ID: 501
答案 0 :(得分:2)
您的initWithCoder:
需要致电[super init];
。
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super init];
if (self) {
self.description = [aDecoder decodeObjectForKey:description];
}
return self;
}
答案 1 :(得分:2)
MyCustomClass的序列化版本与代码中的当前版本不同,可能是由于开发过程中的更改。
/用户/用户/资源库/缓存/ * / DocumentBasedApp.app/Contents/MacOS/DocumentBasedApp
删除缓存目录删除了旧的序列化数据。
答案 2 :(得分:0)
最后解决了,我从缓存中删除了所有内容,因为我找不到以下路径:
/Users/USER/Library/Caches/*/DocumentBasedApp.app/Contents/MacOS/DocumentBasedApp
它开始工作了!奇异!
答案 3 :(得分:0)
使用NSCoder's
时,我遇到了decodeObjectForKey
FXForm
方法的另一个问题 - 它在没有任何解释的情况下崩溃了。
- (id)initWithCoder:(NSCoder *)decoder
{
if (self = [super init]) {
self.someObject = [decoder decodeObjectForKey:@"someObject"];
}
return self;
}
原因在于记忆问题。通常,看起来当日志中没有错误的解释时,这意味着它是一个内存问题。我忘了使用正确的属性属性 - 复制。我改用了assign。这是正确的代码:
@interface MyClass : : NSObject <FXForm, NSCoding>
@property (nonatomic, copy) SomeClass *someObject;
@end
以防有人遇到这个问题。