How to get file path in iPhone app - iphone

I have a problem accessing my files in my app.
I am currently using
//Directly from TileMap example from WWDC2010
NSString *tileDirectory = [[[NSBundle mainBundle] resourcePath]
stringByAppendingPathComponent:#"Tiles"];
to access my tiles for my MKOverlay. This gives me this directory
/Users/xxxx/Library/Application Support/iPhone Simulator/4.2/Applications/9D62025C-C53B-472C-8309-xxxx/xxxx.app/Tiles
The x's is only for privacy reasons
I have my tiles in a folder called Tiles in the root of my application which is in Xcode in a group called Tiles which is in directly in the Resources group.
When I run my app, I get a simple error saying that it could not find my tiles at the generated directory (the one quote above) If I replace that piece of code and make it:
NSString *tileDirectory = #"/Users/xxxx/Documents/xxxx/Tiles";
Then my app works fine. This is obviously because it finds my tiles in its direct location on my Mac. This is fine for testing, but I need it to work on my iPhone/iPad.
This problem might be occurring due to:
The generated directory is incorrect.
The tile images aren't getting included in the builded .app file.
Either way, I have no clue of what to do to solve it.
How can I solve this problem?
[EDIT]
I changed that piece of code to:
NSString *tileDirectory = [[NSBundle mainBundle] resourcePath];
Now it works in simulator, because all files are in the apps root folder and I don't ask for it to enter another directory called "Tiles".
This runs with no error on the simulator, but when on my iPhone it gives the original error (just a different file path but also ending with /xxxx.app
How can I ensure a directory in my app file such as xxxx.app/Tiles - TileMap does this.

Since it is your files in your app bundle, I think you can use pathForResource:ofType: to get the full pathname of your file.
Here is an example:
NSString* filePath = [[NSBundle mainBundle] pathForResource:#"your_file_name"
ofType:#"the_file_extension"];

Remember that the "folders/groups" you make in xcode, those which are yellowish are not reflected as real folders in your iPhone app. They are just there to structure your XCode project. You can nest as many yellow group as you want and they still only serve the purpose of organizing code in XCode.
EDIT
Make a folder outside of XCode then drag it over, and select "Create folder references for any added folders" instead of "Create groups for any added folders" in the popup.

If your tiles are not in your bundle, either copied from the bundle or downloaded from the internet you can get the directory like this
NSString *documentdir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *tileDirectory = [documentdir stringByAppendingPathComponent:#"xxxx/Tiles"];
NSLog(#"Tile Directory: %#", tileDirectory);

You need to use the URL for the link, such as this:
NSURL *path = [[NSBundle mainBundle] URLForResource:#"imagename" withExtension:#"jpg"];
It will give you a proper URL ref.

You need to add your tiles into your resource bundle. I mean add all those files to your project make sure to copy all files to project directory option checked.

Related

Localizing HTML files in XCode

I have a localized iOS application in which I wish to include some localized HTML files. I can't work out how to do it.
Currently, my folder structure looks like this:
/myapp
/en.lrproj
/Localizable.strings
/fr.lrproj
/Localizable.strings
/webviews
/view1
/index.html
/pic1.png
/view2
/index.html
/pic2.png
As you can see, I currently have the views organized into their own folders with the associated images.
In XCode, when I selected the Localizable.strings files I can add new localizations. When searching for the solution to this problem I see that other people have done the same for the HTML files, however when I select the HTML files there are no options displayed for localizations, so I'm wondering if the folder structure is the problem.
On the other hand, I don't know how to structure the HTML into language code folders whilst not replicating the graphics that have to be along side.
Clearly I'm not understanding something - what do I need to do to get this working?
Thanks,
Tim
Arrange your index.html right next to the Localized.strings, keep the pics in the web views directory:
/myapp
/en.lrproj
/Localizable.strings
/view1/index.html
/view2/index.html
/fr.lrproj
/Localizable.strings
/view1/index.html
/view2/index.html
/webviews
/view1
/pic1.png
/view2
/index.html
/pic2.png
The build a file path:
NSArray* availableLocalizations = [[NSBundle mainBundle] localizations];
NSArray* userPrefered = [NSBundle preferredLocalizationsFromArray:availableLocalizations forPreferences:[NSLocale preferredLanguages]];
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"index" ofType:#"html" inDirectory:#"view" forLocalization:[userPrefered objectAtIndex:0]];
The picture in the html tree are now similar to
/myapp/en.lrproj/view1/index.html
/myapp/webviews/view1/pic1.png
Inside your index.html make the <img> tags point to ../../../webview/pic1.png
(Not sure about the number of ../'s that you need. You might want to open a terminal, navigate to /myapp/en.lrproj/view1/ and test with ls ../../../webview/pic1.png. )
I assume "webviews/view1/index.html" is English, and "webviews/view2/index.html" is French.
NSString *dir = NSLocalizedString("webviews/view1", #"webdir");
NSString *path = [[NSBundle mainBundle]pathForResource:#"index" ofType:#"html" inDirectory:dir];
in Localizable.strings of French
/* webdir */
"webviews/view1" = "webviews/view2";
I tested above code using below in a ViewController.
[self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:path]]];
"webviews" directory should be a "folder reference" in Xcode, not a group.
(Blue directory icon, not yellow one)
Also, be careful not to add a slash after the directory name, like "webviews/view2/".
I found that this could be a problem when I run that on iOS 5.x(I tested it on 5.0.1 and 5.1.1). But no problem on iOS 6.1.2.

How to access local files within project

I want to add some static files (image, binary, etc...) to my app. I've placed them under a folder named Resources and have added it to my XCode project.
Next, I have those files added to the Copy Bundle Resources in the Build Phases tab in the project settings.
However, I can't seem to refer to them in the right way.
For instance, reading a binary file:
NSInputStream *is = [[NSInputStream alloc] initWithFileAtPath:#"data.bin"];
if(![is hasBytesAvailable]) NSLog(#"wrong");
This always fails & prints wrong
I tried a similar approach with NSData initWithContentsOfFile: but this wouldn't even execute. Another attempt was to use [NSBundle mainBundle] but this also didn't execute fully.
I'm new to iOS please help I can access my local files! Any help would be appreciated.
Thank you,
You need to ensure that you're accessing the file in the right place. Xcode places your resource files in the application's "application bundle" in the Resources directory. There are many ways to dig 'em out.
A common way is to get the pathname of a file in your bundle:
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *myFile = [mainBundle pathForResource: #"data" ofType: #"bin"];
If you have other files in nonstandard places in your bundle, there are variations to pathForResource that let your specify a directory name.
If you want to see the actual location on your hard-drive that the simulator is using so you can inspect it, you can say:
NSLog(#"Main bundle path: %#", mainBundle);
NSLog(#"myFile path: %#", myFile);
Search for the "Bundle Programming Guide" in the Xcode documentation library to get started. :-)
Use NSBundle class for that. For Example:
NSString *path = [[NSBundle mainBundle] pathForResource:#"data" ofType:#"bin"];
NSInputStream *is = [[NSInputStream alloc] initWithFileAtPath:path];
...
Indeed calling [is open] is needed even though you "initialiseWithFileAtPath". I would think the initialisation would automatically open the file for you, but it doesn't.

(IPHONE) Big confusion to read/write the same file from resource folder

i've read several thread for this question but unfortunatly not found the answer to my problem :(
i have a xml file in resource folder, and i need just to re-write the same file;
the app logic is:
display data loaded from file
add new data to the same file
for read a file my code is:
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"myfile" ofType:#"xml"];
NSData *dataXml=[NSData dataWithContentsOfFile:filePath];
for re-write the same file:
NSString *myDataString = #"?xml version=""1.0"" encoding=""UTF-8""?";
NSString *path = [[NSBundle mainBundle] pathForResource:#"myfile" ofType:#"xml"];
BOOL ok=[myDataString writeToFile:path atomically:YES encoding:NSUnicodeStringEncoding error:nil];
For read works fine, but when i try to write, the file is not updated, but it was created another one in another folder, i've tested this in the simulator noting that an app is in a folder like this:
Users/user/Library/Application Support/iPhoneSimulator/Users/Applications/05279766-7B2C-4FC0-BFB0-D87A158A3337/
where there are 3 folder (Documents,tmp,Libary) and the bundle file .app (where there is my xml file)
My question are: is my logic wrong? in wich way are managed app folders in the device??
thanks in advance and sorry for the long thread!
You cannot write files into your application bundle; it's read only (on the device, at least; you may be able to do this in the Simulator).
What you should do is use your ~/Documents folder for the file. If it's not there, first read it from your bundle, then write it out to ~/Documents, and from then on, read it from there.

Problem getting path to .plist using [[NSBundle mainBundle] pathForResource

I'm an Objective C noob, and I don't know enough to explain the following problem.
This code works:
NSString *plistPath = #"/Users/andrewf/MyApp/Resources/Plates.plist";
dicPlates = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
My dictionary object is loaded with values as expected.
This code does not work:
NSString *plistPath = [[NSBundle mainBundle] pathForResource:#"Plates" ofType:#"plist"];
dicPlates = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
plistPath comes back with a value of nil. This is the case irrespective of whether I include inDirectory:#"Resources" in the call or not. All the examples that I have found do not include inDirectory when trying to open a .plist file in the Resources directory.
I have confirmed that the file exists in the correct location and even recreated it to be sure.
This seems like such a simple problem, but I am mystified. Please assist.
I think you're confused as to where pathForResource: is looking.
This works:
NSString *plistPath = #"/Users/andrewf/MyApp/Resources/Plates.plist";
Notice that this path does not point to your application. It points to your project directory. Your plist is supposed to be at #/Users/andrewf/MyApp/build/Release/MyApp.app/Resources/Plist.plist" (for an iPhone app this would be different, more like #"/Users/andrewf/Library/Application Support/iPhone Simulator/User/Applicatons/(unique id)/MyApp.app/Resources/Plates.plist"), and it is inside the Resources folder of your app that pathForResource: is looking.
What this implies is that your resource is not in the "Copy Bundle Resources" phase of your build target. You need to drag it from the Groups and Files area to inside that phase.
I have found the problem!
The .plist file was included in the target correctly.
When the .plist was originally created, I named the file "plates.plist". Immediately after creating the file, I renamed it to "Plates.plist", and this is what I used henceforth.
Even though the file was named "Plates.plist" in my resources folder, in the target section and in the iPhone Simulator location mentioned above, the file was named "plates.plist". Curiously, the contents of the file was still updated correctly.
Now that I have changed the code to refer to "plates.plist", and renamed the file in the Resources folder to the same for good measure, everything works. I can only assume that this is a bug in the iPhone SDK.
Check that the plates.plist file has been added to the target in Xcode.
If the file is not added to the target it will not be inside the build product and NSBundle will not find it.

iPhone - Loading local images from a local xml file

How come I can load a local xml file from the main bundle, but I can't load images?
NSString *path = [[NSBundle mainBundle] resourcePath];
This gets loaded (i know because I can trace it)
/Users/me/Library/Application Support/iPhone Simulator/User/Applications/5B888456-40FF-4C72-A2ED-5D5CFA287777/MyApp.app/test.xml
This image never loads (nor does any image):
/Users/me/Library/Application Support/iPhone Simulator/User/Applications/5B888456-40FF-4C72-A2ED-5D5CFA287777/MyApp.app/background.png
You can use [UIImage imageNamed:#"background.png"].
This will load background.png (which should be located in your Resources folder in Xcode).
You say in a comment that you're composing a NSURL for the path. To do this for a local file system path, such as a file in your bundle, you need to use NSURL fileURLWithPath:.
There are two possibilities here:
1) Either your image file name doesn't proper. That means, file name is case sensitive. So might be issue of capital-small letters.
2) You might have unchecked the target name from your image property. That means your images are not a member of the target of your project which you are compiling. To verify this, right click on any image name inside your XCode poject --> Select Get Info --> Select Targets tab from the File Info dialog --> Verify the status of the checkbox near the target name/s. In case, it is selected/checked then there is a strange issue. But if it's not selected/unchecked, that means the image is not being added to the bundle file which is created after compilation.
The third possibility here is you might not have added the image which you're referring. Re-check your project hierarchy & see all the resources are there or not.
Something like
UIImage *testimg = [UIImage imageNamed:myfilename];
if (nil==testimg) [testimg initWithContentsOfURL:myurl];
I'm away from compiler right now so I can't check whether you might need to download it to an NSData object before making it an image. You should also put the initWithContents... in a try... catch... finally block.
Hi
Use the following code
[UIImage imageWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"background" ofType:#"png"]];
NSURL *imageURL = [NSURL URLWithString:#"bundle://background.png"];