Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to retrieve a file/resource in a iOS framework bundle from a main program?

I use methods about creating a universal binary framework for iOS development to distribute a library. I would also like to add files in the framework, and load them in the main program (an SSL certificate actually). This is related to this StackOverflow question, the main difference is that I want to include something else than a XIB.

If we read the thread related to the linked post, it seems it is not possible. However, the following blog article was mentioned; we can read:

"Static frameworks are not a full replacement for standard frameworks -- standard methods for accessing the framework resources, such as +[NSBundle bundleForClass:] will not return the expected bundle. The bundle path is determined by querying dyld for the library path corresponding to the symbol address -- In the case of static linking, this will return the path to the binary into which the static library was linked. Additionally, NSBundle/CFBundle will examine the previous stack from for the return address, and use that return address to determine the calling code's dyld binary path. Given these restrictions, some work-arounds are possible, such as using -[NSBundle privateFrameworkPath] to locate the path to the embedded framework."

I am a beginner in iOS development, and I struggle in using such a mechanism. Using the privateFrameworksPath returns a path indeed, but I do not know what to do next to locate the file I want to load.

It is something like that:

NSBundle * bundle = [NSBundle bundleForClass:[self class]];
NSString * path = [bundle privateFrameworksPath]; // Works, return something like .../Frameworks
NSString * file = [path stringByAppendingPathComponent:@"MyFramework.framework/Versions/A/my-cert.der"]; 
NSData * trustedCertData = [NSData dataWithContentsOfFile:file]; // Returns nil

Any ideas?

like image 847
Vincent Hiribarren Avatar asked Aug 06 '14 11:08

Vincent Hiribarren


People also ask

How do I load a bundle in Swift?

It's called contentsOfFile , and here it is in action: if let filepath = Bundle. main. path(forResource: "example", ofType: "txt") { do { let contents = try String(contentsOfFile: filepath) print(contents) } catch { // contents could not be loaded } } else { // example.

What is IOS framework?

A framework is a bundle (a structured directory) that contains a dynamic shared library along with associated resources, such as nib files, image files, and header files. When you develop an application, your project links to one or more frameworks.

How do I open framework in Xcode?

One is to right click your "src" folder in Xcode, and select "New File..", the other is to go to the menu and select File > New > File... In the dialog that pops up, navigate to OS X > Source and then select C++ file.


2 Answers

Access to Framework bundle

The key point is to pass any metatype[About] of class which belongs to framework

//Objective-C
NSBundle *someBundle = [NSBundle bundleForClass:[SomeFrameworkClass class]];

//Swift

//via public framework's class
let frameworkBundle = Bundle(for: SomeFrameworkClass.self)
//or via Bundle Identifier(PRODUCT_BUNDLE_IDENTIFIER)
let frameworkBundle = Bundle(identifier: "com.someid") 
//or if it is called from the framework
let frameworkBundle = Bundle(for: type(of: self))
let frameworkBundle = Bundle(for: Self.self)

//working with bundle as usual

[Vocabulary]

like image 118
yoAlex5 Avatar answered Sep 17 '22 20:09

yoAlex5


The following code worked for me in a similar case

NSBundle * bundle = [NSBundle bundleForClass:[self class]];
NSString * file = [bundle pathForResource:@"my-cert" ofType:@"der"];; 
NSData * trustedCertData = [NSData dataWithContentsOfFile:[file stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];

The NSBundle bundleForClass: method returns a bundle for the framework of the current class. So if you call this method from within MyFramework you won't need to append the path with MyFramework.framework again, but you would have caught that debugging if that was your problem.

Also the dash in my-cert.der may need to be replaced with the % equivelent. hence the stringByReplacingPercentEscapesUsingEncoding: call.

like image 33
izzy Avatar answered Sep 18 '22 20:09

izzy