Подтвердить что ты не робот

Запуск приложения с пользовательской клавиатуры iOS8

Я хочу запустить мое содержащее приложение.

Я попытался использовать схемы URL.

Схема URL запустила приложение из других мест - так что проблемы там нет.

Похоже, что этот объект равен нулю:

   self.extensionContext

поэтому я не могу запустить этот метод:

[self.extensionContext openURL:url completionHandler:nil];

Могу ли я запустить приложение? Утилиты URL-схемы работают на пользовательской клавиатуре?

спасибо!

4b9b3361

Ответ 1

Чтобы ответить на мой СОБСТВЕННЫЙ вопрос:

В пользовательской клавиатуре iOS8 объект extensionContext равен нулю, поэтому я не могу использовать его для запуска содержащего приложения.

Обходной путь, с которым я столкнулся, это:

  • создать схему URL для вашего приложения.
  • добавьте UIWebView в свой входной файл.
  • загрузите схему URL-адресов для вашего приложения, содержащего веб-просмотр.

Я не уверен, что Apple допустит это, но теперь это работает.

Ответ 2

Попробуйте этот код

    UIResponder* responder = self;
    while ((responder = [responder nextResponder]) != nil)
    {
        NSLog(@"responder = %@", responder);
        if([responder respondsToSelector:@selector(openURL:)] == YES)
        {
            [responder performSelector:@selector(openURL:) withObject:[NSURL URLWithString:urlString]];
        }
    }

Ответ 3

Вот рабочее решение (протестированное на iOS 9.2) для расширения клавиатуры. Эта категория добавляет специальный метод для доступа к скрытому объекту sharedApplication, а затем вызывает на нем openURL:. (Конечно, тогда вы должны использовать метод openURL: с вашей схемой приложений.)

// Usage:
// UIInputViewController.openURL(NSURL(string: "your-app-scheme://")!)
extension UIInputViewController {

    func openURL(url: NSURL) -> Bool {
        do {
            let application = try self.sharedApplication()
            return application.performSelector("openURL:", withObject: url) != nil
        }
        catch {
            return false
        }
    }

    func sharedApplication() throws -> UIApplication {
        var responder: UIResponder? = self
        while responder != nil {
            if let application = responder as? UIApplication {
                return application
            }

            responder = responder?.nextResponder()
        }

        throw NSError(domain: "UIInputViewController+sharedApplication.swift", code: 1, userInfo: nil)
    }

}

В последнее время я разработал несколько иной подход:

// Usage:
// UIApplication.🚀sharedApplication().🚀openURL(NSURL(string: "your-app-scheme://")!)

extension UIApplication {

    public static func 🚀sharedApplication() -> UIApplication {
        guard UIApplication.respondsToSelector("sharedApplication") else {
            fatalError("UIApplication.sharedKeyboardApplication(): `UIApplication` does not respond to selector `sharedApplication`.")
        }

        guard let unmanagedSharedApplication = UIApplication.performSelector("sharedApplication") else {
            fatalError("UIApplication.sharedKeyboardApplication(): `UIApplication.sharedApplication()` returned `nil`.")
        }

        guard let sharedApplication = unmanagedSharedApplication.takeUnretainedValue() as? UIApplication else {
            fatalError("UIApplication.sharedKeyboardApplication(): `UIApplication.sharedApplication()` returned not `UIApplication` instance.")
        }

        return sharedApplication
    }

    public func 🚀openURL(url: NSURL) -> Bool {
        return self.performSelector("openURL:", withObject: url) != nil
    }

}

Ответ 4

Apple не разрешает расширениям приложений, отличным от расширений Today, для открытия содержащего приложения.

Из рекомендаций:

Сегодня виджет (и другой тип расширения приложения) может попросить систему открыть свое приложение, вызвав метод openURL: completeHandler: класс NSExtensionContext.

Вы можете проверить здесь

Ответ 5

Я попытался сделать выше решения для последних xcode 8.2 и swift 3.0.

