Search code examples
iphoneobjective-ciosxcodexcode4

(id)sender = nil?


I have the following code that updates the value of a textfield with the current time. My question is: Why do you send nil as the sender at the bottom part of the code? [self showCurrentTime:nil];

CurrentTimeViewController.m

- (IBAction)showCurrentTime:(id)sender
{
NSDate *now = [NSDate date];

static NSDateFormatter *formatter = nil;

if(!formatter) {
    formatter = [[NSDateFormatter alloc] init];
    [formatter setTimeStyle:NSDateFormatterShortStyle];
}

[timeLabel setText:[formatter stringFromDate:now]];

}

...

- (void)viewWillAppear:(BOOL)animated
{
    NSLog(@"CurrentTimeViewController will appear");
    [super viewWillAppear:animated];
    [self showCurrentTime:nil];
}

Solution

  • Because normally when action handlers are called, they pass the object that initiated the call to the method, like a UIButton, or UISegmentedControl. But, when you want to call the method from your code, and not as the result of an action, you cannot pass a human as sender, so you pass nil.

    Also, the - (IBAction) indicates that this method can be connected to an event via the Interface Builder by dragging a Touch Up Inside (or touch down outside/etc) event from a button (or any other control that has some sort of event) to the File's Owner and selecting thumbTapped:.

    For example:

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    button.tag = 1001;
    [button addTarget:self action:@selector(thumbTapped:) forControlEvents:UIControlEventTouchUpInside];
    

    When the touch is released (and the touch is still inside the button), will call thumbTapped:, passing the button object as the sender

    - (IBAction)thumbTapped:(id)sender {
        if ([sender isKindOfClass:[UIButton class]] && ((UIButton *)sender).tag == 1001) {
            iPhoneImagePreviewViewController *previewVC = [[iPhoneImagePreviewViewController alloc] initWithNibName:@"iPhoneImagePreviewViewController" bundle:nil];
            [self.navigationController pushViewController:previewVC animated:YES];
            [previewVC release];
        } else {
            [[[[UIAlertView alloc] initWithTitle:[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"] 
                                         message:@"This method was called from somewhere in user code, not as the result of an action!" 
                                        delegate:self 
                               cancelButtonTitle:@"OK" 
                               otherButtonTitles:nil] autorelease] show];
        }
    }