iOS 8 SDK: modal UIWebView i camera / image picker
Odkryłem, że podczas kompilacji dla iOS 8 (i działa w iOS 8), UIWebView
nie może pokazać aparatu/selektora obrazu, Jeśli UIWebView
znajduje się w kontrolerze widoku prezentowanym modalnie. Działa bez problemu w kontrolerach widoku bezpośrednio "wiszących" z okna rootViewController
lub sterownikach widoku wypychanych z niego.
Aplikacja testowa znajduje się na stronie https://dl.dropboxusercontent.com/u/6214425/TestModalWebCamera.zip ale opiszę to poniżej.
Moja aplikacja testowa (zbudowana z storyboardami, ale prawdziwa aplikacja ich nie używa) ma dwa kontrolery widoku (nieoryginalnie nazwane ViewController
i ViewController2
). ViewController
jest zawarty w {[8] } , który jest kontrolerem widoku głównego. ViewController
zawiera UIWebView
(Działa OK), przycisk "pokazuje" ("naciska") ViewController2
i UIBarButtonItem
, który modalnie prezentuje ViewController2
. ViewController2
ma inny UIWebView
, który działa, gdy jest "popchnięty", ale nie gdy jest "przedstawiony".
Zarówno ViewController
jak i ViewController2
są załadowane:
- (void)viewDidLoad {
[super viewDidLoad];
[self.webView loadHTMLString:@"<input type=\"file\" accept=\"image/*;capture=camera\">" baseURL:nil];
}
Podczas próby użycia modalnego UIWebView
Xcode wyświetla w konsoli i odrzuca modal aplikacji:
Warning: Attempt to present <UIImagePickerController: 0x150ab800> on <ViewController2: 0x14623580> whose view is not in the window hierarchy!
Moja obecna teoria jest taka, że zmiany w UIActionSheet
do UIAlertController
mogły spowodować tę sytuację, ale to dość trudne do udowodnienia. Otworzę Radar z Apple, na wszelki wypadek.
Czy ktoś znalazł tę samą sytuację i jakieś obejście?
7 answers
Znalazłem, że w iOS 8.0.2 iPad nie wydaje się mieć tego błędu, ale iPhone nadal ma.
Jednakże, nadpisanie następujących w kontrolerze widoku zawierającym uiwebview
-(void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
I sprawdzanie, czy istnieje presentedViewController wydaje się działać.
Ale trzeba sprawdzić efekty uboczne
#import "UiWebViewVC.h"
@interface UiWebViewVC ()
@property (weak, nonatomic) IBOutlet UIWebView *uiwebview;
@end
@implementation UiWebViewVC
- (void)viewDidLoad
{
[super viewDidLoad];
NSURL *url = [NSURL URLWithString:@"http://html5demos.com/file-api-simple"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
self.uiwebview.scalesPageToFit = YES;
[self.uiwebview loadRequest:request];
}
-(void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
{
if ( self.presentedViewController)
{
[super dismissViewControllerAnimated:flag completion:completion];
}
}
@end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-07 16:56:53
Mam ten sam problem na iOS 9. Spróbuj dodać ivar '_flag' , a następnie nadpisać te metody w kontrolerze widoku za pomocą UIWebView
#pragma mark - Avoiding iOS bug
- (UIViewController *)presentingViewController {
// Avoiding iOS bug. UIWebView with file input doesn't work in modal view controller
if (_flagged) {
return nil;
} else {
return [super presentingViewController];
}
}
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion {
// Avoiding iOS bug. UIWebView with file input doesn't work in modal view controller
if ([viewControllerToPresent isKindOfClass:[UIDocumentMenuViewController class]]
||[viewControllerToPresent isKindOfClass:[UIImagePickerController class]]) {
_flagged = YES;
}
[super presentViewController:viewControllerToPresent animated:flag completion:completion];
}
- (void)trueDismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion {
// Avoiding iOS bug. UIWebView with file input doesn't work in modal view controller
_flagged = NO;
[self dismissViewControllerAnimated:flag completion:completion];
}
This works for me fine
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-30 15:01:12
Miałem podobny problem i odkryłem, że elementy UIWebView w IOS nie obsługują elementu html:
Nie jestem pewien, dlaczego Apple zdecydowało się nie wspierać tego ważnego elementu html, ale jestem pewien, że mają swoje powody. (Nawet jeśli ten element działa doskonale na Safari na IOS.)
W wielu przypadkach, gdy użytkownik kliknie ten rodzaj przycisku w UIWebView, pozwoli mu zrobić / wybrać zdjęcie. Jednak UIWebView w systemie IOS nie ma możliwości załącz takie pliki do danych postu po przesłaniu formularza.
Rozwiązanie: aby wykonać to samo zadanie, możesz utworzyć podobny formularz w Interfacebuilderze za pomocą przycisku, który uruchamia UIImagePickerController. Następnie tworzysz żądanie HTTP POST ze wszystkimi danymi formularza i obrazem. Nie jest to takie trudne, jak się wydaje, sprawdź poniższy link, aby uzyskać przykładowy kod, który wykonuje zadanie: iOS Prześlij obraz i tekst za pomocą HTTP POST
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:50
Dla mnie zwykle mam własny kontroler UINavigationController, aby wiele widoków mogło dzielić tę samą logikę. Tak więc dla mojego obejścia (w języku Swift) oto, co umieściłem w moim niestandardowym kontrolerze nawigacyjnym.
import UIKit
class NavigationController: UINavigationController {
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func dismissViewControllerAnimated(flag: Bool, completion: (() -> Void)?) {
if let vc = self.presentedViewController {
// don't bother dismissing if the view controller being presented is a doc/image picker
if !vc.isKindOfClass(UIDocumentMenuViewController) || !vc.isKindOfClass(UIImagePickerController) {
super.dismissViewControllerAnimated(flag, completion:completion)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// make sure that the navigation controller can't be dismissed
self.view.window?.rootViewController = self
}
}
Oznacza to, że możesz mieć mnóstwo kontrolerów widoku z webviews i wszystkie będą działać z elementem przesyłania plików.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-19 09:37:56
Dobra, oto obejście, którego użyłem. To 2-minutowa zmiana, dość hacky, ale działa zgodnie z oczekiwaniami i unika błędu, który wszyscy mamy. Zasadniczo, zamiast prezentować kontroler widoku potomnego modalnie, ustawiłem go na rootviewcontroller okna i zachowuję odniesienie do kontrolera nadrzędnego. Więc gdzie miałem to (w kontrolerze widoku nadrzędnego):
presentViewController(newController, animated: true, completion: nil)
I now have this
view.window?.rootViewController = newController
W obu przypadkach kontrolerem nadrzędnym jest delegat newController
, czyli jak I zachowaj referencje.
newController.delegate = self
Wreszcie, gdzie w moim delegate callback do zamknięcia modalu, gdzie miałem to:
dismissViewControllerAnimated(true, completion: nil)
Mam teraz to:
viewController.view.window?.rootViewController = self
Tak więc otrzymujemy ten sam efekt kontrolera widoku, który całkowicie przejmuje ekran, a następnie oddaje jego kontrolę po zakończeniu. W tym przypadku jednak nie jest animowana. Mam wrażenie, że animowanie przejścia kontrolera nie byłoby zbyt trudne w przypadku niektórych wbudowanych animacji widoku.
Mam nadzieję, że już używanie wzorca delegowania do zarządzania komunikacją z kontrolerem modalnym, zgodnie z zaleceniem Apple, ale jeśli nie jesteś, jestem pewien, że możesz użyć dowolnej liczby metod, które przechowują odniesienie i oddzwaniają.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-30 17:10:49
Moim rozwiązaniem jest stworzenie niestandardowego kontrolera widoku z niestandardową prezentacją modalną w oparciu o hierarchię kontrolerów child-parent. Animacja będzie taka sama, więc użytkownik nie zauważy różnicy.
Moje propozycje animacji:
animateWithDuration:(animated ? 0.6 : 0.0)
delay:0.0
usingSpringWithDamping:1.f
initialSpringVelocity:0.6f
options:UIViewAnimationOptionCurveEaseOut
Będzie to wyglądać dokładnie jak domyślna animacja prezentacji modalnej w iOS7/8.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-24 09:29:40
Co zrobiłem co za każdym razem, gdy kontroler widoku jest zmiana, przekonwertować widok docelowy w root.
Z kontrolera pierwszego widoku:
let web = self.storyboard?.instantiateViewController(withIdentifier:"web") as! UINavigationController
view.window?.rootViewController = web
Tak przekazuję korzeń drugiemu, a po powrocie do pierwszego zrobiłem to.
From web view controller:
let first = self.storyboard?.instantiateViewController(withIdentifier: "reveal") as! SWRevealViewController
present(first, animated: true, completion: nil)
I wszystko jest w porządku, mogę pokazać modal dla wybierz zdjęcie z biblioteki, zrobić zdjęcie i wszystko inne.
Nie wiem czy to dobra praktyka ale działa dobrze w emulatorze i urządzenie. Mam nadzieję, że to pomoże.Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-18 21:04:58