(id)sender = nil?

时间:2011-10-01 21:37:44

标签: iphone objective-c ios xcode xcode4

我有以下代码用当前时间更新文本字段的值。我的问题是:为什么你在代码的底部发送nil作为发送者? [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];
}

4 个答案:

答案 0 :(得分:3)

因为通常在调用操作处理程序时,它们会将启动调用的对象传递给方法,如UIButtonUISegmentedControl。但是,当您想要从代码中调用方法而不是作为操作的结果时,您无法将人传递为sender,因此您传递nil

此外,- (IBAction)表示此方法可以通过Interface Builder通过从按钮拖动Touch Up Inside(或触摸外部/ etc)事件来连接到事件(或任何其他具有某种事件的控件)File's Owner并选择thumbTapped:

例如:

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

触摸释放后(触摸仍在按钮内),将调用thumbTapped:,将button对象作为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];
    }
}

答案 1 :(得分:3)

IBAction方法,以其最常见的形式,采用单个发送者参数。当系统调用时,它们将触发操作的控件作为sender参数传递。如果您要直接调用该方法,则需要提供发件人。由于该方法不是由用户刚刚与之交互的控件调用的,因此使用了nil。

我实际上认为直接调用动作并不是一个好的模式。使用带有标记IBAction的方法意味着“响应用户操作调用此方法”,并且这是在该方法中工作时能够依赖的重要上下文。如果代码将直接调用该方法,则该想法已被违反。

通常我觉得做这样的事情会更好:

- (void)updateTime:(NSDate *)date {
    static NSDateFormatter *formatter = nil;
    if(!formatter) {
        formatter = [[NSDateFormatter alloc] init];
        [formatter setTimeStyle:NSDateFormatterShortStyle];
    }

    [timeLabel setText:[formatter stringFromDate:date]];
}

- (IBAction)showCurrentTime:(id)sender {
    [self updateTime:[NSDate date]];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self updateTime:[NSDate date]];
}

答案 2 :(得分:1)

这是因为您需要发送某些内容,因为您正在调用的方法的签名会引发争议。

:(id)sender常见于按键操作。将nib中的按钮连接到视图控制器中的方法时,它将检查是否可以进行参数。如果是,则“发件人”将指向在笔尖中创建的UIButton的实例。

对于程序化按钮创建以及您在选择器中发送的许多其他情况也是如此。

答案 3 :(得分:1)

showCurrentTime函数的规范有1个名为sender的参数。如果您在不发送对象ID的情况下调用该函数,则该调用将无效。

在objective-c中使用Nil而不是NULL,并且它纯粹被发送以满足您正在调用的函数的规范。

由于函数实际上并没有在正文中使用参数,因此发送给函数的对象实际上并不重要。