I need to execute my host app from inside an extension. In Objective-C
I've used this:
// Get "UIApplication" class name through ASCII Character codes.
NSString *className = [[NSString alloc] initWithData:[NSData dataWithBytes:(unsigned char []){0x55, 0x49, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E} length:13] encoding:NSASCIIStringEncoding];
if (NSClassFromString(className))
{
// A different way to call [UIApplication sharedApplication]
id object = [NSClassFromString(className) performSelector: @selector(sharedApplication)];
// These lines invoke selector with 3 arguments
SEL selector = @selector(openURL:options:completionHandler:);
id (*method)(id, SEL, id, id, id) = (void *)[object methodForSelector: selector];
method(object, selector, myURL, nil, nil);
// Close extension
[self.extensionContext completeRequestReturningItems: @[] completionHandler: nil];
}
But in Swift
I have a couple of issues:
UIApplication
does not have sharedApplication
method anymore. Instead it has a class property shared
. So I can not perform a selector to get shared instance. I've tried to bypass this by writing an extension
extension UIApplication { class func shared() -> UIApplication { return UIApplication.shared } }
but I get an error Function produces expected type 'UIApplication'; did you mean to call it with '()'?
Function produces expected type 'UIApplication'; did you mean to call it with '()'?
. Adding these braces will give me an infinite loop.
Even if I get the instance somehow, I can't understand how to invoke open
method.
let selector = NSSelectorFromString("open(_:options:completionHandler:)") let method = object?.method(for: selector) method(destinationURL, String: Any, nil)
The last line gives me Cannot call value of non-function type 'IMP'
. When pressing on the type in apple's documents, nothing happens. I can't find a description of IMP
and how to work with it.
You might say: "just set Require only app-extension-safe api
to NO
in your extension's settings and call UIApplication.shared
normally". To which I would reply that my builds get rejected by iTunes Connect
with a message Compliance with export requirements is required
or something along those lines (iTunes Connect is in Russian when my entire OS is in English).
So here are the questions:
UIApplication.shared
using ASCII codes in Swift
?BTW I get class name like so
let codes = [CUnsignedChar](arrayLiteral: 0x55, 0x49, 0x41, 0x70, 0x70, 0x6C, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E)
let className = String(data: Data(bytes: UnsafeRawPointer(codes), count: 13), encoding: String.Encoding.ascii) ?? ""
IMP
?Thank you very much.
The problem is that you shouldn't try to access sharedApplication
from your extension in the first place.
As per App Extension Programming Guide :
Some APIs Are Unavailable to App Extensions
Because of its focused role in the system, an app extension is ineligible to participate in certain activities. An app extension cannot:
- Access a sharedApplication object, and so cannot use any of the methods on that object
So you may hack your way through it, but that will result in your application being rejected upon review.
However, to do what you're trying to do (open a URL) you don't need sharedApplication
- you can simply do that using NSExtensionContext
s open(_:completionHandler:)
extensionContext.open(myUrl, completionHandler: myCompletionHandler)
虽然.shared
属性不能直接在扩展中使用,但您可以通过#keyPath
访问它:
let application = UIApplication.value(forKeyPath: #keyPath(UIApplication.shared)) as! UIApplication
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.