UIImage imageWithContentsOfFile: not working on iOS8 - uiimage

When I test my app on iOS8 beta3 and beta5, I found an bug that about [UIImage imageWithContentsOfFile:].
When image resources are stored in sub-bundle of a main bundle, it will return nil if we initialize UIImage via the following method:
NSString *testBundlePath = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"bundleā€¯];
NSBundle *bundle = [NSBundle bundleWithPath:testBundlePath];
NSString *path = [bundle pathForResource:#"play.png" ofType:nil];
UIImage *image = [UIImage imageWithContentsOfFile:path]; //iOS8 image = nil, iOS7 image != nil
But when the image resources are stored in main bundle, UIImage Initialization can be succeed through the following method:
NSString *path = [[NSBundle mainBundle] pathForResource:#"play.png" ofType:nil];
UIImage *image = [UIImage imageWithContentsOfFile:path]; //iOS8 and iOS7 image != nil
We have found this problem under iOS8 beta3 and it still exists under iOS8 beta 5.
The Demo app directory structure was below:
XXX.app
|----test~ipad.bundle
|----play.png
|----test~iphone.bundle
|----play.png
|----play.png
|----play~iphone.png
|----play~ipad.png
......
Does anyone have the same problem? I think this is a bug on iOS8, Therefore, many apps have used bundle to organize resources, such as images. But now, this bug will make thousands of apps become ugly and hard to use. We really hope that Apple can fix this bug in the next version, otherwise, all of my app will have to developing an new version for this bug!

It's not actually broken, you're just sending it the wrong path.
I'm guessing that you are using the simulator, and have saved a file somewhere in your app and then made note of the full path to that file. However, when you rebuild your app the UUID for the installed app changes, and your saved path is no longer valid (even though the files are still there). You can see your current active path by checking [[NSFileManager defaultManager] currentDirectoryPath] Note that the value changes each time you rebuild and re-deploy your app.
To get to your actual file, you'll need to do something like this:
NSString *image = #"myImage.png";
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
NSString *cache = [paths objectAtIndex:0];
NSString *fullPath = [NSString stringWithFormat:#"%#/%#", cache, image];
UIImage *image = [UIImage imageWithContentsOfFile:fullPath];

pathForResource:ofType: only looks in the Resources folder (and localised folders). If you are placing files into dedicated folders in the bundle then you need to use pathForResource:ofType:inDirectory: and supply the directory name.

Apple has fixed this bug on iOS8.1,Cheers

just use
NSString *fullPath = [bundle pathForResource:name ofType:#"png"];
NSData *data = [NSData dataWithContentsOfFile:fullPath];
UIImage *image = [UIImage imageWithData:data];

Related

Load xib file from framework

I'm creating some code which I've sorted into a framework - purely because I want to reuse this code elsewhere (other osx apps - not iOS).
Inside my Resources folder I created a xib file. One level higher in my root I have the corresponding Controller file.
If my client app is using storyboards - how would I go about loading this view? Note I did manage to access properties on the mentioned controller so I did all the hook up etc as described in Apple docs and elsewhere.
Thanks in advance!
You have to put the resources in a *.bundle, not a framework.
Just create a new target that's a bundle.
Then load the nibs with:
NSString *resourceBundlePath = [[NSBundle mainBundle] pathForResource:#"myBundle" ofType:#"bundle"];
NSBundle *resourceBundle = [NSBundle bundleWithPath:resourceBundlePath];
// load View Controller from that
UIViewController *vc = [[MyViewController alloc] initWithNibName:#"MyViewController" bundle:resourceBundle];
Solution: Here is a sample to load xib to create a view in the framework:
Create a new bundle (eg: MyBundle.bundle) and put your all resources (such as: xib, images, audio files, etc) into the new bundle.
Load xib:
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
NSString* path = [resourcePath
stringByAppendingPathComponent:#"MyBundle.bundle"];
NSBundle *bundle = [NSBundle bundleWithPath:path];
if(bundle)
{
self.view = [[bundle loadNibNamed:#"MyXibNameWithoutSuffix" owner:nil options:nil] lastObject];
} else {
self.view = [[[NSBundle mainBundle]
loadNibNamed:#"MyXibNameWithoutSuffix" owner:nil options:nil] lastObject];
}
Load image:
UIImage* image = [UIImage imageNamed:#"MyBundle.bundle/MyImageName"];
if(nil == image) {
image = [UIImage imageNamed:#"MyImageName"];
}
If you're using cocopods, please make sure the s.resources has been
set in .podspec file.
s.resources = "MyBundle.bundle/**/*.{png,jpeg,jpg,storyboard,xib,xcassets,plist}"

Writing/reading to paths with interleaved double dots fails on iOS 8

This code fails on iOS 8, although it would work on iOS 7
UIImage *imageTest = ...
NSString *file = #"../Documents/Test.png";
NSString *fullpath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent: file];
[UIImagePNGRepresentation(imageTest) writeToFile: fullpath atomically: YES];
UIImage *image = [UIImage imageNamed: file];
On iOS 8 I need to use this instead
NSString *file = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0] stringByAppendingPathComponent:#"Test.png"];
[UIImagePNGRepresentation(imageTest) writeToFile:file atomically:YES];
UIImage *image = [[UIImage alloc] initWithContentsOfFile: file];
...but then I have to refactor my project and a third party library that works with paths relative to the main bundle.
It seems to me that paths like "/PathToMainBundle/MyApp.app/../Documents/something" are either not properly resolved, or not allowed at all by iOS 8
That path should be the same as "/PathToMainBundle/Documents/something"
In iOS8, Resource Directory(App.app), Data Directory(NSCachesDirectory, NSTemporaryDirectory,..) are managed separately as below.
iOS7 Directory Hierarchy
App UUID
Documents
Library
Caches
Preferences
tmp
App.app
iOS8 Directory Hierarchy
Resource Directory UUID
App.app
Data Directory UUID
Documents
Library
Caches
Preferences
tmp
So, you should fix code based on absolute path in iOS8.
UIImage *imageTest = ...
NSString *fullpath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject] stringByAppendingPathComponent:#"Test.png"];
[UIImagePNGRepresentation(imageTest) writeToFile: fullpath atomically: YES];
UIImage *image = [UIImage imageNamed: fullpath];

DiskImageCache: Could not resolve the absolute path of the old directory. failed to find PDF header: `%PDF' not found

In one of my views, I simply want to show a pdf file in a UIWebView.
My code of the header file:
#import <UIKit/UIKit.h>
#interface FCOMViewController : UIViewController
{IBOutlet UIWebView *fcomWebView;}
//flag to denote if this is first time the app is run
#property (nonatomic) BOOL firstRun;
#end
And here the method in the implementation file:
- (void)viewDidLoad {
//Show the procedures PDF
NSString *path = [[NSBundle mainBundle] pathForResource:#"b777normalprocedures" ofType:#"pdf"];
NSURL *url = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[fcomWebView loadRequest:request];
[fcomWebView setScalesPageToFit:YES];
The app starts fine, does not crash or anything. The referencing outlets are set, but it doesn't show the PDF. Console says:
DiskImageCache: Could not resolve the absolute path of the old
directory. failed to find PDF header: `%PDF' not found.
The pdf is in the project directory, I have double checked that it is written correctly.
What can I do here? Any help would be appreciated.
Try this if you are targeting iOS 8.0:
NSString *path = [[NSBundle mainBundle] pathForResource:#"b777normalprocedures" ofType:#"pdf"];
NSURL *targetURL = [NSURL fileURLWithPath:path];
NSData *pdfData = [[NSData alloc] initWithContentsOfURL:targetURL];
[_webView loadData:pdfData MIMEType:#"application/pdf" textEncodingName:#"utf-8" baseURL:nil];
For me the problem was with downloaded pdf files which had extensions that I presume was otherwise recognised by UIWebView (aspx,php etc.). When I renamed the downloaded pdf files so that they had a ".pdf" extension the error did not occur.

Cannot open PDF file using UIWebView in iOS8beta5

I have working project in which i display pdf file in UIWebView
While testing my application in iOS8beta5 with XCode5, it did not work
In log it display failed to find PDF header : '%PDF' not found
I create sample application with below code which also have same problem
CODE :
self.myWebView.delegate = self;
NSString *path = [[NSBundle mainBundle] pathForResource:#"201" ofType:#"pdf"];
NSURL *targetURL = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:targetURL];
[self.myWebView loadRequest:request];
I read release note, Apple wrote that
Quicklook framework may did not display PDF file in some application
but they did not mention any thing about UIWebView,
Reference
NOTE :
This problem was not came in iOS8beta4.
Same problem is also occur in XCode6 + iOS8beta5.
I also check with different PDF files but have same problem.
QUESTION :
1] Is there any one had done fix for the above problem ?
If yes, please provide me some sample code.
I found a workaround for viewing the PDF in WebView
// Create pdf path & url
NSString *path = [[NSBundle mainBundle] pathForResource:#"201" ofType:#"pdf"];
NSURL *targetURL = [NSURL fileURLWithPath:path];
// Load pdf in WebView
NSData *pdfData = [[NSData alloc] initWithContentsOfURL:targetURL];
[self.webView loadData:pdfData MIMEType:#"application/pdf" textEncodingName:#"utf-8" baseURL:nil];

UIImageView's image disappears when changing the image

When changing the image on an UIImageView in code, the image disappears. This only happens on an iPod Touch device, not on the iPhone emulator.
In my bundle I have an image named SomeImage.PNG
NSString *path = [[NSBundle mainBundle] pathForResource:#"SomeImage" ofType:#"png"];
[self.background setImage:[[UIImage alloc] initWithContentsOfFile:path]];
I must reiterate, this works fine on the iPhone simulator but not on an iPod Touch device.
Notice that the image file has an upper-case file extension, but in my code it is declared with lower case. This is the problem. So to fix the problem, change the code to this:
NSString *path = [[NSBundle mainBundle] pathForResource:#"SomeImage" ofType:#"PNG"];
[self.background setImage:[[UIImage alloc] initWithContentsOfFile:path]];
I am asking if there is a 'better' way to do what I am doing, so I don't come across such issues in the future.
Not really. Unfortunately the iOS file system is case sensitive.
Something like this.....?
NSString *filename = #"SomeImage";
NSString *extension = #"png";
UIImage *img = nil;
NSString *path = nil;
path = [[NSBundle mainBundle] pathForResource:filename ofType:[extension lowercaseString]];
img = [[UIImage alloc] initWithContentsOfFile:path];
if (img == nil) {
path = [[NSBundle mainBundle] pathForResource:filename ofType:[extension uppercaseString]];
img = [[UIImage alloc] initWithContentsOfFile:path];
}

Resources