I'm very much a noob/hobbyist programmer, putting together a few simple Mac apps.
I'm confused about resource files.
I have some .png images sitting in a folder in my (XCode 4.4) project.
I also have a .plist (containing a dictionary) sitting in my Supporting Files folder.
To access the .plist, I've added a few lines of code to dig into the Bundle and get the file I'm after (pretty standard, I believe).
To use the .png files, I simply refer to them by name, and when I run from within Xcode everything does what I'm expecting.
But when I export as an Application, the images are still available and work fine, without me going into the Bundle for them.
So my question is - what determines which resource files I should go into the Bundle for, and which resource files I can assume will just be available by virtue of their being in my Supporting Files folder?
Many Thanks for reading this, and for any help you can give me.
I'm guessing that it depends on the class you are using and when you are only referring to them by name its just a convenience thing and XCode does the work nonetheless.
For example for a UIImage you can typeUIImage *image = [UIImage imageNamed:#"something"];
But XCode will do the NSSearchPathForDirectoriesInDomains or the [NSBoundle mainBoundle] thingy at build time.
You can only do the quick name referencing method on a few frequently-used classes and it's just for convenience.
This is my theory anyway, it requires confirmation.
Related
I have developed a simple app for Mac which uses a browser window to display some content. Now the assets (images etc.) are visible to anyone who receives the app and discloses the content in finder using 'show package content'.
Is there a way to prevent this? Can I hide it or encapsulate it somehow using code or some XCode function?
A trivial way would be to change the extension on your files so the system doesn't recognize them as images. You'd then have to load the images as data and convert them to images in code, which would be a bit of a pain.
A more rigorous solution would be to encrypt the images in your app bundle, then write a utility function that loads and decrypts images.
Here's another option.
You can zip all the assets. Use whatever is easiest e.g. pkzip or gzip or even just tar it all. Then you hide a lot of info and, if you want to go the extra step, it is easy to encrypt the zipped file and there are lots of libraries around to include in your project and use to unzip it with.
It should be easy to read assets directly from the zipped file, but if you need them individually you could e.g. put a single file / resource inside a zip or you could unzip it. You could even unzip to temporary space and remove it all when the app quits if you have really sensitive stuff that is too big to fit in memory.
** EDIT **
Java works this way right. A jar file is just a renamed zip and it often contains all of the resources the app needs, and it seems to be working there. So if that is a guide performance should not be too bad.
In my iOS app, I'm downloading content from the web into my /Library/Caches directory. I'd like to represent this directory as an NSBundle for better compatibility with some of the external APIs we're using. (That way, we can simply change [[NSBundle mainBundle] pathForResource...] to [myBundle pathForResource...] whenever it appears.)
The following seems to work fine:
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString* cachesDirectory = [paths objectAtIndex:0];
NSBundle* bundle = [NSBundle bundleWithPath:cachesDirectory];
Better yet, the bundle reflects any changes I make to the /Library/Caches directory. However, I'm concerned because the caches directory is technically not a bundle per Apple's docs. That is to say:
It's not a "directory with a standardized hierarchical structure that holds executable code and the resources used by that code", since there's no code.
It's neither an Application, Framework, nor a Plug-In bundle.
It's most like an Application bundle, but it doesn't contain the required Info.plist or executable.
I could find no mention anywhere of this sort of dynamically-created, resource-only bundle. Is this okay to do?
The /Library/Caches directory will lack some of the standard files which are required in a bundle, like a Contents/ directory or a Contents/Info.plist file, so it may not behave properly when treated as one. Proceed with caution.
Yes, it's absolutely okay to have a resources only bundle. Some of the verbage that you quote pre-exists iOS. In OS X you can dynamically load executable code, that's specifically excluded in iOS.
Localization is an example of resource only bundles.
Edit:
The Bundle Programming Guide says:
Although document formats can leverage the bundle structure to
organize their contents, documents are generally not considered
bundles in the purest sense. A document that is implemented as a
directory and treated as an opaque type is considered to be a document
package, regardless of its internal format. For more information about
document packages, see “Document Packages.”
which says:
There are several ways to access the contents of a document package.
Because a document package is a directory, you can access the
document's contents using any appropriate file-system routines. If you
use a bundle structure for your document package, you can also use the
NSBundle or CFBundleRef routines. Use of a bundle structure is
especially appropriate for documents that store multiple
localizations.
also note that Apple has been telegraphing that it is minimizing the use of "path"/NSString APIs in favor of URL APIs, though existing path APIs will no doubt continue for many more major OS releases.
Where is the best place to store your dependent files like xml, css and assets? I have been storing them in the src folder which works ok as they get moved to the debug folder when I build.
I can't find any info on this but I'm thinking that src is not really the place for these.
For what it's worth, here is the way Flash Catalyst CS5 (1.0.0) organizes its packages and assets when it generates a FXP:
src(default package)assetsgraphicsimagescom.adobe.flashcatalyst.componentscomponentsskins
Where graphics contains any .fxg files, and images holds all other image files. An auto-generated .css file (in my case, for embedding a font), was placed inside the (default package).
I would assume that this is how the Adobe team would expect things to be organized. However, you may also want to check out how they do it in Flash Catalyst "Panini", since the big thing with that release is the two-way workflow with Flash Builder "Burrito".
I'm working with xcode and I have classes associated with other projects that I want to be included in new projects. I realize that the #import will do the job technically (although what should i do if it's out of the project root folder). But what do I do if I want to include the class "properly" --basically so i can double click and edit out of the main project window where you can see all your files and such.
I guess I'm just looking for the best and/or proper way to include/import (into the project) .h and .m files that I've already created outside of the current project I'm working on. Taking into consideration that I may want to modify the class from the original without subclassing. Hopefully this makes sense.
Thanks,
Nick
Xcode project file organization doesn't reflect the data files on disk. Files can be added to a project from anywhere in the file system. When you add the files, choosing not to copy the files to the current project's directory means that the original files are used. Selecting one of these files in Xcode for editing will alter the original file in that other project. When returning to that other project, Xcode will use the edited files in any further work.
This type of use can be quite handy while working on multiple projects with some shared code. Yet, it can also cause headaches for a versioning system.
Might be worth thinking about how to make the classes into a private framework - then you can import that as another dependency each time. Alternatively you could use a separate version control system location to store the shared classes and just check that out into the project folder.
If you scroll down to the section 'Writing to Files and URLs' at this link, would the path varaible have to be a file on disk? Is it possible to write to a file in the bundle or must it always be deployed first?
You can write files to the application bundle as much as you'd like. Just get the path of the file through NSBundle's pathForResource:ofType: method and you can write to that file. If you want just the directory of the bundle, use resourcePath.
You don't want to do this, though. There are various reasons, but you'll break code signing, which is a big one. You should use the established conventions instead (such as writing to Library:Application Support:Your App).
EDIT: For a (possibly) more convincing reason of not to do this... When I was first learning Cocoa programming, I saved to the bundle because I didn't want to bother with the Library. It got really annoying, though, because every time you make a change to your program, you lose all of your saved data/settings for that program (assuming you're not using NSUserDefaults for preferences). I kept having to move it over from the old version to the new one. By using the Library, you don't have to worry about this.
The bundle is on disk; it's just the ".app" directory. You should not write to files in this directory, however. While currently possible on Mac, it will break code signing. On iPhone, you already can't write into your own bundle, and we should expect to see this limitation in the future on Mac. You should write your application files into various directories under ~/Library or ~/Documents as appropriate. See the File System Programming Guide for guidance.