Accessing images from nsbundle - ios

I have a framework which is trying to access xib's and images from a bundle. I am able to access the xib fine but unable to load the images in UIImageView. I even check if the file exists and the console output is yes...
Any idea how to load the image?
Code to load xib in the framework viewcontroller file
self = [super initWithNibName:#"ViewController_iPad" bundle:[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:#"MyBundle" ofType:#"bundle"]]];
Code to load images
- (void) loadImage
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"MyBundle.bundle/test" ofType:#"png"];
BOOL present = NO;
present = [[NSFileManager defaultManager] fileExistsAtPath:path];
if (present)
{
NSLog(#"MyBundle.bundle/test exists");
}
else
{
NSLog(#"MyBundle.bundle/test does not exists");
}
self.testImageView.image = [UIImage imageNamed:path];
self.testImageView2.image = [UIImage imageWithContentsOfFile:path];
}
MyTestHarnessApp[11671:c07] MyBundle.bundle/test exists

When you use imageNamed: you must pass just a simple filename and the image must exist in the root of the app's resource bundle.
Your image is not in the root of the resource bundle, it is in a subfolder.
Since you have obtained the image's full path in the path variable, you must use the UIImage imageWithContentsOfFile: method:
self.testImageView.image = [UIImage imageWithContentsOfFile:path];

If +[UIImage imageNamed:] isn't resolving the path correctly, you could always use:
self.testImageView.image = [UIImage imageWithContentsOfFile: path];

You can just use the following:
self.testImageView.image = [UIImage imageNamed:#"MyBundle.bundle/test.png"];
But it seems that if you put the XIB in the bundle too, the interface will be relative to the bundle.
self.testImageView.image = [UIImage imageNamed:#"test.png"]

try going step by step.
First get the path to the bundle within your main bundle:
NSString *myBundlePath=[[NSBundle mainBundle] pathForResource:MyBundle ofType:#"bundle"];
Check to see if there is anything in the bundle. This is more for double checking. Once it is working you can choose to omit this code. But it is always a good idea to double check things.
NSBundle *imageBundle=[NSBundle bundleWithPath: myBundlePath];
NSArray *allImageURLs=[imageBundle URLsForResourcesWithExtension:#"png" subdirectory:nil];
NSLog(#"imageURLS: %#",allImageURLS);
Since you already have the bundle path add the image name to the path. Or you can just pull it from the list of urls that you already have in the above code.
NSString *myImagePath=[myBundlePath stringByAppendingPathComponent:#"test.png"];
NSLog(#"myImagePath=%#",myImagePath);
Then, since you have the full path, load the image
UIImage *testImage = [UIImage imageWithContentsOfFile:backgroundImagePath];
Code taken from shipping app.
Good Luck
Tim

If the images are already in the main bundle just use the image name: test.png or simply test
[UIImage imageNamed:#"test.png"];
[UIImage imageNamed:#"test"];

Related

Retrieving image from asset folder - iOS

I'm writing a class to build a cocoapods and I want to get the image I placed in Assets.xcassets. The problem is always getting nil image. Are there anything I miss?
Here is my podspec file :
Here is the directory stucture :
This is what I try to load the Image:
#import "HaloImage.h"
#implementation HaloImage
- (void)showImage {
NSBundle * bundle = [NSBundle bundleForClass:self];
NSURL * bundleUrl = [bundle URLForResource:#"Assets" withExtension:#"bundle"];
self.image = [UIImage imageNamed:bundleUrl.absoluteString];
}
#end
You can access image from Assets.xcassets by this. Give it a try
UIImage *image = [UIImage imageNamed:#"image name without extension"];
you can use image from asset or main bundle only by name (png file)
self.image = [UIImage imageNamed:#"name_of_image"];
Can you please try below code :
#implementation HaloImage
- (void)showImage {
NSBundle * bundle = [NSBundle bundleForClass:self];
NSURL * bundleUrl = [bundle pathForResource:#"Assets" withExtension:#"bundle"];
self.image = [UIImage imageNamed:bundleUrl.absoluteString];
}
#end

UIImage failed to be loaded for IOS 7.x SPECIFIC

I was trying to load image using method:
[UIImage imageNamed:imageName]
[UIImage imageWithContentsOfFile:imagePath]
In IOS 8.x, the images are loaded. However in IOS 7.x simulators, the above methods always return nil. This situation happened in both simulators and devices.
NSBundle *myBundle = [NSBundle findMyBundle];
[myBundle load];
NSString *imagePath = [NSString stringWithFormat:#"%#/%#", [myBundle bundlePath], imageName];
UIImage *targetImage = [UIImage imageWithContentsOfFile:imagePath];
NSLog(#"FrameworkBundle: %#", myBundle);
// Bundle does exist For IOS 7.x
NSLog(#"Image: %#", targetImage);
// targetImage = nil for IOS 7.x; while it does return image for IOS 8.x
Is there any method need to notice for loading UIImage about IOS 7.x devices / simulators.?
Edit:
Here is what worked out for me:
// I have to specify imageType to be #"png"
// If one compose the path without the fileType ending, it does not load the image properly.
NSString *imagePath = [myBundle pathForResource:imageName ofType:#"png"];
UIImage *myImage = [UIImage imageWithContentsOfFile:imagePath];
I think there was a change when iOS 8 launched in how and where the bundles exist, I just search on Stackoverflow and probably this question (and its answer can help you), you probably have to use a different loading method for locating bundle or resource
ios 8: Bundle path changes
PS:should have been a comment in your answer but dont have enought reputation at the moment :)

Adding unit testing target to existing Xcode project, can't find resource in bundle

I've added a new target of type Cocoa Touch Unit Testing Bundle to an existing iOS project, a test case and some jpg files that I need for testing.
I'm trying to load the image from the test bundle using the following code :
#implementation PhotosViewController_Tests : XCTestCase
-(void)addImage:(NSString *)imageName
{
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSString *imagePath = [bundle pathForResource:imageName ofType:#"jpg"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
...
}
However, bundle returns the main bundle, not the test bundle and imagePath and image are nil.
I can successfully load images from the main bundle (using this code), but I don't understand why bundleForClass returns the mainBundle instead of the unit test one.
I printed the [NSBundle allBundles] and I get the main bundle as well :
"NSBundle </var/mobile/Applications/uuid/Photos Light.app> (loaded)"
I guess it has something to do with adding the unit testing target after the project was created, but I can't figure what else to do to load images from the test bundle.
Try adding an extension to NSBundle in your test target that looks something like this...
#implementation NSBundle (MyAppTests)
+ (NSBundle *)testBundle {
// return the bundle which contains our test code
return [NSBundle bundleWithIdentifier:#"com.mycompany.MyAppTests"];
}
#end
Then when you need to load resources from your test bundle, import that category and then your code looks like...
NSString *imagePath = [[NSBundle testBundle] pathForResource:imageName ofType:#"jpg"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];

Bundle subdirectory access

I'm try to implement ability to change interface in my program, something like themes. I'm decide to use bundles, so in my case they looks like this:
Theme1.bundle
Theme2.bundle
Every bundle have folders:
Theme1.bundle
graphic
pic1.png
pic2.png
sound
sound1.wav
sound2.wav
So I can get path to any required picture from bundle with this code:
path = [NSString stringWithFormat:#"%#.bundle/graphic/%#", selectedBundle, imageName];
When I get pictures from bundle there is no problem, path looks like this (I check it using breakpoints):
Theme1.bundle/graphic/pic1.png and I create UIImage
image = [UIImage imageNamed:path];
Pictures loaded without any problem.
But when I trying to play sound using AVAudioPlayer, I get path to sound by same way and path looks like this:
Theme1.bundle/sound/sound1.wav, but when I try to create NSData
sound = [NSData dataWithContentsOfFile:path];
it is not initialized.
When I try to keep sounds in main bundle and get it with
path = [[NSBundle mainBundle] pathForResource:#"sound1" ofType:#"wav"];
everything is OK, and path looks like this
/var/mobile/Applications/E8313E88-CE05-44B2-A80C-B05331D8596F/Myapp.app/sound1.wav
I cant understand why this works with pictures but not with sound?
Why I cant get sound from bundle?
Only one thing I can suggest - imageNamed: do some work to find right path to file and dataWithContentsOfFile: does not.
In your code instead of
sound = [NSData dataWithContentsOfFile:path];
Use
NSString * path = [NSString stringWithFormat:#"%#.bundle/sounds/%#", selectedBundle, soundName];
NSString *fullPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:path];
sound = [NSData dataWithContentsOfFile:path];
Explanation:
ImageNamed attaches the path of the application to the image name you specify

Selectively loading low-resolution resources in iOS when #2x-version is also present

I had a lot of trouble trying to force the loading of the low-resolution version of some resources on iOS, when the high-res version (#2x) is also present.
The reason I wanted to do this is simple: My app shows a bunch of full-screen images to the user (320x480 on older devices, 640x960 on Retina devices), and the user can upload some of these to TwitPic. I wanted to unify the uploaded images to 320x480, regardless of the device (for consistency, because that size is fine in a web browser).
I found out that no matter what UIImage method I used, when the high-resolution version of a resource file is present it is loaded (even if you pass the full file path): UIImage will out-smart you. But I found a way to out-smart UIImage:
- (UIImage*) lowResImage{
NSString* path = [[NSBundle mainBundle] pathForResource:_fileName
ofType:#"png"
inDirectory:_resourceSubdirectory];
path = [path stringByReplacingOccurrencesOfString:#"##2x" withString:#""];
NSData* imageData = [[NSData alloc] initWithContentsOfFile:path];
UIImage* image = [[UIImage alloc] initWithData:imageData];
[imageData release];
return [image autorelease];
}
The above code works fine on a 4th generation iPod touch.
Anybody came up with a better approach?
Build your path, open data, and then init the image using data as in the example below.
NSString *dataPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:_fileName];
NSData *data = [[NSData alloc] initWithContentsOfFile:dataPath];
UIImage *image3 = [UIImage imageWithData:data];

Resources