2014-06-30 4 views
15

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

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

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

Похоже, этот объект является нулевым:

self.extensionContext 

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

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

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

спасибо!

+0

У вас есть решение вашей проблемы? –

+0

Отметьте этот ответ [Открыть мое приложение с моего расширения клавиатуры в swift 3.0] (https://stackoverflow.com/a/44718613/2150318) –

+0

https://forums.raywenderlich.com/t/open-my-application- from-my-keyboard-extension-in-swift-3-0/21121/2? u = leangchhean –

ответ

9

Чтобы ответить на мой собственный вопрос:

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

Обходной я придумал это:

  1. создать схему URL-адрес для вашего приложения
  2. добавить UIWebView к вашему inputView
  3. нагрузку, схема URL для содержащего приложения в WebView

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

+0

Яблоки все еще разрешают это сейчас?Я не могу заставить UIWebView работать внутри UIInputViewController. Дайте мне знать, если он по-прежнему работает для вас! –

+0

@ThE _-_ BliZZarD убедитесь, что вы включили AllowFullAccess в настройках клавиатуры. – nurxyz

+0

@ThE _-_ BliZZarD сообщите нам, помогло ли это! – nurxyz

0

Я боролся с этим в течение нескольких дней. Я не мог заставить 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]; 
} 
+0

Я думаю, что это раздражает, что все заканчивается в viewDidAppear, а не viewDidLoad ... Как вы думаете? – nurxyz

1

Это то, что я нашел, чтобы открыть любой 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 из содержащего приложения

ПРИМЕЧАНИЯ: На прошивке 8.3 Apple, убил этот метод

1

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

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

На самом деле, это не возможно либо использовать Application.sharedApplication.openURL(...) в App Extension, как указано в Apple documentation.

Так, по состоянию на 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. Перенаправление приложений с пользовательских клавиатур может быть достаточно плохим для пользователей.

4

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

Из принципов:

A Today widget (and no other app extension type) can ask the system to open its containing app by calling the openURL:completionHandler: method of the NSExtensionContext class.

Вы можете проверить Here

13

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

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]]; 
     } 
    } 
+0

Спасибо за ваш ответ, но для меня открытие схемы URL не работает, открытие Universal Links отлично работает. – Changwei

8

Здесь рабочим раствора (проверен на прошивке 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 
    } 

} 
+0

Я протестировал, это не работает – TomSawyer

+0

Это странно, это работает для меня. Какой подход вы проверили? –

+1

Я тестирую бета-версию 9.3.2. – TomSawyer

1

быстротекущей 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() 
    } 
} 
2

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

К сожалению. Я не могу заставить его работать. Таким образом, я нашел свое собственное решение, и это хорошо работает в быстрой 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") 
+0

Это не скомпилирует, выдает ошибку: «Использование неразрешенного идентификатора« openURL ». Это работает, но устарело: 'let selector: Selector =" openURL: "' – Joey

+0

Спасибо, что это работает! – Jamil

1

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

Для справки см apple review guidelines

Раздел 4.4.1

They must not:

  • Include marketing, advertising, or in-app purchases;
  • Launch other apps besides Settings; or
Смежные вопросы