Looks like no one’s replied in a while. To start the conversation again, simply ask a new question.

blank document after loading from file

Hello guys,


I have a problem understanding how the NSCoding protocol is meant to work.


Let's describe my situation: I have an NSDocument subclass which only contains a "Canvas *canvas" (a NSView subclass). The canvas has an NSMutableArray of NSDictionary objects. Each NSDictionary has two key/value pairs: one stores an NSBezierPath object and the other stores an NSColor object.


I am trying to get the saving/loading mechanism of NSDocument work in this way: once overridden the readFromData:ofType:error: and the dataOfType:error: methods in such a way that they archive the canvas object, I override initWithCoder: and encodeWithCoder: methods of the canvas itself. Here are my implementations:


In Sketch.m (my NSDocument subclass)


- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError {

NSData *data = [NSKeyedArchiverarchivedDataWithRootObject:canvas];


if (!data && outError) {

NSDictionary *d = [NSDictionarydictionaryWithObject:typeName forKey:@"DataType"];

*outError = [NSErrorerrorWithDomain:NSOSStatusErrorDomaincode:unimpErruserInfo:d];

returnnil;

}

return data;

}


- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError {

Canvas *c = nil;


@try {

c = [[NSKeyedUnarchiverunarchiveObjectWithData:data] retain];

} @catch (NSException *exception) {

if (!c && outError) {

NSDictionary *d = [NSDictionarydictionaryWithObject:typeName forKey:@"DataType"];

[d setValue:exception forKey:@"Exception"];

*outError = [NSErrorerrorWithDomain:NSOSStatusErrorDomaincode:unimpErruserInfo:d];

returnNO;

}

}

canvas = c;

NSLog(@"%@",self);



returnYES;

}


In Canvas.m (my NSView subclass)


- (void) encodeWithCoder:(NSCoder *) coder {

[[selfwindow] endEditingFor:nil];


[superencodeWithCoder:coder];

[coder encodeObject:pathsforKey:CNVPathKey];

}


- (id)initWithCoder:(NSCoder *) decoder {

if ( (self = [super initWithCoder:decoder]) ) {

paths = [[decoder decodeObjectForKey:CNVPathKey] retain];


bgColor = [NSColorwhiteColor];

strokeColor = [NSColorblackColor];

}

NSLog(@"Loaded canvas %@.",self);

returnself;

}


That seems to work fine. The methods encode and decode my NSMutableArray and one restored from the archive all data is correct. Then I got the problem. Immediatly after initWithCoder: returns the decoded object, this is litterally thrown away and a new BLANK instance of Canvas gets created, so I am never able to really load anything.


Is there some basis I don't know to get it work? I don't understend why Canvas's init method gets called since initWithCoder: should not call the designated initializer.

Mac OS X (10.6.8)

Posted on Feb 28, 2012 5:51 AM

Reply
2 replies

Feb 28, 2012 11:01 AM in response to gianlucaFromTrieste

Solved!


Looks like one cannot unarchive a view and visualize it because the actual instance of the NSDocument subclass doesn't get created until readFromData:ofType:error returns YES. It is then obvious that setting the canvas instance variable of my document doesn't really do anything since the object has not yet been allocated and have therefore no storage memory avaliable for instance variables.


A workaround which worked for me was to insert a pointer to the "paths" NSMutableArray (which is a view's property. Ok, I may have mismodeled my application) into the Sketch (NSDocument subclass) definition and then only archive that array. Fortunately NSDictionary conforms to the NSCoding protocol so I don't need to teach any object to encode itself.


Ok, this is now a useless but I really hope it can be helpful to someone else.


Thanks anyway to anyone who has thought of a solution!

See you on the next thread!


Gianluca

blank document after loading from file

Welcome to Apple Support Community
A forum where Apple customers help each other with their products. Get started with your Apple ID.