Creating a NSData object from an included file - macos

I have an application which creates strict folder structures.
I also have some template files which should be placed in specific folders within that structure. My problem is that I'm not sure how to point to those files (which I've included in the project) so that I can create an NSData object from them. The plan was then to call the createFileAtPath:contents:attributes: method of NSFileManager to save them to the folders.
How can I reference these included files? I tried using the NSData dataWithContentsOfFile: method and just setting the name of the file like so:
[NSData dataWithContentsOfFile:#"Storyboard.template"];
but that does not appear to work.
Is there perhaps a better way of doing this?

If by, "I've included in the project", you mean you have these files in your bundle, then you should use the NSBundle method, pathForResource:ofType:, or one of its siblings to get the path.

Related

Execute different NSDocument subclass according to file extensions

I have written different parsers and different NSDocument subclasses for files with different extensions to visualize the data. I would like to intergrate them together into one application. I am using NSDocument architecture. I am not sure how to map files identified by file extensions to its NSdocument object.
I have tried to add document types in the Xcode info session with class and extensions. However, it seems that it always execute the same parser regardless of the file's extension.
1)Subclass NSDocumentController
a)in your XIB with mainmenu put a new object and give it a class of your new NSDocumentController subclass
or
b)create a new instance before appDidFinishLaunching (initialize, load...)
2)override methods as you see on picture (those which determine type and return document instances) to provide new document instances (as per type)
Read more here
Also scan with your eyes NSDocumentController.h (CMD+SHIFT+O and type NSDoc...)

what does "failed to load window nib file" mean?

