2016-03-21 18 views
4

Kilitlenme raporlarında, NSInternalInconsistencyException numaralı telefonun, JavaScript uyarılarının istenmesi için WKWebView temsilci yöntemlerinden atıldığını görüyorum. "Tamamlama işleyicisi geçti - [MyClass webView: runJavaScriptAlertPanelWithMessage: başlatıldıByFrame: completionHandler:] çağrılmadı".UIAlertController eylemlerinin hiçbir zaman çağrılmasına neden olmayan nedir?

Her UIAlertAction, WKWebView tamamlama işleyicisini işleyicisinden çağırır. Tek açıklama, herhangi bir işlem yapmadan uyarının iptal edilmesidir. UIAlertView, bu gibi durumlar için temsilci yöntemlerine sahipti, ancak UIAlertController, bu denetim düzeyini sunmuyor.

Bunun için bir çözüm geliştiren var mı?

Aynı tekniği kullanmayı düşünmüştüm Apple, CompletionHandlerCallChecker (WebKit'te) içinde, kendi geriçağırımımın başarısız olmasının yakalanmasını yakalamak için kullanır ve WKWebView'ın işleyicisini, sahte özel durumu önlemek için çağırır. Müthiş kludgy görünüyor ve henüz işe yarayacağından emin değilim. Öncelikle bunun olmasını engellemeyi tercih ederim.

Düzenleme: Program denetleyicisinin bu denetleyiciyi işten çıkarmasının bu davranışa yol açtığını biliyorum, ki bu talihsiz bir durumdur, ancak iOS'un denetleyiciyi kullanıcı etkileşimi olmadan reddetmeye karar verdiği koşulu bilmiyorum.

Düzenleme 2:

class CompletionHandlerCallCheckerDefeater: NSObject { 
    private var calledCompletionHandler: Bool = false 
    private var fallbackHandler:() -> Void 

    init(fallbackHandler:() -> Void) { 
    self.fallbackHandler = fallbackHandler 
    } 

    deinit { 
    if (!calledCompletionHandler) { 
     fallbackHandler() 
    } 
    } 

    func didCallCompletionHandler() { 
    calledCompletionHandler = true 
    } 
} 

Temsilci Geri arama durumunda bu gibi kullanmak:

İşte benim kludgy ama çalışma çözüm
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler { 
    UIAlertController *alertController = [UIAlertController alertControllerWithTitle:message message:nil preferredStyle:UIAlertControllerStyleAlert]; 
    [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { 
    completionHandler(); 
    }]]; 
    [self presentViewController:alertController animated:YES completion:nil]; 
} 
+0

İlgili kodu ilgili soruya gönderin. – rmaddy

+0

İptal düğmesi için UIAlertAction var mı? – matt

+0

Bu çözüme bir çözüm buldunuz mu? Değilse, bahsettiğiniz CompletionHandlerCallChecker nasıl yapardınız? Başka bir UI'nin ortaya çıkabileceği ve uyarının işten çıkarılmasına neden olan ve yalnızca bu istisnaya neden olmak için söylenemediği aynı sorunu yaşıyorum. – danchik

cevap

0

: kodunuzu istemeden olanlar için, minimum uygulama gerçekten :

let defeater = CompletionHandlerCallCheckerDefeater(fallbackHandler: completionHandler) 
let alertController = UIAlertController(title: title, message: message, preferredStyle: .Alert) 
alertController.addAction(UIAlertAction(title:"OK", style: .Default) { (action) in 
    completionHandler() 
    defeater.didCallCompletionHandler() 
}) 
presentViewController(alertController, animated: true, completion: nil) 

Geri dönüş için gerekli olan her şeyi atayınHandler, bu b olmak zorunda değil kilit aktarıldı, sadece completionHandler'ı uygun parametrelerle çağırması gerekiyor. Tüm referanslar serbest bırakıldığında, yani, alarm yok edildiğinde "defeater" yok edilir ve eğer didCallCompletionHandler hiç çağrılmadıysa fallbackHandler (tamamlandıHandler) çağırır, böylece istisnadan kaçınır.

İlgili konular