views:

108

answers:

1

Say for example you want to subclass UIScrollView to create UITableView, and you don't want to use any private interfaces.

In order to load cells, you must use the the parent's delegate (scrollViewDidScroll in UIScrollViewDelegate). Additionaly, you want to add some of your own methods to the delegate (e.g. tableView:willDisplayCell:forRowAtIndexPath:).

What I do now is:

  1. Create UITableViewDelegate protocol which extends UIScrollViewDelegate protocol.
  2. Create UITableViewDelegateProxy, which I set as super.delegate, in UITableView's init.

    This class conforms to UIScrollViewDelegate and has a next property, which may reference an object conforming to UITableViewDelegate.

    By default, it tries to respond using it's own implementation. If that isn't available, it tries with the next's implementations, otherwise it doesn't respond.

    - (BOOL)respondsToSelector:(SEL)aSelector
    {
        if ([super respondsToSelector:aSelector])
            return YES;
        else if (self.next)
            return [self.next respondsToSelector:aSelector];
        else
            return NO;
    }
    
    
    - (void)forwardInvocation:(NSInvocation *)anInvocation
    {
        // self did not respond to selector
        if (self.next)
            [anInvocation invokeWithTarget:self.next];
        else
            [self doesNotRecognizeSelector:anInvocation.selector];
    }
    

    So up to now, this class is totally transparent and future-proof if UIScrollViewDelegate is extended.

    Then I add implementations for some of the delegate methods to change the default behavior or add some more behavior (e.g. call next's tableView:willDisplayCell:forRowAtIndexPath: in scrollViewDidScroll).

  3. Override delegate and setDelegate: in UITableView to return and set super.delegate.next instead of super.delegate. I also change the protocol from UIScrollViewDelegate to UITableViewDelegate.

This works OK if UIScrollView is accessing the delegate via it's ivar directly. If it uses the getter, it will not return our proxy, but instead the delegate set by the user of the class. Either way, we can't rely on this behavior. (fyi: In UIScrollView, it goes through the getter sometimes, but not always).

So if we stay with this example, the question is: how could we implement UITableView, exactly as it is today, ourselves?

+1  A: 

You can't do it and preserve the contract, which is unfortunate. It's somewhat unusual that UITableView inherits from UIScrollView; on the desktop Cocoa side of things, NSTableView does not inherit from NSScrollView.

John Calsbeek