在Swift

时间:2017-09-15 13:11:31

标签: ios swift xcode uiapplication

我需要从扩展程序中执行我的主机应用程序。在Objective-C我用过这个:

// 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 arguements
    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];
}

但在Swift我有几个问题:

1)UIApplication不再有sharedApplication方法。相反,它有一个类属性shared。所以我无法执行选择器来获取共享实例。我试图通过编写扩展

来绕过这个
extension UIApplication
{
    class func shared() -> UIApplication
    {
        return UIApplication.shared
    }
}

但我收到错误Function produces expected type 'UIApplication'; did you mean to call it with '()'?。添加这些括号将给我一个无限循环。

2)即使我以某种方式获得实例,我也无法理解如何调用open方法。

let selector = NSSelectorFromString("open(_:options:completionHandler:)")
let method = object?.method(for: selector)
method(destinationURL, [String: Any](), nil)

最后一行给了我Cannot call value of non-function type 'IMP'。当按下苹果文档中的类型时,没有任何反应。我找不到IMP的说明以及如何使用它。

您可以说:“只需在您的分机设置中将Require only app-extension-safe api设置为NO,然后正常呼叫UIApplication.shared”。我会回复说我的构建版本被iTunes Connect拒绝,并带有消息Compliance with export requirements is required或类似的东西(当我的整个操作系统都是英文时,iTunes Connect是俄语版)。

以下是问题:

1)有没有办法在UIApplication.shared中使用ASCII代码获取Swift

BTW我得到类名这样的

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) ?? ""

2)如何调用类型为IMP的方法?

非常感谢。

2 个答案:

答案 0 :(得分:3)

问题是您不应该首先尝试从您的分机访问sharedApplication

根据App Extension Programming Guide

  

某些API不适用于App Extensions

     

由于其在系统中的重点作用,应用扩展程序没有资格参与某些活动。应用扩展程序不能:

     
      
  • 访问sharedApplication对象,因此无法使用该对象上的任何方法
  •   

因此,您可能会破解它,但这会导致您的申请在审核后被拒绝。

但是,要执行您尝试执行的操作(打开网址),您不需要sharedApplication - 您可以使用NSExtensionContext s {{3}执行此操作}

extensionContext.open(myUrl, completionHandler: myCompletionHandler)

答案 1 :(得分:1)

尽管.shared属性在扩展名中不直接可用,但是您可以通过#keyPath来访问它:

let application = UIApplication.value(forKeyPath: #keyPath(UIApplication.shared)) as! UIApplication