Missing Edit button and "unrecognized selector" (solved)


#1

I had a couple of typos in my code that I didn’t notice even looking back through it a couple times, so I figured I’d mention them here and save some possible grief.

Problem 1: “Edit” button isn’t showing up.
Solution: I put an NSLog() trace in the headerView function, and it wasn’t being called. Finally I saw that I mis-typed the long UITableView delegate methods on p.158. I thought they were arbitrary strings, but they’re actually predetermined methods of UITableViewDelegate (thanks OPTION+CMD+DOUBLE_CLICK). Apparently the first delegate method invokes the header / calls the function (i’m still a little fuzzy on this, but marching on).

[code]
// call header

  • (UIView *)tableView:(UITableView *)tv viewForHeaderInSection:(NSInteger)sec {
    return [self headerView];
    }
    // make room at top
  • (CGFloat)tableView:(UITableView *)tv heightForHeaderInSection:(NSInteger)sec {
    return [[self headerView] frame].size.height;
    }[/code]

Problem 2: Clicking the Edit button throws an exception, even with the “editingButtonPressed” method defined.
Solution: On p.157, the “action” parameter’s @selector argument has an unexpected colon inside the parenthesis. I’m guessing this is what differentiates a method from a variable, like another language’s empty parentheses in something like callMyFunction()

[editButton addTarget:self action:@selector(editingButtonPressed:) forControlEvents:UIControlEventTouchUpInside];

Great book btw.


#2

Recall from the Objective-C chapter that, while colons specify that there will be an argument, it’s also part of the name of the method.

Try this out: change your implementation of editButtonPressed: to not include an argument.

- (void)editButtonPressed
{
    ....
}

Then, remove the colon from the method name in the argument to addTarget:action:forControlEvents:. It’ll work. In fact, you can implement both editButtonPressed and editButtonPressed: - they will be two totally different methods.

Also, for additional fun: action methods (those that a UIControl sends an object when an event occurs) can have three forms: no arguments, one argument or two arguments.

If you supply a method with no arguments, @selector(method), you don’t get anything passed to you. If you supply a method with one argument, @selector(method:), you get the control object that is sending the message as an argument. If you supply a method with two arguments, @selector(method:event:), you get the control object as the first argument and an instance of UIEvent as the second argument. The event object stores information about touches and timing.

Typically, for controls, you either want the sender because you need to check its state or you don’t want any additional information. Rarely, if ever, do you need the event object.


#3

Ah, got it! Thanks Joe.