I am writing an iPhone/iPad app where I have zipped files come in which are basically the contents of a website which I can then run upon extracting.
However I would like to put all these files and folders into a single file i.e. an NSBundle
file so that I can display it to the user as if it were a single file and where it can then be deleted or moved but not traversed.
(My app allows traversal of folders throughout the NSDocuments
folder)
I know that you can easily import your own NSBundle
into your project and then read it into a website.
But is it at all possible to write one using an already made directory structure with files and folders that must remain as they are, i.e. the web folder I described earlier?
If not an NSBundle
, can I write(convert) a folder into any other type of package?
If not, do you have any other suggestions for my predicament
This is not a direct answer to your question, but an alternative way of looking at your problem.
Specifically, you've stated that your app allows traversal of folders throughout NSDocumentDirectory. Since your code is what is enumerating files/folders in there, you could simply implement your enumeration code so that it treats folders matching some pattern (e.g. *.bundle) as leaf nodes in the hierarchy; the user need never know there was anything inside there.
Taking that one step further, you could store the .zip files directly in the documents directory, then provide their contents directly to the UIWebView as it requests access to individual URLs.
It's possible to register a subclass of NSURLProtocol
which gets first crack at examining all URL requests. If the subclass says it can handle the particular URL (e.g. for a particular host or path), then an instance of the subclass will be created and asked to provide the content.
At that point, you can use some zip-reading code, for example Objective-Zip to read the requested file from within the zip, and return its contents back from the request.
Use NSURLProtocol +registerClass:
to register the subclass with the system.
In the following example, my protocol handler ignores all requests, except those to my site. For those it returns the same hard-coded string (as a proof-of-concept):
MyURLProtocolRedirector.h:
#import <Foundation/Foundation.h>
@interface MyURLProtocolRedirector : NSURLProtocol
+ (BOOL)canInitWithRequest:(NSURLRequest *)request;
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request;
- (void)startLoading;
- (void)stopLoading;
@end
MyURLProtocolRedirector.m:
#import "MyURLProtocolRedirector.h"
@implementation MyURLProtocolRedirector
+ (BOOL)canInitWithRequest:(NSURLRequest *)request {
if ([request.URL.host compare:@"martinkenny.com"] == 0) {
return YES;
}
return NO;
}
+ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request {
return request;
}
- (void)startLoading {
NSURLResponse *response = [[NSURLResponse alloc] initWithURL:self.request.URL MIMEType:@"text/plain" expectedContentLength:11 textEncodingName:nil];
[self.client URLProtocol:self didLoadData:[[NSData alloc] initWithBytes:"Hello World" length:11]];
[self.client URLProtocol:self didReceiveResponse:response cacheStoragePolicy:NSURLCacheStorageAllowed];
[self.client URLProtocolDidFinishLoading:self];
}
- (void)stopLoading {
}
@end
SomeViewController.m:
// register the new URL protocol handler with the system
[NSURLProtocol registerClass:[MyURLProtocolRedirector class]];
UIWebView *webView = [[UIWebView alloc] initWithFrame:self.view.bounds];
[webView loadRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.seenobjects.org/"]]];
[self.view addSubview:webView];