0

I'm updating an old iOS App at work and I'm replacing the UIWebView API with the new WKWebView API. But I can't quite get it to work (I'am relatively new to iOS development and totally new to objective-c).

What I did up until now is, I added Webkit to my ViewController.h and changed the UIWebView parts in the ViewController.m as follows:

Old ViewController.m

@implementation ViewController

-(BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{   NSLog( @" URL -> %@", request.URL.absoluteString );
    if ( navigationType==UIWebViewNavigationTypeLinkClicked && [request.URL.absoluteString containsString:@"&external"] )
    {   [[UIApplication sharedApplication] openURL:request.URL];
        return NO;
    }
    return YES;
}

-(void)webViewDidFinishLoad:(UIWebView*)wv
{   int hWV=[[wv stringByEvaluatingJavaScriptFromString:@"document.body.offsetHeight"] intValue]+24, wWV=[[wv stringByEvaluatingJavaScriptFromString:@"document.body.offsetWidth" ] intValue]; 
    NSLog( @" height: %d,  width: %d",  hWV, wWV ); // height: 534,  width: 351
    wv.frame = CGRectMake( 12-BrowserDX, -BrowserDY, ww-2*(12-BrowserDX), hWV+BrowserDY );
    UIView *vDetail = wv.superview;   vDetail.frame = CGRectMake( 0, vDetail.frame.origin.y, ww, hWV+0 );
    int y = vDetail.frame.origin.y + vDetail.frame.size.height +24;
    
    HelpInfo *h = arHelpInfo[wv.tag];
    UIScrollView *svDetail = (UIScrollView*)vDetail.superview;

    for( UIView *v in svDetail.subviews )
    {   if ( [v isKindOfClass:[UIButton class]] || [v isKindOfClass:[UIImageView class]]  )
            v.frame = CGRectOffset( v.frame, 0, hWV );
    }
    svDetail.contentSize = CGSizeMake( ww, y+h.arRelated.count*52+0 );
}

-(void)addHelpView :(HelpInfo*)h
{
...
    UIWebView *wvDetail = [[UIWebView alloc] initWithFrame:CGRectMake(12-BrowserDX,-BrowserDY,ww-2*(12-BrowserDX),1)];    wvDetail.tag = [arHelpInfo indexOfObject:h];   [vDetail addSubview:wvDetail];
    wvDetail.scrollView.scrollEnabled = NO;    wvDetail.delegate = self;
    [wvDetail loadHTMLString:h.body baseURL: [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];
...
}
@end

New ViewController.m

@implementation ViewController

-(void)webView:(WKWebView*)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{   NSURLRequest *request = navigationAction.request;
    NSLog( @" URL -> %@", request.URL.absoluteString );
    if ( navigationAction.navigationType==WKNavigationTypeLinkActivated && [request.URL.absoluteString containsString:@"&external"] )
    {
        [[UIApplication sharedApplication] openURL:request.URL];
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

-(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
{
    __block int hWV, wWV;
    [webView evaluateJavaScript:@"document.body.offsetHeight" completionHandler:^(id _Nullable height, NSError * _Nullable error) {
        hWV = [height intValue]+24;
        NSLog( @" height: %d", hWV); // height: 576
    }];
    [webView evaluateJavaScript:@"document.body.offsetWidth" completionHandler:^(id _Nullable width, NSError * _Nullable error) {
        wWV = [width intValue];
        NSLog( @" width: %d", wWV); // width: 964
    }];
    NSLog( @" height: %d,  width: %d",  hWV, wWV ); // height: 0,  width: 0 -> gets called before evaluateJavascript returns the value
    webView.frame = CGRectMake( 12-BrowserDX, -BrowserDY, ww-2*(12-BrowserDX), hWV+BrowserDY );
    UIView *vDetail = webView.superview;   vDetail.frame = CGRectMake( 0, vDetail.frame.origin.y, ww, hWV+0 );
    int y = vDetail.frame.origin.y + vDetail.frame.size.height +24;
    
    HelpInfo *h = arHelpInfo[webView.tag];
    UIScrollView *svDetail = (UIScrollView*)vDetail.superview;

    for( UIView *v in svDetail.subviews )
    {   if ( [v isKindOfClass:[UIButton class]] || [v isKindOfClass:[UIImageView class]]  )
            v.frame = CGRectOffset( v.frame, 0, hWV );
    }
    svDetail.contentSize = CGSizeMake( ww, y+h.arRelated.count*52+0 );
}

-(void)addHelpView :(HelpInfo*)h
{
...
    WKWebView *wvDetail = [[WKWebView alloc] initWithFrame:CGRectMake(12-BrowserDX,-BrowserDY,ww-2*(12-BrowserDX),1)];
    wvDetail.tag = [arHelpInfo indexOfObject:h];   [vDetail addSubview:wvDetail];
    wvDetail.scrollView.scrollEnabled = NO;    wvDetail.navigationDelegate = self;
    [wvDetail loadHTMLString:h.body baseURL: [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]]];
...
}
@end

This seems to work for the most part. The problems I have are in the didFinishNavigation function:

  1. The evaluateJavaScript function is async. How can I wait until the height and width are returned, before I continue with the rest of the didFinishNavigation function?
  2. Somehow evaluateJavaScript returns different values for height and width than stringByEvaluatingJavaScriptFromString (see comments). Why is that? They call the same "document.body.offsetHeight" and "document.body.offsetWidth".
  3. Even when I hardcode the height and width for a specific page eg.
int hWV, wWV;
hWV = 534;
wWV = 351;
NSLog( @" height: %d,  width: %d",  hWV, wWV ); // height: 534,  width: 351
...

The page in the App still looks different (it is zoomed out and the text is very small), even though the rest of the code in didFinishNavigation is the same.

0 Answers0