What is the application Bundle and Resources folder - objective-c

My question is about the application bundle in a project. I was reading about that and can understand some basic things (I'm not a native english speaker). I can understand that the resources folder is used to hold the files that will be used in the project, e.g. media files (images, audio, video, etc.) and should be in the application bundle to be identified.
So, what is the point if I want to use images and another resources in my project? In my other related question, I can't use them by referencing with NSImage imageNamed:.
I have used the following with no success loading my files:
NSBundle methods
imageNamed:#"string" with/without file extension
the images are in resources folder
I'm learning Cocoa and Objective-C, and of course this is different to C++ or Java when I want to create an ImageIcon or a QImage.

I may not have completely understood the issue, so correct me if I am wrong. I believe the problem has to do with your image's target membership or how you're retrieving the image in your code.
Adding an image to your project target will appropriately copy the resource at compile time. To add the image to your target, select it in the file navigator and then reveal the Utilities Panel. On the Utilities Panel, select the File Inspector Tab. Look for the Target Membership section and ensure that the image is selected for the desired targets:
Do you mean that you can't use the NSImage imageNamed: method to retrieve resources? If so, you can retrieve the resource like this (from the main resource bundle):
NSString *imageName = [[NSBundle mainBundle] pathForResource:#"image1" ofType:#"png"];
NSImage *imageObj = [[NSImage alloc] initWithContentsOfFile:imageName];
It also looks like you already have a good answer to your other related question.

Related

Add an image (or other resources) to a Mac or iOS Framework

Let's say I have an existing iOS or Mac Framework that we'll call Test.framework. This framework has compiled and linked successfully (a trick was done to lipo both i386 and armv6/7 archs for the iOS part) and is working perfectly fine.
Now I want to add an image to it let's call it 'test.png'. I have copied it into the Resources folder of my framework so that I have the following structure:
ls Test.framework
- Headers -> Versions/Current/Headers
- Resources -> Versions/Current/Resources
- Test -> Versions/Current/Test
- Versions
ls Test.framework/Resources
- Info.plist
- test.png
Yet when I create a project using my framework I cannot access that image.
I've tried:
[UIImage imageNamed:#"test.png"]
[UIImage imageNamed:#"Test.framework/test.png"]
[UIImage imageNamed:#"Test.framework/Resources/test.png"]
But nothing worked out that always gave me back a nil object.
Any ideas ?
EDIT
After much further investigation it seems what I am trying to accomplish can't be done on iOS. The reason is that the final application bundle (the .app) doesn't copy the private frameworks where applications compiled for Mac OS will.
This is further detailed in the iOS Bundle Structures documentation.
Thanks to Rob Keniger and xuzhe for their appreciated help. I will credit xuzhe for the answer as it is actually the most appropriate answer to my original problem (even though Rob comment made me dig quite deeper into the issue)
The "imageNamed:" method is only for images in your App bundle. You should use
[[UIImage alloc] initWithContentsOfFile:path];
instead.
About the path, since I am not sure if the "Test.Framework" is in you App bundle, I am not able to give you a sample code. But if it dose, the code below should work:
NSString* path = [Nsstring stringWithFormat:#"%#/Test.framework/Resources/test.png", [[NSBundle mainBundle] bundlePath]];
You can get the bundle for a particular class using [NSBundle bundleForClass:[SomeClass class]]. All you need to do is pass in a class that's defined in the framework and you'll have a reference to the framework's bundle.
You can then ask the bundle for the path to the image using the pathForResource:ofType: method of NSBundle, and then use the initWithContentsOfFile: method of NSImage to create your image.
Note that you should never hard-code paths. Ever. There are many different functions and methods for obtaining paths to resources, you never need to hard-code them.

Show contents of a zip file in a WebView

I want to have a WebView that displays some static files from the application bundle. Since I have a large number of small files, I'd like to pack them all into a compressed archive so the application doesn't take up too much space. What's the best way to make this happen?
This should help you out: http://code.google.com/p/ziparchive/
To display data in the WebView:
On Mac OS X use WebFrame's loadHTMLString:baseURL:
On iOS use UIWebView's loadHTMLString:baseURL:
What you probably want to do, is implement an NSURLProtocol subclass that will resolve relative URLs by reading them from the zip archive. That way, you only need to initially read the "main" HTML file from the zip into memory, and the others will be read in on demand. To get WebKit to use your custom URL protocols for resolving relative paths, you could instantiate the WebView like this:
[[web_view mainFrame] loadHTMLString:your_main_html baseURL:[[NSURL alloc] initWithString:#"zip:///"]];
Apple has a really good example of combining a custom URL protocol with a WebView here:
https://developer.apple.com/library/mac/#samplecode/SpecialPictureProtocol/Introduction/Intro.html#//apple_ref/doc/uid/DTS10003816

Using images from a static Library

I'm trying to convert a project, which has images, into a static library.
The code that gets the image is as follows:
[UIImage imageNamed:#"foo.png"]
When I include this library into another project, the image doesn't load. However, if I copy the images into the new project, then it does load.
Is there any way I can get this to work where the images are only contained in the library and I don't have to copy them over to my project?
By the way, my Header Search Paths contains the path to where these images are located in the library, if that makes any difference.
Just prepend the name of the bundle that contains your image to the image name:
[UIImage imageNamed:#"Myframework.bundle/MyImage"
This also works in Interface Builder, the preview may be broken but the image will be properly loaded.
If using CocoaPods (which I would recommend) make sure to use the resource_bundles option for your images and Nibs.
You can see a related answer here.
A static library cannot contain bundle resource. So simply linking the .a file will not be enough. But you should be able to cross-reference the static library xcodeproj. Example
Had a similar situation to this and wrote a script to copy the files in to the .app at compile time. A similar fix to the one we use is described in the "Non-code assets for static libraries" section on this web page. This works but can cause some code signing errors. Another option is to create a second .bundle target for the resources described on this web page although for some reason I could not get the bundle to actually build. I am currently looking at writing a script to copy the resources in to a bundle at compile time and compile any .xib files to .nibs, this is also a possible solution you could look at.

Adding Help to a Cocoa App

I want to add a simple one-page HTML page help to my Cocoa app. Can you tell me how to do it? I assume I just have to throw in one lousy .html (and maybe one .css?) file somewhere into my Cocoa project in Xcode?
Creating Apple Help documents that are opened in the Help viewer is straightforward but you must follow the directions in the documentation exactly.
Help files are HTML but you need to place a couple of special tags in the page and name the files in a particular way.
It's all explained in the documentation.
Today I've been facing the same problem. I found no up-to-date howto so here is one of my own. Help is nicely working with this Step by Step to create Apple Help in your Cocoa Xcode Application.
If you only want a single HTML page and not a proper help file, you could add an HTML document and CSS file to your project. These will be copied to your application's Resources directory inside the app bundle when you compile the project. To load the document, you'll need to get its address. This is actually quite easy:
NSString *helpFilePath = [[NSBundle mainBundle] pathForResource:#"YourHelpDocumentHere" ofType:#"html"];
NSURL *helpFileURL = [NSURL fileURLWithPath:helpFilePath];
The resulting URL will be a file URL that a WebView can display inside your application, or you can pass it off to the operating system using NSWorkspace and it will be opened in the user's default web browser.

Trouble using xib files in libraries

I'm having some trouble working with libraries and included xib files. Let me explain my situation first. I've got a project that's running pretty good. Now I need a part of my project as a library for another customer who want's to use some of the functionality in his app. I've created a library with help of that highly recommended article.
My customer should be able to initialize a main view controller like this:
LibraryMainViewController *lmvc = [[LibraryMainViewController alloc] initWithNibName:#"LibraryMainViewController.xib" bundle:foo];
That for sure leads to an error when I try to present that view controller modally. I'm not sure what bundle I have to use here. I tried something like
[NSBundle bundleForClass:[SomeClassInTheLibrary class]];
but that didn't solve the problem.
I would be glad if someone could tell me how to actually use a xib file in that kind of situation.
Thanks
–f
Update
Ok, I see I got it wrong somehow. Just for clarification: What I need is the library, the headers and the additional resources, right? Is there some kind of best practice for creating and shipping "a feature" with all it's parts above mentioned?
Static libraries can't include graphics, sounds, xibs or even headers. Only object code. Even if you added the xibs to Copy Bundle Resources, they won't become a part of the object file. Unfortunately, you can't use dynamic libraries or frameworks on the iPhone. See my answer here for a suggestion of how to create a separate assets bundle. You could also just send your customer the xib files separately, but then they have to replace them by hand if they change in the future.
Try without adding the extension to the XIB file. That's the way i usually do it. I'm also not sure if the XIB must be compiled to a NIB..
NSBundle *bundle = [NSBundle bundleForClass:[SomeClassInTheLibrary class]];
LibraryMainViewController *lmvc = [[LibraryMainViewController alloc] initWithNibName:#"LibraryMainViewController" bundle:bundle];