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 havesharedApplication
method anymore. Instead it has a class propertyshared
. So I can not perform a selector to get shared instance. I've tried to bypass this by writing an extensionextension 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 '()'?
. 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:
- Is there a way to get
UIApplication.shared
using ASCII codes inSwift
?
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) ?? ""
- How do I invoke a method that has type
IMP
?
Thank you very much.
Objective-C
code: it is working. I have an issue with replication the same behaviour inSwift
. – Wicklow