2011-10-01 48 views
1

我有以下代碼用當前時間更新文本字段的值。我的問題是:爲什麼你發送nil作爲代碼底部的發送者? [self showCurrentTime:nil];(id)sender = 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]; 
} 

回答

3

因爲通常動作處理程序被調用時,他們通過發起調用方法,像UIButton對象,或UISegmentedControl。但是,如果您想從代碼中調用方法,而不是作爲操作的結果,則無法通過人爲sender,因此您通過nil

此外,- (IBAction)表明,該方法可以通過Interface Builder通過拖動Touch Up Inside被連接到一個事件(或觸摸向下外/等)從一個按鈕(或任何其它控制具有某種事件)的事件至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

這是因爲您需要發送,因爲您要調用的方法的簽名需要參數。

:(id)sender通常出現在按鈕按鈕操作中。當你將一個nib中的按鈕連接到視圖控制器中的一個方法時,它將檢查它是否可以接受一個參數。如果是,則「發件人」將指向在筆尖中創建的UIButton的實例。

編程式按鈕創建以及您在選擇器中發送的許多其他情況也是如此。

1

showCurrentTime函數的規範有一個名爲sender的參數。如果您在不發送對象ID的情況下調用該函數,則該調用將無效。

在objective-c中使用Nil而不是NULL,並且它純粹被髮送以滿足您要調用的函數的規範。

由於函數實際上並沒有在實體內使用參數,所以實際上並不關心你發送給函數的對象。

3

IBAction方法以其最常見的形式採用單個發件人參數。當系統調用時,它們將觸發該操作的控件作爲發送者參數傳遞。如果您要直接調用該方法,則需要提供發件人。由於該方法沒有被剛剛與用戶交互的控件調用,因此使用nil。

我其實認爲直接調用action並不是一個好的模式。使用標籤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]]; 
}