loading NSBundle files on iOS
untested.
You can distribute all the content in a zip file, unzip using SSZipArchive.
NSBundle* bundle = [NSBundle bundleWithPath:absolutePathToNibFile].
UIViewController* vc = [[[MyViewController alloc] initWithNibName:@"mycustomnib" bundle:bundle] autorelease];
Using NSBundle to load my resources
[NSBundle bundleWithPath:[NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] bundlePath], pathToYourBundleWithinTheDotAppDirectory];
Let me know how you get on.
How to use NSBundle to load NIBs from downloaded bundle and fall back to main bundle
Here are the steps:
1) Create NIBs in the main bundle in the normal fashion. I recommend using a file group that points to a folder, to keep all the assets together that will be be used for the downloaded bundle. Let’s call it NIB_Resources.
To create a NIB under a folder in the Project Navigator:
- Right-click on a file group.
- Choose New File…
- Choose User Interface, and select View.
2) Add a target for the asset bundle.
- Click on the + in the targets panel.
- Select the Bundle template in the Framework and Library category, under OS X. It is in that category because it is a type of asset library.
- For the product name, enter the name that you want to call the asset library. Leave everything else as is, and select the project that you want to add the product to.
- In the Build Settings for the new product, change the Base SDK from Latest OS X to Latest iOS.
3) Add the assets to the asset bundle.
- Select the Copy Bundle Resources Build Phase for the new product.
- Drag and drop the assets that you want to include in the bundle. The cursor will show a + icon if it is possible to add the asset.
4) Build the asset bundle.
- Select the Scheme for the newly created target.
- Select iOS Device as the build target.
- Build.
- If this was done correctly, the product for the new bundle should have changed from red to black, under the Products folder of the Project Navigator.
5) Zip the asset bundle
- Right-click the newly built product in the Products folder, and select Show in Finder.
- Copy the bundle to a location, such as some folder in a directory dedicated to this project.
- Right-click on the directory that contains the bundle and possibly other NIB files, images, etc.
- Select Compress.
6) Upload the asset bundle to a location that you have download access to.
7) Download the zipped asset bundle:
The code below is tucked away in convenience functions, in a convenience file that handles a lot of low-level File System operations. The FS prefix refers to File System.
FSDownloadTempFileWithURLString
can be called from a secondary thread, before returning to the main thread.
I use the NSData
synchronous method, initWithContentsOfURL:
, because the call is likely to be made from a secondary thread. The basic strategy is to download the zip file to a temporary location (the Caches directory is usually a good candidate for this purpose), before doing any necessary preparations and unzipping the file to the Documents directory. The approach of defining inline static operations in a header file was adopted from Apple.
//Documents directory
#define FSDocumentsDirectory [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
//Caches directory
#define FSCachesDirectory [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) firstObject]
/**
* Get the path to a file under the caches directory. The given filename can have
* multiple file separators.
*/
inline static NSString* FSCachesPath(NSString *filename)
{
return [FSCachesDirectory stringByAppendingPathComponent:filename];
}
/**
* Download a file from a specified URL, and copy to the caches directory, to the same filename as the URL's filename.
*
* Returns the result.
*/
inline static BOOL FSDownloadTempFileWithURLString(NSString *urlString)
{
NSData *data = getDataFromURL(urlString);
if (!data) {
//Error already logged
return FALSE;
}
NSString *path = FSCachesDirectory;
NSString *filename = [urlString lastPathComponent];
path = [path stringByAppendingPathComponent:filename];
NSError *error = nil;
if (![data writeToFile:path options:NSDataWritingAtomic error:&error]) {
NSLog(@"Error occurred while trying to write the file to: %@\n", path);
NSLog(@"%@", error);
return FALSE;
}
return TRUE;
}
/**
* Get the data from a specified URL.
*/
inline static NSData* getDataFromURL(NSString *urlString)
{
NSString *escapedUrlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:escapedUrlString];
NSData *data = [[NSData alloc] initWithContentsOfURL:url];
if (!data) {
debugLog(@"Could not download file: %@", escapedUrlString);
return nil;
}
return data;
}
8) Unzip the download to the Documents directory, using SSZipArchive
or something similar:
NSString *cachesPath = FSCachesPath(URL_RESOURCE_FILENAME);
if (![SSZipArchive unzipFileAtPath:cachesPath toDestination:FSDocumentsDirectory delegate:nil]) {
return;
}
9) Finally, try to load a view from a NIB file in the bundle in the Documents directory, and fall back to the main bundle.
The FSResourceNib
operation below can be called from a view controller that is trying to load a view from a Nib, like so:
UIView *view = FSResourceNib(ResourcesBundle, nibName, self);
/**
* Get a NIB from the documents directory, otherwise fall back to the bundle.
*
* Returns nil, if an error occurs.
*/
inline static UIView* FSResourceNib(NSString *bundleFilename, NSString *nibName, id owner)
{
UIView *resourceView = nil;
//If bundld doesn't exist in the documents path, then use the main bundle
NSString *resourcePath = FSDocumentsPath(bundleFilename);
if ([[NSFileManager defaultManager] fileExistsAtPath:resourcePath]) {
NSBundle *resourceBundle = [NSBundle bundleWithPath:resourcePath];
@try {
//Try to load the NIB from the given bundle
resourceView = [[resourceBundle loadNibNamed:nibName owner:owner options:nil] lastObject];
}
@catch (NSException *exception) {
//do nothing - will try main bundle
}
}
//If loading from the given bundle failed, try loading from the main bundle
if (!resourceView) {
NSBundle *resourceBundle = [NSBundle mainBundle];
@try {
resourceView = [[resourceBundle loadNibNamed:nibName owner:owner options:nil] lastObject];
}
@catch (NSException *exception) {
//do nothing - will return nil, indicating an error occurred
}
}
return resourceView;
}
Loading External Bundle Files allowed?
You should ask Apple to be sure, but probably no.
The bundle can contain image / data resources but also code, and there is a restriction guideline against running code that wasn't in the app when it was reviewed. If you're just loading image / data resources then you'll probably be fine. Code resources, you might get through review but would likely be pulled if found out.
Loading NSBundle Plist file to Document Directory
no. the plist is not user data and shouldn't be backuped but the documents folder is
move it to library/Caches/ (and be prepared to lose it)
OR
create a custom dir in library .. (e.g. app support)
src: https://developer.apple.com/icloud/documentation/data-storage/index.html
src2: https://developer.apple.com/library/ios/documentation/FileManagement/Conceptual/FileSystemProgrammingGuide/ManagingFIlesandDirectories/ManagingFIlesandDirectories.html
iOS mainBundle not loading resources
I don't know exactly what is the issue here. But it is the most common problem. In two situations such issue occurs. 1. file path is wrong. 2.File is not included in bundle.
After checking above file path shown by you I don't think it is the issue of file path. But you can check your file is included in target or not. Just right click on your file and select get info. Where check in target your current target is selected or not.
accessing a file using [NSBundle mainBundle] pathForResource: ofType:inDirectory:
well i found out the mistake i was committing i was adding a group to the project instead of adding real directory for more instructions
Related Topics
Tap Gesture on Animating Uiview Not Working
Is There Any Facebook Plugin for Phonegap 2.7.0
Spritekit: Why Does It Wait One Round for the Score to Update? (Swift)
Different Cornerradius for Each Corner Swift 3 - iOS
-[Not a Type Retain]: Message Sent to Deallocated Instance
Adding Quartzcore to Xcode 4 for iOS
How to Get File Name in Uiimagepickercontroller with Asset Library
How to Edit Uialertaction Title Font Size and Style
iOS 7 - Restrict Landscape Orientation Only in One View Controller
Is This Code Drawing at the Point or Pixel Level? How to Draw Retina Pixels
How to Read Plist Without Using Nsdictionary in Swift
How to Display Remote Document Using Qlpreviewcontroller in Swift
When to Use Static Constant and Variable in Swift
Codesign Returned Unknown Error -1=Ffffffffffffffff
Find Uialertview Without Having Reference to It iOS 7
Simulate Universal Gravitation for Two Sprite Kit Nodes