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?

Author: computingfreak, 2014-09-20

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
 45
Author: seeinvisible,
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

 7
Author: Artyom Devyatov,
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

 1
Author: Takide,
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.

 1
Author: Jeremy JC Paul,
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ą.

 0
Author: bloudermilk,
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.

 0
Author: kelin,
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.
 0
Author: Jason Sa,
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