I'm working on my first Cocoa application, and I'm hoping very much that
[NSWindowController loadWindow]: failed to load window nib file 'Genius Document'
means that there's something very specific I've done wrong, because if I have to go back and redo all the bindings I'll want to kill myself.
FWIW, I'm working with a document-based application that has (so far) only one XIB file and no NIB files.
I can post code/screenshots of my bindings but in case that's not necessary I didn't want to make people wade through them.
Thanks for the help.
The error you have described ultimately occurs because a call to load the nib file is failing. Make sure you've supplied the correct name for your Interface Builder file.
You can supply the correct value in a number of ways (depending on your use of AppKit), so I'll lay out the two most common possibilities and you can track down which one applies to you. Given what you've said in your question, I suspect you'll be dealing with the first scenario.
NSDocument windowNibName
If you are relying on the document architecture's defaults, you are probably not making the call in question directly. Instead, the framework makes the call on your behalf, using whatever nib name you specify on the given document class.
For example, if you were to make a new document-based project with a document class of "XYZDocument," the Xcode template would provide you with a basic XYZDocument class and a XYZDocument.xib file. The XYZDocument implementation file would have the following in it:
// XYZDocument.m
- (NSString *)windowNibName {
return #"XYZDocument"; // this name tells AppKit which nib file to use
}
If you were to alter this value, you would create the [NSWindowController loadWindow] error.
NSWindowController initialization methods
If you are making this call yourself (perhaps on your own subclass of NSWindowController), then you will have written a line like the following.
// XYZWindowController.m (a subclass of NSWindowController)
- (id)init {
self = [super initWithWindowNibName:#"XYZDocument"];
if (self) {
// initializations
}
return self;
}
If the string argument you've supplied does not match the name of the nib file, the same error will occur.
I ran a Clean (Cmd-Shift-K) in Xcode and that solved the issue for me.

how to read sdef file

I am trying with NSArray.arrayWithContentsOfFile_("bla.sdef") but that returns None.
I also tried NSDictionary.dictionaryWithContentsOfFile_("bla.sdef") but that also returns None.
I am trying to get a NSDictionary object in the end in a form where parts of it are conforming to the dict for NSScriptCommandDescription initWithSuiteName:commandName:dictionary:.
(Note: I don't want to know here how to load scripting definitions into NSScriptSuiteRegistry. I really just want to know here how to read the sdef-file.)
Those methods are for reading property-list files. An sdef file is not a property list; it follows a different, purpose-specific XML schema, defined in sdef(5).
I don't think there is a public API for reading sdef files directly into a dictionary or more scripting-specific object; you'll need to do it yourself using an XML parser (either one of Cocoa's or one of Python's).

How to parse the contents of a foreign file created with NSKeyedArchiver

I need to be able to compare two versions of a plist file created with NSKeyedArchiver. In particular, it's the "elements" file created in Xcode for a .xcdatamodeld file.
Since I have not created this file myself I can not recreate its object model. Instead, I need to understand which classes and keyed properties the archive contains.
Ideally, I want to create a tree containing strings representing the names of classes along with their property names and values. I assume that all this information is stored in the archive, so it should be possible to generically parse this archive, right?
I've read about NSKeyedUnarchiver and its delegate. I've only gotten as as as this:
Unarchive the file data:
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
unarchiver.delegate = self;
id graph = [unarchiver decodeObjectForKey:#"root"];
Here's the delegate method that gets called when an unknown class is requested. I return a proxy class here in which I hope to collect its values:
- (Class)unarchiver:(NSKeyedUnarchiver *)unarchiver cannotDecodeObjectOfClassName:(NSString *)name originalClasses:(NSArray *)classNames
{
NSLog(#"wants: %#", name);
return [ObjProxy class];
}
The proxy class implements
- (id)initWithCoder:(NSCoder *)aDecoder
in which I do not know how to proceed, not knowing the actual properties of the classes. NSCoder doesn't seem to provide any function to learn of the available keys. Is there a trick to get to them, maybe by overriding some of the lower level objc methods?
So far, with this little code shown above, when parsing the "elements" file, I only get the request for one class, "XDPMModel", and then it's done.
Any ideas how to get this working, i.e. traverse the tree deeper?
You can use PlistExplorer, it's a Cocoa Tool to inspect files written by NSKeyedArchiver.
I've done exactly this before, to decode objects stored in the preferences file for Panic's Coda. What I did was to use class-dump on the app (in your case Xcode and its related frameworks), which allows you to see the properties of the real objects, and use these to create proxy objects that match those properties. You can then use NSKeyedUnarchiver successfully and query the proxy objects for their values.
It's a fairly laborious process but it works perfectly. In my case I was working with a user defaults plist so I only had to define a couple of these proxy classes for the objects I was interested in, but I would imagine that you'll have to define quite a few for Xcode.
I'd also be very interested to know if there's a way to do this without having to go the class-dump route (possibly, as you say, via some of the lower-level Objective-C functions) because it would greatly simplify this type of reverse engineering.

Should header files be included in .h or .m files?

If I have four .h/.m file pairs
file1.h
file2.h
file3.h
file4.h
where I am using file1.h, file2.h, and file3.h functionality in file4, should those header files be included in file4.h or file4.m?
In the .m file if possible. You may have to forward declare classes in the .h file, like:
#class AClassIImportInDotMFile;
If Class B is a subclass of Class A, you need to import Class A's .h file in Class B's .h file.
I assume file4.h is going to be used by other .m files. If so, only include in file4.h what is used in file4.h, and the rest in file4.cpp. This will reduce the overal number of inclusions and including file4.h will not pull useless additional headers.
When the number of required .h files starts to grow inconveniently, you can group them in topic headers. For instance, topic1.h may include file1.h and file2.h but not file3.h.
I Usually import the other headers into the current header file if I plan on using their classes in property declaration. However this can create some havoc if the classes reference each other.
If this is the case then you will want to include the headers in the .m file so they can be used inside the class, but for any external access to these items you would use id in the place of your custom classes. And cast them when you get them in the other referencing methods.
I run into this issue if I include the AppDelegate.h and then reference the other class in app delegate.
the reason for this would be that I want to include a reference to my current object in the app delegate, but the class also uses the app delegate to access other classes. In this case I would include the Classes in the AppDelegate.h and include AppDelegate.h in the m file of the class.
I hope that made sense.

Resources