【问题标题】:(id)sender = nil?(id)sender = nil?
【发布时间】:2011-10-01 21:37:44
【问题描述】:

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

【问题讨论】:

    标签: iphone objective-c ios xcode xcode4


    【解决方案1】:

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

    另外,- (IBAction) 表示此方法可以通过 Interface Builder 连接到事件,方法是从按钮(或任何其他具有某些某种事件)到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];
        }
    }
    

    【讨论】:

      【解决方案2】:

      IBAction 方法在它们最常见的形式中采用单个发送者参数。当被系统调用时,它们将触发操作的控件作为发送者参数传递。如果您要直接调用该方法,则需要提供一个发送方。由于该方法不是由刚刚与用户交互的控件调用的,因此使用了 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]];
      }
      

      【讨论】:

        【解决方案3】:

        这是因为您需要发送 一些东西,因为您正在调用的方法的签名需要一个参数。

        :(id)sender 常见于按钮按下动作中。当您将 nib 中的按钮连接到视图控制器中的方法时,它将检查它是否可以接受参数。如果是,“发送者”将指向在 nib 中创建的 UIButton 的实例。

        这也适用于程序化按钮创建,以及您发送选择器的许多其他情况。

        【讨论】:

          【解决方案4】:

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

          在 Objective-c 中使用 Nil 代替 NULL,它纯粹是为了满足您正在调用的函数的规范而发送的。

          由于函数实际上并不使用主体中的参数,因此发送给函数的对象实际上并不重要。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-03-05
            • 1970-01-01
            • 2012-12-28
            • 2011-05-06
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-09-03
            相关资源
            最近更新 更多