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 :)
Related
I'm using dataWithContentsOfFile on a PNG image and the iOS Simulator returns a value that differs from an iOS Device. My device is a 64-bit iPad Air (iOS 8.3) and my simulator is set to iPad Retina iOS 8.3. Here's the code that I'm using:
NSString *sourcePath = [[NSBundle mainBundle] pathForResource:#"image" ofType:#"png"];
NSData *data = [NSData dataWithContentsOfFile:sourcePath];
NSString *hash = [self md5Hash:data]
// Results on device: 2D25F346396FB00BEB27754ED1B56310
// Results on simulator: 55016FD1AB3DA0F882FEA85D5ABCA2ED
I tested my hash function with a string, and it works fine regardless of device. I'm not going to display the results of the dataWithContentsOfFile method, but I can assure you that they're different.
Update: Testing dataWithContentsOfURL works fine, example:
NSURL *fileURL = [NSURL URLWithString:#"https://www.google.com/images/srpr/logo11w.png"];
NSData *data = [NSData dataWithContentsOfURL:fileURL];
NSString *hash = [self md5Hash:data]
// Results on device: 57E396BAEDFE1A034590339082B9ABCE
// Results on simulator: 57E396BAEDFE1A034590339082B9ABCE
I'm going to guess that it's Xcode applying PNGCrush to your image... so it is actually not the same file.
I'm trying to preload the image tags from an html string in order to load them when the device is offline. Basically, I strip the source url from all the <img>tags, clean the url to have a clean filename, then download the image.
__block NSString *imageName = [[NSString alloc]init];
//Get the string after HTTP://
NSArray *nohttp = [actualUrl componentsSeparatedByString:#"//"];
imageName = [nohttp objectAtIndex:1];
//Clean any /.:
imageName = [imageName stringByReplacingOccurrencesOfString:#"/" withString:#""];
imageName = [imageName stringByReplacingOccurrencesOfString:#"." withString:#""];
imageName = [imageName stringByReplacingOccurrencesOfString:#":" withString:#""];
//Add .png at the end as we will be saving it as a PNG
imageName = [NSString stringWithFormat:#"%#.png", imageName];
//change the source url to the new filename of the image so the WebView will load it from the main bundle
html = [html stringByReplacingOccurrencesOfString:actualUrl withString:imageName];
//save the image to the main bundle
NSString *pathString = [NSString stringWithFormat:#"%#/%#",[[NSBundle mainBundle]bundlePath], imageName];
//this just checks if the image already exists
BOOL test = [[NSFileManager defaultManager] fileExistsAtPath:pathString];
if (!test){
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); dispatch_async(queue, ^(void) {
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:actualUrl]];
UIImage* image = [[UIImage alloc] initWithData:imageData];
NSData *imageData2 = UIImagePNGRepresentation(image);
[imageData2 writeToFile:pathString atomically:YES];
});
}
Then after I load the html string into the UIWebView, it works perfectly on the simulator, but on the device the images just aren't loaded. Why?
NSURL *baseUrl = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#",[[NSBundle mainBundle]bundlePath]]];
[self.webView loadHTMLString:self.htmlPage baseURL:baseUrl];
Any suggestions, thoughts? The images download fine on the iOS device/simulator but aren't loaded in the WebView of the real device. It works perfectly for the simulator.
That is correct.
On iOS an App's bundle is read-only. Any attempts to save changes into your bundle will fail on an iOS device.
On Mac OS the bundle is not read-only, but you should still treat it as read-only. Modifying your app's bundle is a bad idea. If the user updates their app from the app store, restores from a backup, etc, then changes you save to the bundle will be lost, even on Mac OS.
The simulator runs under Mac OS, and is built against Mac OS frameworks and the Mac file system.
There are a fair number of differences between the sim and running on a device. This is one.
Another example: The iOS file system is always case-senstive. The simulator, which runs on Mac OS, is not case-sensitive by default. (Mac OS can read from volumes running different file systems. The default file system is not case sensitive, but you can set it up to be case-sensitive.)
The file "Foo.txt" is a different file than the file "foo.txt". They can both exist in the same directory. If your file is called "Foo.txt" and you try to load it with the string "foo.txt" it will fail on an iOS device, but work on Mac OS.
As a result, you should always test your apps on an actual device. Don't assume that if something works correctly on the sim that it's correct for an iOS device. It may not be.
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"];
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];
I'm try to create some images and store it inside the Documents folder. When I run it on the simulator it is fine. However when I run it through the ipad device, the gdb just pauses at a certain point and doesn't give me much information to work with. I used the analyser to check what items to release to check memory leaks. Im running 4.3 SDK.
I'm not sure what the actual issue is. Sometimes looping through 100 images and storing them is ok but then after a while it just pauses. Where can I look further for debug or clues on how to fix this. I have provided some code.
for(int i = 0; i < totalpages; i++)
{
NSString *imagePath = [NSString stringWithFormat:#"%#/%d.jpg",
imageFullPathFolder, i+1];
if(![manager fileExistsAtPath:imagePath])
{
NSString *urlParams = [NSString stringWithFormat:#"SOMEURL",
fileSourceId, i+1];
NSURL *imageUrl = [NSURL URLWithString:urlParams];
UIImage *image = [UIImage imageWithData:[NSData
dataWithContentsOfURL:imageUrl]];
NSData *imageData = UIImageJPEGRepresentation(image, 1.0);
[manager createFileAtPath:imagePath contents:imageData
attributes:nil];
[imageData release];
}
}
You don't need to release the image data returned by UIImageJPEGRepresentation (you don't own it; you're over-releasing it).