Challenge: More UIWebView


#1

Here’s my solution to the problem:

In WebViewController.h:

@interface WebViewController : UIViewController
{
    BOOL backEnabled;
    BOOL forwardEnabled;
    UIBarButtonItem *backButton;
    UIBarButtonItem *forwardButton;
}

@property (nonatomic, readonly) UIWebView *webView;
@property (nonatomic, assign) BOOL backEnabled;
@property (nonatomic, assign) BOOL forwardEnabled;

- (void)toggleBack;
- (void)toggleForward;


@end

Then in WebViewController.m:

- (void)loadView
{
    CGRect screenFrame = [[UIScreen mainScreen] applicationFrame];
    UIWebView *wv = [[UIWebView alloc] initWithFrame:screenFrame];
    [wv setScalesPageToFit:YES];
    
    UIToolbar *toolBar = [[UIToolbar alloc] initWithFrame:CGRectMake(0.0, 920, 768, 44.0)];
    [toolBar setBarStyle:UIBarStyleDefault];
    
    backButton = [[UIBarButtonItem alloc] initWithTitle:@"Back"
                                                  style:UIBarButtonItemStyleBordered
                                                 target:wv
                                                 action:@selector(goBack)];
    forwardButton = [[UIBarButtonItem alloc] initWithTitle:@"Forward"
                                                     style:UIBarButtonItemStyleBordered
                                                    target:wv
                                                    action:@selector(goForward)];
    UIBarButtonItem *backToggle = [[UIBarButtonItem alloc] initWithTitle:@"toggleBack"
                                                                   style:UIBarButtonItemStyleBordered
                                                                  target:self
                                                                  action:@selector(toggleBack)];
    UIBarButtonItem *forwardToggle = [[UIBarButtonItem alloc] initWithTitle:@"toggleForward"
                                                                      style:UIBarButtonItemStyleBordered
                                                                     target:self
                                                                     action:@selector(toggleForward)];
    [toolBar setItems:[NSArray arrayWithObjects:backButton, backToggle, forwardButton, forwardToggle, nil] 
                                                                            animated:YES];
      
        
    [wv addSubview:toolBar];
    
    [backButton release];
    [backToggle release];
    [forwardToggle release];
    [forwardButton release];
    [toolBar release];
    
    [self setView:wv];
    [wv release];
}

- (void)toggleBack
{
    if (backEnabled) {
        backEnabled = NO;
        [backButton setEnabled:YES];
    } else {
        backEnabled = YES;
        [backButton setEnabled:NO];
    }
}

- (void)toggleForward
{
    if (forwardEnabled) {
        forwardEnabled = NO;
        [forwardButton setEnabled:YES];
    } else {
        forwardEnabled = YES;
        [forwardButton setEnabled:NO];
    }
}

- (UIWebView *)webView
{
    return (UIWebView *)[self view];
}

@end

There are two main concerns:

  1. I had to create the toolbar and set it using coordinates.
    Is there any way to just get it to hug the bottom of the view? I had to use trial and error to set it, and I felt this was a pretty inelegant solution.
    Not to mention I cannot find any info on the coordinate grid of the iPhone and iPad screens in the documentation.

  2. As far as the bonus goes, I could not figure out how to use canGoBack and canGoForward to toggle the back and forward buttons, since I was unable to set these properties. I made my own toggle buttons and tried to use a conditional statement like

if ([self backEnabled]) {
    [wv canGoBack];
}

but it just ignored this.

Any help would be appreciated.
Also if anybody knows where to find coordinate grid info in the documentation that would be great, too.
It’s gotta be there.


#2

Hi,

  1. setting the toolBar position

This code is mostly from the UICatalog sample code and should do the trick

[code] UIToolbar *toolBar = [[UIToolbar alloc]initWithFrame:CGRectZero];
toolBar.barStyle = UIBarStyleDefault;

// size up the toolbar and set its frame
[toolBar sizeToFit];
CGFloat toolbarHeight = [toolBar frame].size.height;
[toolBar setFrame:CGRectMake(CGRectGetMinX(wv.bounds),
                             CGRectGetMinY(wv.bounds) + CGRectGetHeight(wv.bounds) - (toolbarHeight * 2.0) + 2.0,
                             CGRectGetWidth(wv.bounds),
                             toolbarHeight)];

[/code]

  1. canGoBack, canGoForward
    These are readonly boolean’s that are set depending on what the webView can do. i.e. if it’s the first page then you can’t go back or forward. Once you’ve navigated to another page then you can go back etc.

To use these then you can implement one of the UIWebViewDelegate methods - you will need to set the delegate to get this to trigger.

- (void)webViewDidFinishLoad:(UIWebView *)webView { backButton.enabled = [webView canGoBack]; forwardButton.enabled = [webView canGoForward]; }

  1. The iOS Human Interface Guidelines has the platform screen resolutions.

HTH
Gareth


#3

Hi all,

Basically the same solution here… but I’m having a few issues.

  1. The very bottom of the web page is covered by the toolbar. So I need to also adjust the frame of the UIWebView so that it doesn’t overlap.

EDIT: it works better using the ToolBar of the navigation controller instead of setting as a subview. No overlap, no calculating frames.
webViewController.hidesBottomBarWhenPushed = NO;
[webViewController setToolbarItems:[NSArray arrayWithObjects:backButton, space, forwardButton, nil]];
Then you also need to hide the toolbar when the webViewController is popped. I did this in ListViewController’s viewDidAppear

  1. Why doesn’t it work when I put the toolbar set up in webViewDidStartLoad: ? The canGo* messages don’t seem to be accurate until the page finished loading. But it’s annoying to wait until a page loads when you know you just want to go back anyway.

EDIT: I made another post about this. No answer. The canGo* properties only seem reliable in webViewDidFinishLoad.

  1. After clicking forward or back, the buttons should be disabled until you can check the status canGoForward/Back in your delegate function. Right? Otherwise, they can be clicked while the page is loading, but at that point you don’t know if they are valid (see 2).

  2. We are reusing our UIWebView, which seems to maintain a history across different RSSItems. (When you look at a second item from the listView, you can press back to see previous pages.) There doesn’t seem to be any documented way to clear the history, so our WebViewController should have a function to ditch its old webView and make a new one.

EDIT: can’t find any solution to this. I thought I would just give the webViewController a new UIWebView with a fresh history, but the webView property is read-only.

Kurt