Getting bundle file references / paths at app launch - ios

Suppose I have an arbitrary set of files included in the Main App Bundle. I would like to fetch the file URLs for those at launch and store them somewhere. Is this possible using NSFileManager? The documentation is unclear in that regard.
Note: I only need the file URLs, I do not need to access the actual files.

You can get the URL of a file in the main bundle using
NSString *path = [[NSBundle mainBundle] pathForResource:#"SomeFile" ofType:#"jpeg"];
NSURL *url = [NSURL fileURLWithPath:path];
You can write this URL to, for example, a property list file in the Documents directory:
NSString *docsDir = [NSSearchForDirectoriesInDomains(NSDocumentsDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [docsDir stringByAppendingPathComponent:#"Files.plist"];
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:[url absoluteString] forKey:#"SomeFile.jpeg"];
[dict writeToFile:plistPath atomically:YES];
If you don't know the names of the files and you just want to list all the files in the bundle, use
NSArray *files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[[NSBundle mainBundle] bundlePath] error:NULL];
for (NSString *fileName in files) {
NSString *path = [[NSBundle mainBundle] pathForResource:fileName ofType:nil];
NSURL *url = [NSURL fileURLWithPath:path];
// do something with `url`
}

Or in Swift 4:
let url = Bundle.main.url(forResource: "FileName", withExtension: ".xyz")

Yes, you would get their path:
NSString *path = [NSBundle mainBundle] pathForResource:#"file1" ofType:#"png"];
NSURL *fileURL = [NSURL fileURLWithPath:path]
// save it as any other object or in a dictionary:
[myMutableDictionary setObject:fileURL forKey:#"file1.png"];
EDIT: to get the complete list of files, use the NSFileManager, get the path to the bundle itself, then walk each directory getting the files, making URLs, and saving them somewhere. There is oodles of code on SO how to walk a directory to do this. [You should update your question to be more specific on what you want, this was not made clear at all originally]

There's an API on NSBundle (documentation) available on 10.6 or iOS 4 to get an NSURL directly, rather than passing a path to the NSURL constructor:
- (NSURL *)URLForResource:(NSString *)name withExtension:(NSString *)ext;
It also has variants that take a subdirectory and localizationName, the same as its -pathForResource: equivalents.

Related

Show downloaded PDF file with webView ios

I'm making an iPhone app, that will download a PDF file and display it in a webView.
However my script will not show the downloaded PDF. It does download it and save it in Documents, but the webView will not show it.
Here's my script:
NSString *path = [[NSBundle mainBundle] pathForResource:#"3" ofType:#"pdf"];
NSURL *urlen = [NSURL fileURLWithPath:path];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:urlen];
[webView loadRequest:urlRequest];
[webView setScalesPageToFit:YES];
From the official documentation on NSURL official documentation on NSURL.
Sending nil as the argument to fileURLWithPath: produces an exception.
The problem then is actually with [[NSBundle mainBundle] pathForResource:ofType:]. This is returning nil, rather than an actual path to a file.
The problem here is actually that [NSBundle mainBundle] refers to files that are bundle with your app. You need to look in your app's document directory, which is where it stores files it has downloaded.
This method will give you the path to your app's document directory:
NSString* documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
Now, just append the file name to this path:
NSString *pdfPath = [documentsPath stringByAppendingPathComponent:#"3.pdf"];
And for good measure (because crashes are always bad), make sure the file exists as such:
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:pdfPath];
And finish as such:
if (fileExists) {
NSURL *urlen = [NSURL fileURLWithPath:pdfPath];
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:urlen];
[webView loadRequest:urlRequest];
[webView setScalesPageToFit:YES];
} else {
// probably let the user know there's some sort of problem
}

Crash when trying to open downloaded pdf in new view

My app downloads a pdf and then on a button press brings it up in a new view.
I get the error:
-[NSURL initFileURLWithPath:]: nil string parameter'
After some troubleshooting I pinned the problem to somewhere in this code snippet. The path that is being pointed to is in the /Documents folder where the downloaded pdf is placed. Thus the document is not in the main bundle.
NSString *path = [[NSBundle mainBundle] pathForResource:PDFpathwithextension ofType:#"pdf"];
NSURL *url = [NSURL fileURLWithPath:path];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
Here's the download code:
//Start an NSURL connection to download from the remotepath
NSData *pdfData = [[NSData alloc] initWithContentsOfURL:remotepathURL];
//Store the Data locally as PDF File
NSString *resourceDocPath = [[NSString alloc] initWithString:[[[[NSBundle mainBundle] resourcePath] stringByDeletingLastPathComponent] stringByAppendingPathComponent:#"Documents"]];
NSString *filePath = [resourceDocPath stringByAppendingPathComponent:[newdata.ThirdPickerName stringByAppendingFormat:#".pdf"]];
pdfData writeToFile:filePath atomically:YES];
As NSURL is telling you, you've handed it nil instead of a valid path.
nil here means no such resource could be found by that name. Indeed, your question suggests you're well aware of this.
Since you claim your app already downloads a PDF, does it actually write that out to disk? If so, you should know where the resulting file is from doing that. If not, you first need to write the actual download code!

Return NSBundle file path that is created before from an URL

So I got a function:
+ (NSString *)dataFilePath:(BOOL)forSave {
NSURL *url = [NSURL URLWithString:#"https://dl.dropbox.com/u/35612216/sample.xml"];
NSData *data = [NSData dataWithContentsOfURL:url]; // Load XML data from web
// construct path within our documents directory
NSString *applicationDocumentsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *storePath = [applicationDocumentsDir stringByAppendingPathComponent:#"sample.xml"];
// write to file atomically (using temp file)
[data writeToFile:storePath atomically:TRUE];
return [[NSBundle mainBundle] pathForResource:storePath ofType:#"xml"];
//return [[NSBundle mainBundle] pathForResource:#"sample" ofType:#"xml"];
}
And this seems to not work, but when I add a supporting file in my project (sample.xml) and just use this line:
return [[NSBundle mainBundle] pathForResource:#"sample" ofType:#"xml"];
It will work. But I need to get my XML data from the url instead of the supporting file (resource file)
Does anybody know how I can fix this?
The NSBundle method loads the file from the app's bundle, while you've saved the file to the app's Documents directory (which are different locations).
All you need to do is return storePath; which will give you the NSString representation of where the file is located.

Semantic issue undeclared identifier Utilities

I want to make the object of NSUrl in following way but Utilities is undefined.
Please someone tell me If i want to use Utilities class then which framework have to include in our project.
NSString* outputFileName = #"outputFile.mov";
NSString* outputFilePath = [Utilities documentsPath:outputFileName];
NSURL* outputFileUrl = [NSURL fileURLWithPath:outputFilePath];
More easy
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"outputFile" ofType:#"mov"];
Nothing that I know about, but what you are probably looking for is the path to the application documents directory
given by...
NSString *docspath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString* outputFilePath = [docspath stringByAppendingPathComponent:outputFileName];
NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:#"Documents/movie.m4v"]];

-[NSString writeToFile:] does not change the contents of the file

I'm trying to write to a file "index.html" that I have in my resources. I can load the file with no problem, but I can't seem to write to it. Nothing is showing up as an error, it simply doesn't write. The app doesn't abort or anything, but when I re-load the file nothing has changed.
My writing code:
NSBundle *thisBundle = [NSBundle bundleForClass:[self class]];
NSString *path = [thisBundle pathForResource:#"index" ofType:#"html"];
NSString *myString = [[NSString alloc] initWithFormat:#""];
[myString writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:NULL];
My loading code:
[myWebView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:#"index" ofType:#"html"]isDirectory:NO]]];
What am I doing wrong?
The reason that your existing code doesn't overwrite the index.html file is that an application can not overwrite its resources. Apple's iOS Application Programming Guide specifically says:
This is the bundle directory containing the application itself. Do not write anything to this directory. To prevent tampering, the bundle directory is signed at installation time. Writing to this directory changes the signature and prevents your application from launching again.
Instead, write to your documents directory. You can get the path to the documents directory like this:
NSString * docsDir = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
Note that NSHomeDirectory() on iOS simple returns the path to your application's bundle. Once you have the path to the documents directory, you can write to a resource, let's say index.html, as follows:
NSString * path = [docsDir stringByAppendingPathComponent:#"index.html"];
[myString writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];
Note that I changed your error: parameter to nil. This will not actually affect anything, but it is common practice to use nil to indicate NULL Objective-C objects.
Try to move your file to Documents Directory before perform the operation this bunch of code makes the work
.h
#import <Foundation/Foundation.h>
#interface NSFileManager (NSFileManagerAdds)
+ (NSString*) copyResourceFileToDocuments:(NSString*)fileName withExt:(NSString*)fileExt;
#end
.m
#import "NSFileManager + NSFileManagerAdds.h"
#implementation NSFileManager (NSFileManagerAdds)
+ (NSString*) copyResourceFileToDocuments:(NSString*)fileName withExt:(NSString*)fileExt
{
//Look at documents for existing file
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.%#", fileName, fileExt]];
NSFileManager* fileManager = [NSFileManager defaultManager];
if(![fileManager fileExistsAtPath:path])
{
NSError *nError;
[fileManager copyItemAtPath:[[NSBundle mainBundle] pathForResource:fileName ofType:fileExt] toPath:path error:&nError];
}
return path;
}
#end
Finally you should use it in something like that:
[NSFileManager copyResourceFileToDocuments:#"index" withExt:#"html"];

Resources