0
votes

For my IOS hybrid app I create a WKWebView programatically as shown below

- (void)viewDidLoad
    {
    [super viewDidLoad];

    _statBarH = [UIApplication sharedApplication].statusBarFrame.size.height ;
    appH = self.view.frame.size.height ;
    appW = self.view.frame.size.width ;
    webView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:theConfiguration];
    smallScreen = [deviceType hasPrefix:@"iPhone"];
    if (smallScreen && appW > appH) {webView.frame = CGRectMake(0, 0 , appW, appH);}
    else                            {webView.frame = CGRectMake(0, _statBarH, appW, appH - _statBarH);};
    };

I also change the size of the web view when the device rotates as follows:

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
    {
    [super viewWillTransitionToSize:size withTransitionCoordinator:coordinator];
    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> context)
        {
        appH = size.height ;
        appW = size.width  ;
        if (smallScreen && appW > appH) {webView.frame = CGRectMake(0, 0 , appW, appH);}
        else                            {webView.frame = CGRectMake(0, _statBarH, appW, appH - _statBarH);};
        }
     completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
        {
        [webView evaluateJavaScript:@"IOSOrientationChanged()" completionHandler:nil];
        }
     ];
    }

The javascript function IOSOrientationChanged merely redraws my app content in either portrait or landscape format, detecting the new height and width from javascript window.innerWidth and window.innerHeight

This approach has worked fine for me, until Apple removed the home button on iPhone X, 11 ...

What happens on these newer phones (at least in the XCode 11 IOS 13 simulator as I cannot afford one for real) is that when the web view is first created, it respects the upper safe area, but does not respect the lower safe area.

However when I rotate the device in the simulator, the webview respects both the safe areas.

For iPhone 11, the variables appW and appH are 414 and 896 in portrait and 896 and 414 in landscape. The variable _statBarH is 44 in portrait and 0 in landscape.

However inside the web view, window.innerHeight in portrait is initially set to 852 (896-44), but after rotating it is set to 838.

Please can someone tell me what I am doing wrong? Are some internal view constraints not being enforced the first time, but are being enforced after rotation?

1

1 Answers

0
votes

The solution to this, is two fold

  1. Firstly create the WKWebView in viewDidAppear, rather than in viewDidLoad, as it is not until viewDidAppear that you can programatically access the safeAreaInserts values

  2. Secondly, use the values in safeAreaInserts when creating the WKWebView frame, as below

    smallScreen = [deviceType hasPrefix:@"iPhone"];
    topMargin   = [UIApplication sharedApplication].statusBarFrame.size.height ;
    if (@available(iOS 11, *)) topMargin = self.view.safeAreaInsets.top ;
    bottomMargin = 0 ;
    if (@available(iOS 11, *)) bottomMargin = self.view.safeAreaInsets.bottom ;
    
    int top    = (smallScreen && appW > appH)? 0    : topMargin ;
    int height = (smallScreen && appW > appH)? appH : appH - topMargin - bottomMargin ;
    NSLog (@"Top %d, Height %d",top,height);
    
    webView = [[WKWebView alloc]initWithFrame:CGRectMake(0, top , appW, height) configuration:theConfiguration];