К сожалению. Я не могу заставить его работать. Поэтому я нашел свое собственное решение, и он хорошо работает в swift 3.0, xcode 8.2

   func openURL(_ url: URL) {
        return
   }

   func openApp(_ urlstring:String) {

       var responder: UIResponder? = self as UIResponder
       let selector = #selector(openURL(_:))
       while responder != nil {
           if responder!.responds(to: selector) && responder != self {
              responder!.perform(selector, with: URL(string: urlstring)!)
              return
             }
             responder = responder?.next
          }
   }

  // Usage
  //call the method like below
  //self.openApp(urlString)

  //URL string need to included custom scheme.
  //for example, if you created scheme name = customApp
  //urlString will be "customApp://?[name]=[value]"
  //self.openApp("customApp://?category=1")

Ответ 7

Вот что я нашел, чтобы открыть любой URL, используя то, что было описано выше:

UIWebView * webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
NSString *urlString = @"https://itunes.apple.com/us/app/watuu/id304697459";
NSString * content = [NSString stringWithFormat : @"<head><meta http-equiv='refresh' content='0; URL=%@'></head>", urlString];
[webView loadHTMLString:content baseURL:nil];
[self.view addSubview:webView];
[webView performSelector:@selector(removeFromSuperview) withObject:nil afterDelay:2.0];

Обратите внимание, что в этом случае я запускаю этот вызов из UIInputViewController.

Этот метод также должен работать с использованием схемы URL из содержащего приложения

ПРИМЕЧАНИЕ. Начиная с iOS 8.3 Apple убил этот метод

Ответ 8

В расширении приложения (например, пользовательская клавиатура), которое было бы обработано через UIViewController.extensionContext, но с iOS 8.1.2, поле nil в следующем вызове Swift:

self.extensionContext?.openURL(appURL, completionHandler: nil)
// Does nothing because extensionContext is nil (iOS 8.1)

На самом деле, невозможно использовать Application.sharedApplication.openURL(...) в расширении приложения, как указано в документации Apple.

Итак, начиная с 8.1.2, обходным путем является использование немого UIWebView для перенаправления на содержащее приложение следующим образом:

let webView = UIWebView(frame: CGRectMake(0, 0, 0, 0));
let url = "MyKeyboard://";
let content = "<head><meta http-equiv='refresh' content='0; URL=\(url)'></head>";
webView.loadHTMLString(content, baseURL: nil);
self.view.addSubview(webView);
let delayInSeconds = 2.0
let startTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delayInSeconds * Double(NSEC_PER_SEC)))
dispatch_after(startTime, dispatch_get_main_queue()) { () -> Void in
    webView.removeFromSuperview()
}

Где MyKeyboard:// должно быть определено соответственно как схема URL в содержащем приложении.

Пожалуйста, обратите внимание, что я еще не знаю, одобрено ли это Apple. Переадресация на приложения с пользовательских клавиатур может быть достаточно плохим для пользователей.

Ответ 9

Версия Swift 2.2, сродни ответу DongHyun Jang для Objective-C:

func webLink(urlString: String) {
    let url = NSURL(string: urlString)
    var responder: UIResponder? = self
    while let r = responder {
        if r.respondsToSelector("openURL:") {
            r.performSelector("openURL:", withObject: url)
            break;
        }
        responder = r.nextResponder()
    }  
}

Ответ 10

Я боролся с этим пару дней. Я не мог заставить UIWebView работать внутри пользовательской клавиатуры.

Исправить: поместить его внутри viewDidAppear: анимированный вместо viewDidLoad (в другой записке здесь должен остаться код для пользовательской высоты клавиатуры).

код:

- (void)viewDidAppear:(BOOL)animated {
    UIWebView * webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    NSString * content = @"<a href='your_app_schema://your_params'>anchor</a>";
    [webView loadHTMLString:content baseURL:nil];
    [self.view addSubview:webView];
}

Ответ 11

В соответствии с рекомендациями Apple по расширению, теперь не рекомендуется открывать внешние приложения из расширения.

Для справки см. рекомендации по обзору Apple

Раздел 4.4.1

Они не должны:

  • Включить маркетинг, рекламу или покупки в приложении;
  • Запустить другие приложения, кроме настроек; или