Question

In my project I put a UIWebView under UINavigationBar and the setup the UIWebView to occupy the rest of the screen other than UINavigationBar. But I found some gaps between the two controls. There is also a gap between the left edge and the UIWebView left side. Any idea what I am missing?

enter image description here

Here is my updated code: in UIView+AutoLayout: (this category will set all the view's translatesAutoresizingMaskIntoConstraints property to NO)

#import "UIView+AutoLayout.h"

@implementation UIView (AutoLayout)
+ (id)autolayoutView
{
    UIView *view = [self new];
    view.translatesAutoresizingMaskIntoConstraints = NO;
    return view;
}
@end

in ViewController:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.navigationBar = [UINavigationBar autolayoutView];
    UINavigationItem *backToListItem = [[UINavigationItem alloc] init];
    UIBarButtonItem *listItem = [[UIBarButtonItem alloc] initWithTitle:@"List"   style:UIBarButtonItemStylePlain target:self action:@selector(listButtonPressed:)];
    backToListItem.leftBarButtonItem = listItem;

    self.navigationBar.items = [NSArray arrayWithObject:backToListItem];

    [self.view addSubview:self.navigationBar];

    self.webView = [TNSWebView autolayoutView];

    [self.view addSubview:self.webView];

    NSDictionary *views = NSDictionaryOfVariableBindings(_navigationBar, _webView);
    [self.view addConstraints:[NSLayoutConstraint
                           constraintsWithVisualFormat:@"|[_navigationBar]|"
                           options:0 metrics:nil
                           views:views]];
    [self.view addConstraints:[NSLayoutConstraint
                                 constraintsWithVisualFormat:@"V:|[_navigationBar]->=0-[_webView]|"
                                 options:0 metrics:nil
                                 views:views]];
    [self.view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[_webView]|" options:0 metrics:nil views:views]];
    [self.webView setupVideoPlayer:self.videoId];
}

Using the po [[UIWindow keyWindow] recursiveDescription] command in lldb I got this result

    | <UIView: 0x1d23f880; frame = (0 20; 768 1004); autoresize = RM+BM; layer = <CALayer: 0x1d23cba0>>
   |    | <UINavigationBar: 0x1d00a4b0; frame = (0 0; 768 44); gestureRecognizers = <NSArray: 0x1d015ff0>; layer = <CALayer: 0x1d0c8f60>>
   |    |    | <_UINavigationBarBackground: 0x1d010250; frame = (0 0; 768 44); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1d011140>>
   |    |    |    | <UIImageView: 0x1d0d26b0; frame = (0 44; 768 3); opaque = NO; autoresize = W+TM; userInteractionEnabled = NO; layer = <CALayer: 0x1d23fbd0>>
   |    |    | <UINavigationItemView: 0x1d016740; frame = (384 22; 0 0); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1d016840>>
   |    |    | <UINavigationButton: 0x1d013ff0; frame = (7 7; 48 30); opaque = NO; layer = <CALayer: 0x1d014170>>
   |    |    |    | <UIImageView: 0x1c5d9ca0; frame = (0 0; 48 30); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1c58b330>>
   |    |    |    | <UIButtonLabel: 0x1d0144c0; frame = (13 7; 22 15); text = 'List'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1d014560>>
   |    | <TNSWebView: 0x1d016bc0; baseClass = UIWebView; frame = (0 44; 768 960); layer = <CALayer: 0x1d016ca0>>
   |    |    | <_UIWebViewScrollView: 0x1d012390; frame = (0 0; 768 960); clipsToBounds = YES; autoresize = H; gestureRecognizers = <NSArray: 0x1d011380>; layer = <CALayer: 0x1d0125e0>; contentOffset: {0, 0}>
   |    |    |    | <UIImageView: 0x1d00f2a0; frame = (0 0; 10 10); transform = [-1, 0, -0, -1, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1d00f300>>
   |    |    |    | <UIImageView: 0x1d00f210; frame = (0 0; 10 10); transform = [0, 1, -1, 0, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1d00f270>>
   |    |    |    | <UIImageView: 0x1d00f180; frame = (0 0; 10 10); transform = [0, -1, 1, 0, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1d00f1e0>>
   |    |    |    | <UIImageView: 0x1d00efb0; frame = (0 0; 10 10); alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1d00f150>>
   |    |    |    | <UIImageView: 0x1d00ef20; frame = (-4.5 4.5; 10 1); transform = [0, 1, -1, 0, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1d00ef80>>
   |    |    |    | <UIImageView: 0x1d00ee90; frame = (-4.5 4.5; 10 1); transform = [0, -1, 1, 0, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1d00eef0>>
   |    |    |    | <UIImageView: 0x1d00ee00; frame = (0 0; 1 10); transform = [-1, 0, -0, -1, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1d00ee60>>
   |    |    |    | <UIImageView: 0x1d00ec30; frame = (0 0; 1 10); alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1d00edd0>>
   |    |    |    | <UIImageView: 0x1d00eba0; frame = (0 954; 768 6); alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1d00ec00>>
   |    |    |    | <UIImageView: 0x1d00fcd0; frame = (0 0; 768 6); transform = [-1, 0, -0, -1, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1d00fe70>>
   |    |    |    | <UIWebBrowserView: 0x1dbf2400; frame = (0 0; 768 960); gestureRecognizers = <NSArray: 0x1d014c40>; layer = <UIWebLayer: 0x1d017d00>>
   |    |    |    |    | <TileHostLayer: 0x1d017e70> (layer)
   |    |    |    |    |    | <TileLayer: 0x1c5511a0> (layer)
   |    |    |    |    |    | <TileLayer: 0x1c551210> (layer)
   |    |    |    |    |    | <TileLayer: 0x1c551250> (layer)
   |    |    |    |    |    | <TileLayer: 0x1c551290> (layer)

The updated screenshot:

enter image description here

By just changing the height of the navigationbar to 44 and use recursiveDescription command I got:

$0 = 0x2008f680 <UIWindow: 0x1ed814f0; frame = (0 0; 768 1024); autoresize = W+H; layer = <UIWindowLayer: 0x1ed815f0>>
   | <UIView: 0x20167680; frame = (0 20; 768 1004); autoresize = RM+BM; layer = <CALayer: 0x1ed0ea50>>
   |    | <UINavigationBar: 0x1ed14b70; frame = (0 0; 768 44); gestureRecognizers = <NSArray: 0x20081bd0>; layer = <CALayer: 0x1ed09ff0>>
   |    |    | <_UINavigationBarBackground: 0x1ed8b9b0; frame = (0 0; 768 44); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x1ed08570>>
   |    |    |    | <UIImageView: 0x2007aa90; frame = (0 44; 768 3); opaque = NO; autoresize = W+TM; userInteractionEnabled = NO; layer = <CALayer: 0x200f9640>>
   |    |    | <UINavigationItemView: 0x20053320; frame = (384 22; 0 0); opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x200f9c30>>
   |    |    | <UINavigationButton: 0x200fa980; frame = (7 7; 48 30); opaque = NO; layer = <CALayer: 0x200f50c0>>
   |    |    |    | <UIImageView: 0x2016af20; frame = (0 0; 48 30); clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x2016af80>>
   |    |    |    | <UIButtonLabel: 0x2004e420; frame = (13 7; 22 15); text = 'List'; clipsToBounds = YES; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x200f8040>>
   |    | <TNSWebView: 0x2004d660; baseClass = UIWebView; frame = (0 44; 768 960); layer = <CALayer: 0x20053f20>>
   |    |    | <_UIWebViewScrollView: 0x2004a230; frame = (0 0; 768 960); clipsToBounds = YES; autoresize = H; gestureRecognizers = <NSArray: 0x20049700>; layer = <CALayer: 0x2004a6c0>; contentOffset: {0, 0}>
   |    |    |    | <UIImageView: 0x20048d50; frame = (0 0; 10 10); transform = [-1, 0, -0, -1, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x20048db0>>
   |    |    |    | <UIImageView: 0x20048cc0; frame = (0 0; 10 10); transform = [0, 1, -1, 0, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x20048d20>>
   |    |    |    | <UIImageView: 0x20048c30; frame = (0 0; 10 10); transform = [0, -1, 1, 0, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x20048c90>>
   |    |    |    | <UIImageView: 0x200f7c50; frame = (0 0; 10 10); alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x20048c00>>
   |    |    |    | <UIImageView: 0x200f7bc0; frame = (-4.5 4.5; 10 1); transform = [0, 1, -1, 0, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x200f7c20>>
   |    |    |    | <UIImageView: 0x200f7b30; frame = (-4.5 4.5; 10 1); transform = [0, -1, 1, 0, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x200f7b90>>
   |    |    |    | <UIImageView: 0x200f7a30; frame = (0 0; 1 10); transform = [-1, 0, -0, -1, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x200f7b00>>
   |    |    |    | <UIImageView: 0x200f7890; frame = (0 0; 1 10); alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x200f7a00>>
   |    |    |    | <UIImageView: 0x200fad20; frame = (0 954; 768 6); alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x200fad80>>
   |    |    |    | <UIImageView: 0x200fab80; frame = (0 0; 768 6); transform = [-1, 0, -0, -1, 0, 0]; alpha = 0; opaque = NO; userInteractionEnabled = NO; layer = <CALayer: 0x200facf0>>
   |    |    |    | <UIWebBrowserView: 0x1fb37600; frame = (0 0; 768 960); gestureRecognizers = <NSArray: 0x20049910>; layer = <UIWebLayer: 0x200f81c0>>
   |    |    |    |    | <TileHostLayer: 0x2004ed10> (layer)
   |    |    |    |    |    | <TileLayer: 0x20168820> (layer)
   |    |    |    |    |    | <TileLayer: 0x20168890> (layer)
   |    |    |    |    |    | <TileLayer: 0x201688d0> (layer)
   |    |    |    |    |    | <TileLayer: 0x20168910> (layer)
Was it helpful?

Solution

UPDATE

I take it all back. Your problem is not with view layout. I believe your problem is that the web content you're loading into your web view has a border (or padding or margin) around it. You may find “Debugging Web Content on iOS” useful. It explains how to use the Web Inspector in Safari (on your Mac) to debug the content in a UIWebView running on the simulator or a device. I think if you inspect the video element in your web content, you will discover that it is not flush with the top and left margins of the viewport.

ORIGINAL

I would guess that the navigation bar height isn't set correctly when you're looking at it in viewDidLoad. That is too soon to be checking the frames of views you've just created.

An iOS app spends its time in a “run loop” that looks like this:

while (1) {
    Event phase: process one event (e.g. touch event, timer firing, local or push notification, etc.)
    Layout phase: update the frames of new views and views with added or removed subviews
    Draw phase: draw the contents of views that need to be drawn
    Wait for the next event to arrive
}

When you add views to the view hierarchy, they are scheduled to be laid out during the layout phase. It is not until the layout phase completes that you can rely on new views to have their proper frames.

You can tap into the layout phase by writing a subclass of UIView (or a subclass of any other view class as necessary) and overriding its layoutSubviews method. Or you can implement the viewDidLayoutSubviews method in a view controller. I recommend using a UIView subclass and overriding layoutSubviews, but you may find it more expedient to just implement viewDidLayoutSubviews:

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];
    [self layoutWebView];
}

- (void)layoutWebView {
    CGRect frame = self.view.bounds;
    CGFloat navBarHeight = self.navigationBar.frame.size.height;
    frame.origin.y = navBarHeight;
    frame.size.height -= navBarHeight;
    self.webView.frame = frame;
}

Alternatively, if your deployment target is iOS 6 or later, you can use auto layout to pin the bottom edge of the navigation bar to the top edge of the web view. Put this in viewDidLoad:

[self.view addLayoutConstraints:[NSLayoutConstraint
    constraintsWithVisualFormat:@"|V:[_navigationBar][_webView]|"
    options:0 metrics:nil
    views:NSDictionaryOfVariableBindings(_navigationBar, _webView)]];

Now, what I think is specifically happening in your app is you're specifying a height of 50 when you create your UINavigationBar, but a UINavigationBar wants a height of 44. So in the layout phase, the navigation bar resizes itself to 44 points tall. Since you aren't doing anything to fix your web view's frame during layout, the web view remains 50 points below the top edge of your top-level view, leaving a gap of 6 points. So you could just change the height of the navigation bar to 44 when you create it. ;^)

OTHER TIPS

Maybe you need to take a look on your view mode of your webView. On your StoryBoard, or xib, look to the left panel, select Attributes Inspector, check the view mode selection of your webView (e.g Scale to Fill, AspectFit, AspectFill..).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top