I'm creating a 'test' document based application to learn more about how they work. I want to load an array that I saved earlier.
- (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
{
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSArray *array = [string componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
documentTitle.stringValue = [array objectAtIndex:0];
// For testing
NSLog(@"%@", array);
}
I loaded the file and got the data. I converted the data into an NSString. The file has multiple lines and every line has its own value. The first line is the document title. So I created an NSArray that put every line separately in the array. Then I set the first line of the document to the documentTitle label. For testing purposes I created an NSLog function too. It has to log the array.
The problem is that when I run the code, it doesn't do anything at all. The documentTitle.stringValue doesn't change. But the strange thing is that it does log the array:
2015-09-22 16:57:40.098 DocBased Test[10765:277445]
(
"The awesome title!",
"This is a document!"
)
I declared the documentTitle in the Document.h like this:
#import <Cocoa/Cocoa.h>
@interface Document : NSDocument
{
IBOutlet NSTextField *documentTitle;
}
@end
If you need to view the project in Xcode here's a link: The link.
Does anyone know how to change the stringValue of the documentTitle (or any) label in the Document class?
Given your project @ https://www.mediafire.com/?z6drw20suvt0re0,
I was able to get it working. Writing a new answer because my original is already really bulky, and fits more of a general case; whereas this answer will be very specific with your code
Only a few changes:
1) Because your Document.xib's owner is Document
, you do not need to drag in the Document Object into your Document Outline. So I deleted that.
2) I selected the File's Owner (Document), and set up the connection to your NSTextField property
3) I removed the ivar
@interface Document : NSDocument
{
IBOutlet NSTextField *documentTitle;
}
so your header now looks like this:
@interface Document : NSDocument
@end
4) I created the property inside of your implementation file (Document.m) as well as an NSString
property (I will explain that in a second)
@property NSString *titleString;
@property IBOutlet NSTextField *documentTitle;
5) So if you go ahead and override the -awakeFromNib
method (Just put an NSLog
or something in there), you will see that in fact -awakeFromNib
is being called AFTER -readFromData
. Now remember what I said-- that the object is instantiated, but no connections are made until the view is loaded and the -awakeFromNib
message is sent.
So what happens is this:
Document
is instantiated-readData...
is called immediately during instantiation, but the connection to the NSTextField
isn't made yet, so it's nil
-awakeFromNib
is called, and the connections from Document
to any NSView
s (including your NSTextField
) are madeSo the solution is simple,
in the -readData
method, instead of setting your NSTextField
's stringValue
, you should just save the string you read into a NSString
property (What I mentioned earlier)
Then when your -awakeFromNib
is called, you can just access that NSString
property for the value you want, and set the stringValue
then.
Here are the two methods that were changed:
-(void)awakeFromNib
{
if( self.titleString )
{
[self.documentTitle setStringValue:self.titleString];
}
}
- (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.
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSArray *array = [string componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]];
NSLog(@"\r%@", array);
self.titleString = [array objectAtIndex:1];
return YES;
}
Let me know if you would like more explanation anywhere, but this will work for you :)