Tip: Restoring the Sidebar Table of Contents in Xcode 4

Ever since Apple removed the sidebar table of contents (TOC) in Xcode 4 I find myself using the online documents (which still have it) instead of those in Xcode. The other day I stumbled on this great blog entry from Shawn Webster who explains some black magic to restore the sidebar TOC “Showing Table of Contents in Xcode Documentation

Posted in Tips | Leave a comment

Tutorial: Building a Web Browser with UIWebView (Part 4)

In this tutorial, inspired by user feedback, I will show how to add gesture recognizers as alternatives to the “back” and “forward” buttons on the toolbar and also how to suppress spurious error messages.

The starting point for this tutorial is the completed code from part 3:
WebBrowser3.zip

Adding Gesture Recognizers

Gesture recognizers were added to iOS in version 3.2 and dramatically reduce the amount of code required to support user interface gestures. All gesture recognizers are subclasses of the UIGestureRecognizer class. Currently the following subclasses exist:

  • UILongPressGestureRecognizer
  • UIPanGestureRecognizer
  • UIPinchGestureRecognizer
  • UIRotationGestureRecognizer
  • UISwipeGestureRecognizer
  • UITapGestureRecognizer

The basic procedure for using gesture recognizers is the same for all types. You first allocate the recognizer specifying a target/action to be taken when the gesture is recognized, next you set properties to specify the details of the gesture you want to respond to and finally you add the recognizer to a view.

Open WebBrowserViewController.m and add the following code at the end of your viewDidLoad.

    // Add gesture reconizers
    UISwipeGestureRecognizer* leftSwipe = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(backGesture:)] autorelease];
    leftSwipe.numberOfTouchesRequired = 1;
    leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft;
    [self.webView addGestureRecognizer:leftSwipe];

This code allocates a UISwipeGestureRecognizer that will call a method backGesture: (see below) on the view controller, it then specifies that the swipe should a single touch swipe to the left, and adds the newly created recognizer to the web view. Since the base code of this tutorial does not use Automatic Reference Counting (ARC) you should autorelease the recognizer. If you are trying to use this code in an ARC-enabled project you simply omit the autorelase.

The code for the “forward” recognizer is similar:

    UISwipeGestureRecognizer* rightSwipe = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(forwardGesture:)] autorelease];
    rightSwipe.numberOfTouchesRequired = 1;
    rightSwipe.direction = UISwipeGestureRecognizerDirectionRight;
    [self.webView addGestureRecognizer:rightSwipe];

When the gesture recognizer recognizes a gesture it calls the specified method with a single argument, itself. In the above code you associated backGesture: with the left swipe gesture and forwardGesture: with the right swipe gesture. You must now provide implementations of these methods. At the following methods to WebBrowserViewController.m:

// MARK: - Gesture Recognizers
- (void)backGesture:(UISwipeGestureRecognizer*)recognizer
{
    [self.webView goBack];
}

- (void)forwardGesture:(UISwipeGestureRecognizer*)recognizer
{   
    [self.webView goForward];
}

The implementations, as you can see, are very straightforward; they simply call the relevant UIWebView methods.

At this point you should be able to compile and run the project and the new gesture should be working. If you are speedy with you swipes a UIAlertView may pop-up reporting “Error: The operation couldn’t be completed. (NSURLErrorDomain error -999.)”. The next section explains how to deal with this.

Suppressing Spurious Error Messages

If a user clicks a link within a UIWebView or performs some other action that causes a new page to load before the current page has completed loading, the view’s webView:didFailLoadWithError: delegate method will be called with error code NSURLErrorCancelled (-999).

Constant UIAlertViews popping up reporting this “error” are not very useful to the user. The error is benign and informing the user serves no purpose, therefore alter your webView:didFailLoadWithError: as shown below.

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    [self updateButtons];
    if([error code] != NSURLErrorCancelled)
    {
        [self informError:error];
    }
}

More About Gestures

For a more in-depth tutorial on UIGestureRecognizer I highly recommend Ray Wenderlich’s excellent “UIGestureRecognizer Tutorial in iOS 5: Pinches, Pans, and More!“.

Download the Completed Tutorial

You can download the completed project for this tutorial here: WebBrowser4.zip


Posted in Tutorial | Tagged , , , , | 7 Comments

Precompiled Ogg Vorbis Libraries for iOS

As well as the “All About Images” series of tutorials I have also been working on a series of tutorials explaining how to compile common open source packages for iOS. When I reviewed various forums it appeared that libogg and libvorbis seemed to be proving problematic to compile, so I decided that these libraries might be good candidates.

The compilation process was not trivial so it will take me some time to write up the tutorial on how to compile them, however it seemed to useful to release the compiled libraries themselves.

Packaging

The libraries are compilations of libogg 1.3.0 and libvorbis 1.3.3 from xiph.org. They have been packaged as pseudo-frameworks, Ogg.framework and Vorbis.framework; the vorbis framework contains the combined contents of libvorbis.a, libvorbisenc.a and libvorbisfile.a. The frameworks are compiled for armv7 and i386.

Testing

The libraries have been tested on an iPad 1 running iOS 4.3, an iPad 3 running iOS 5.1, an iPhone 4 running iOS 5.0 and the simulator. Initial testing has focused on the decoder. The encoder has not been tested as yet.

Download

The frameworks can be downloaded here: OggVorbis-0.8.zip


Posted in Precompiled | 13 Comments