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

2

11

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?

Gregg answered 6/8, 2014 at 11:14 Comment(0)
M
6

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.

Martingale answered 13/12, 2015 at 23:0 Comment(0)
V
1

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]

Vasiliu answered 10/5, 2021 at 11:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.