[Cocoapods]:Resource Bundle not accessbile - ios

Before I was loading me resources with the podspec:
s.resources = ["MyFramework/Resources/**/*.{xib, png, jpeg, jpg}"]
now I tried to accomplish the same with the following:
s.resource_bundles = {'Resources' => ['MyFramework/Resources/**/*.{xib, png, jpeg, jpg}']}
They appear to be copied as I can find them under:
Pods\Development Pods\MyFramework\Resources
But when I try to load them:
UIImage *testImage = [UIImage imageNamed:#"testImage.jpeg"];
the testImage is always nil.
I also tried to find out if there was somehow a bundle accessible so I would need to load an image from a created bundle but:
NSArray *bundles = [[NSBundle mainBundle] pathsForResourcesOfType:#"bundle" inDirectory:nil];
Revealed that no bundle was created through Cocoapods.
How exactly can I access those resources?

The resources is put in a bundle called 'Resources'.
s.resource_bundles = {'Resources' => ['MyFramework/Resources/**/*.{xib, png, jpeg, jpg}']}
you can access the bundle by the following code
NSBundle *bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle]
pathForResource:#"Resources"
ofType:#"bundle"]];
The key in the s.resource_bundles is the bundle name.
Note:
I have some bundles listed by the following code. You may have other issues in your pod settings.
NSArray *bundles = [[NSBundle mainBundle] pathsForResourcesOfType:#"bundle" inDirectory:nil];

To load an image from a bundle use:
UIImage *testImage = [UIImage imageNamed:#"Resources.bundle/testImage.jpeg"];

Related

Dlib image load error, unable to load image

I am developing an iOs application in which I have implemented the Dlib library to get the facial landmark points in an image. Below is the code I have implemented.
dlib::frontal_face_detector detector = dlib::get_frontal_face_detector();
dlib::shape_predictor shapePredictor;
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *landmarkdat = [[NSString alloc] initWithFormat:#"%#/%s",
mainBundle.bundlePath,"shape_predictor_68_face_landmarks.dat"];
dlib::deserialize(landmarkdat.UTF8String) >> shapePredictor;
dlib::array2d<dlib::rgb_pixel> img;
dlib::load_image(img,"001.png" );
But when I run the code in xcode 8.3 I am getting error.dlib::image_load_error: Unable to open file
You need to provide bundle path for that image which worked for me.
NSString *imagePath = [[NSBundle mainBundle] pathForResource:#"test" ofType:#"jpg"];
std::string fileName = [imagePath UTF8String];
dlib::array2d<unsigned char> img;
load_image(img, fileName);
Note : Add images directly to bundle dont add images to asset folder.

Access Resources in pod

I would like to include image assets in a cocoapod library, but I'm having trouble accessing them. I've read these resources for help:
Cocoapods Resources
Cocoapods Resource Bundles
Mokacoding Resource Bundles
David Potter Resource Bundles
However, none point me in the direction of accessing the resources. I've tried the following:
[UIImage imageWithData:[NSData dataWithContentsOfURL:[(NSBundle *)[NSBundle bundleWithIdentifier:#"Assets"] URLForResource:#"my-image#2x" withExtension:#"png"]]]
[UIImage imageWithData:[NSData dataWithContentsOfURL:[(NSBundle *)[NSBundle bundleWithIdentifier:#"Assets"] URLForResource:#"my-image" withExtension:#"png"]]]
[UIImage imageWithData:[NSData dataWithContentsOfURL:[(NSBundle *)[NSBundle bundleWithIdentifier:#"Assets.bundle"] URLForResource:#"my-image" withExtension:#"png"]]]
[UIImage imageWithData:[NSData dataWithContentsOfURL:[(NSBundle *)[NSBundle mainBundle] URLForResource:#"my-image" withExtension:#"png"]]]
[[UIImage imageWithData:[NSData dataWithContentsOfURL:[(NSBundle *)[NSBundle mainBundle] URLForResource:#"my-image#2x" withExtension:#"png"]]]
[UIImage imageNamed:#"my-asset"]
[UIImage imageNamed:#"my-asset#2x.png"]
But none of them work.
I've setup my podspec with these alternatives and neither work with the above:
s.resources = ['Pod/Assets/*.{png, jpg}', 'Pod/Assets/**/*.{png, jpg}']
s.resource_bundles = {
'Assets' => ['Pod/Assets/*.{png, jpg}', 'Pod/Assets/**/*.{png, jpg}']
}
The resources show up under 'Development Pods/My App/Resources' after a pod update, but I cannot access them for the life of me. There aren't any bundles and there isn't anything named 'Assets'.
Any help or guidance would be appreciated.
It depends on the version of Cocoapods that you use. With older versions of cocoapods, you could get away with using [NSBundle mainBundle]:pathForResource:ofType:
NSString *bundlePath = [[NSBundle mainBundle]
pathForResource:#"MyResourceBundle" ofType:#"bundle"];
NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
If you are using newer Cocoapods and using spec.resource_bundles instead of spec.resources in your podspec file, you have to avoid mainBundle and replace it with NSBundle bundleForClass, which "Returns the NSBundle object with which the specified class is associated"
Example:
NSString *bundlePath = [[NSBundle bundleForClass:[MyFrameworkClass class]]
pathForResource:#"MyResourceBundle" ofType:#"bundle"];
NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
This tripped me up too. Maybe I'm misunderstanding +bundleWithIdentifier:, but I don't think you can use it to get to a resource bundle inside of your iOS app bundle. See the "Getting Bundles by Identifier" section of the bundle docs for more details.
What does work is +bundleWithPath:, e.g.:
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:#"MyResourceBundle" ofType:#"bundle"];
NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
I wrapped that inside of a dispatch_once block and call it any time I need to access this bundle.
I'm using the s.resource_bundles syntax in my podspec as well and this works fine with it.

Adding unit testing target to existing Xcode project, can't find resource in bundle

I've added a new target of type Cocoa Touch Unit Testing Bundle to an existing iOS project, a test case and some jpg files that I need for testing.
I'm trying to load the image from the test bundle using the following code :
#implementation PhotosViewController_Tests : XCTestCase
-(void)addImage:(NSString *)imageName
{
NSBundle *bundle = [NSBundle bundleForClass:[self class]];
NSString *imagePath = [bundle pathForResource:imageName ofType:#"jpg"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];
...
}
However, bundle returns the main bundle, not the test bundle and imagePath and image are nil.
I can successfully load images from the main bundle (using this code), but I don't understand why bundleForClass returns the mainBundle instead of the unit test one.
I printed the [NSBundle allBundles] and I get the main bundle as well :
"NSBundle </var/mobile/Applications/uuid/Photos Light.app> (loaded)"
I guess it has something to do with adding the unit testing target after the project was created, but I can't figure what else to do to load images from the test bundle.
Try adding an extension to NSBundle in your test target that looks something like this...
#implementation NSBundle (MyAppTests)
+ (NSBundle *)testBundle {
// return the bundle which contains our test code
return [NSBundle bundleWithIdentifier:#"com.mycompany.MyAppTests"];
}
#end
Then when you need to load resources from your test bundle, import that category and then your code looks like...
NSString *imagePath = [[NSBundle testBundle] pathForResource:imageName ofType:#"jpg"];
UIImage *image = [UIImage imageWithContentsOfFile:imagePath];

Accessing images from nsbundle

I have a framework which is trying to access xib's and images from a bundle. I am able to access the xib fine but unable to load the images in UIImageView. I even check if the file exists and the console output is yes...
Any idea how to load the image?
Code to load xib in the framework viewcontroller file
self = [super initWithNibName:#"ViewController_iPad" bundle:[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:#"MyBundle" ofType:#"bundle"]]];
Code to load images
- (void) loadImage
{
NSString *path = [[NSBundle mainBundle] pathForResource:#"MyBundle.bundle/test" ofType:#"png"];
BOOL present = NO;
present = [[NSFileManager defaultManager] fileExistsAtPath:path];
if (present)
{
NSLog(#"MyBundle.bundle/test exists");
}
else
{
NSLog(#"MyBundle.bundle/test does not exists");
}
self.testImageView.image = [UIImage imageNamed:path];
self.testImageView2.image = [UIImage imageWithContentsOfFile:path];
}
MyTestHarnessApp[11671:c07] MyBundle.bundle/test exists
When you use imageNamed: you must pass just a simple filename and the image must exist in the root of the app's resource bundle.
Your image is not in the root of the resource bundle, it is in a subfolder.
Since you have obtained the image's full path in the path variable, you must use the UIImage imageWithContentsOfFile: method:
self.testImageView.image = [UIImage imageWithContentsOfFile:path];
If +[UIImage imageNamed:] isn't resolving the path correctly, you could always use:
self.testImageView.image = [UIImage imageWithContentsOfFile: path];
You can just use the following:
self.testImageView.image = [UIImage imageNamed:#"MyBundle.bundle/test.png"];
But it seems that if you put the XIB in the bundle too, the interface will be relative to the bundle.
self.testImageView.image = [UIImage imageNamed:#"test.png"]
try going step by step.
First get the path to the bundle within your main bundle:
NSString *myBundlePath=[[NSBundle mainBundle] pathForResource:MyBundle ofType:#"bundle"];
Check to see if there is anything in the bundle. This is more for double checking. Once it is working you can choose to omit this code. But it is always a good idea to double check things.
NSBundle *imageBundle=[NSBundle bundleWithPath: myBundlePath];
NSArray *allImageURLs=[imageBundle URLsForResourcesWithExtension:#"png" subdirectory:nil];
NSLog(#"imageURLS: %#",allImageURLS);
Since you already have the bundle path add the image name to the path. Or you can just pull it from the list of urls that you already have in the above code.
NSString *myImagePath=[myBundlePath stringByAppendingPathComponent:#"test.png"];
NSLog(#"myImagePath=%#",myImagePath);
Then, since you have the full path, load the image
UIImage *testImage = [UIImage imageWithContentsOfFile:backgroundImagePath];
Code taken from shipping app.
Good Luck
Tim
If the images are already in the main bundle just use the image name: test.png or simply test
[UIImage imageNamed:#"test.png"];
[UIImage imageNamed:#"test"];

iPhone : Get the file path which is within subfolder of Resource folder

I am new to iPhone programming. I want to read the content of a text file located in a subfolder of the Resource folder.
The Resource folder structure is the following:
Resource
Folder1---->Data.txt
Folder2---->Data.txt
Folder3---->Folder1---->Data.txt
There are multiple files named "Data.txt", so how can I access the files in each folder? I know how to read the text file, but if the Resource structure is similar to the above structure then how can I get the path?
For example, if I want to access the "Data.txt" file from Folder3, how can I get the file path?
Please suggest.
Your "resource folder" is actually the contents of your main bundle, also know as the application bundle. You use pathForResource:ofType: or pathForResource:ofType:inDirectory: to get the full path for a resource.
Loading the contents of a file as a string is done with the stringWithContentsOfFile:encoding:error: method for an autoreleased string of with initWithContentsOfFile:encoding:error: if you want a retained string.
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"Data"
ofType:#"txt"
inDirectory:#"Folder1"];
if (filePath != nil) {
theContents = [NSString stringWithContentsOfFile:filePath
encoding:NSUTF8StringEncoding
error:NULL];
// Do stuff to theContents
}
This is almost the same answer as given by Shirkrin previously, but with the slight difference that it works on target. This is because initWithContentsOfFile: is deprecated on Mac OS X, and not available at all iPhone OS.
To continue psychotiks answer a full example would look like this:
NSBundle *thisBundle = [NSBundle bundleForClass:[self class]];
NSString *filePath = nil;
if (filePath = [thisBundle pathForResource:#"Data" ofType:#"txt" inDirectory:#"Folder1"]) {
theContents = [[NSString alloc] initWithContentsOfFile:filePath];
// when completed, it is the developer's responsibility to release theContents
}
Notice that you can use -pathForResource:ofType:inDirectory to access ressources in sub directories.
Shirkrin's answer and PeyloW's answer above were both useful, and I managed to use pathForResource:ofType:inDirectory: to access files with the same name in different folders in my app bundle.
I also found an alternative solution here that suited my requirements slightly better, so I thought I'd share it. In particular, see this link.
For example, say I have the following Folder References (blue icons, Groups are yellow):
Then I can access the image files like this:
NSString * filePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"pin_images/1/2.jpg"];
UIImage * image = [UIImage imageWithContentsOfFile:filePath];
As a side note, the pathForResource:ofType:inDirectory: equivalent looks like this:
NSString * filePath = [[NSBundle mainBundle] pathForResource:#"2" ofType:#"jpg" inDirectory:#"pin_images/1/"];
NSBundle* bundle = [NSBundle mainBundle];
NSString* path = [bundle bundlePath];
This gives you the path to your bundle. From there on, you can navigate your folder structure.

Resources