2009-06-12 51 views
2

我正在創建一個視圖控制器,用於輸入文本信息。iPhone編程中的選擇器

視圖本身由導航欄中的標籤,文本字段和兩個按鈕組成:「取消」和「確定」。

當用戶按下「取消」時,我只是彈出回到根視圖控制器。

但是,當他按下OK時,我想首先從根視圖控制器調用一個函數,然後才彈出。

我試圖實現它以下列方式:

標題:

@interface UserInputViewController : UIViewController { 
    UILabel *textLabel; 

    UITextField *textField; 

    SEL OKButtonAction; 
} 

-(NSString*) getEnteredText; 

-(UserInputViewController*) initWithTitle: (NSString*)title Text: (NSString*)text andOKButtonSelector: (SEL) OKButtonSelector; 

@end 

實現:

@implementation UserInputViewController 

-(UserInputViewController*) initWithTitle: (NSString*)title Text: (NSString*)text andOKButtonSelector: (SEL) OKButtonSelector 
{ 
    self = [self init]; 
    self.title = title; 

    OKButtonAction = OKButtonSelector; 

    textLabel = [ [UILabel alloc] initWithFrame: CGRectMake(20, 20, 280, 50)]; 
    [textLabel setText: text]; 
    [ [self view] addSubview: textLabel]; 

    textField = [ [UITextField alloc] initWithFrame: CGRectMake(20, 100, 280, 50)]; 
    [ [self view] addSubview: textField]; 

    return self; 
} 

-(NSString*) getEnteredText 
{ 
    return [textField text]; 
} 

-(void) popToRootViewController 
{ 
    [ [self navigationController] popToRootViewControllerAnimated: YES ]; 
} 

-(void) popToRootWithOKAction 
{ 
    [ [self navigationController] popToRootViewControllerAnimated: YES ]; 
    [self performSelector: OKButtonAction]; 
} 

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 

    //Cancel button 
    UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithTitle: NSLocalizedString(@"cancel button", @"") style: UIBarButtonSystemItemCancel target: self action: @selector(popToRootViewController) ]; 


    [ [self navigationItem] setLeftBarButtonItem: cancelButton animated: NO]; 
    [cancelButton release]; 

    //OK button 
    UIBarButtonItem *OKButton = [[UIBarButtonItem alloc] initWithTitle: NSLocalizedString(@"ok button", @"") style: UIBarButtonSystemItemSave target: self action: @selector(popToRootWithOKAction) ]; 

    [ [self navigationItem] setRightBarButtonItem: OKButton animated: NO]; 
    [OKButton release]; 

} 

這裏是根視圖控制器方法:

-(void) OKButtonAction 
{ 
    NSLog(@"text: %@", [newProfileDialog getEnteredText]); 
    [newProfileDialog release]; 
} 

-(void) add_clicked { 
    newProfileDialog = [ [UserInputViewController alloc] initWithTitle: @"User name" Text: @"Please enter a new user name:" andOKButtonSelector: @selector(OKButtonAction)]; 

    [ [self navigationController] pushViewController: newProfileDialog animated: YES]; 
} 

但是,當我編譯它並從推送的視圖中按確定按鈕時,我收到一個異常。

我還不熟悉選擇器編程,所以我很難找出我做錯了什麼。

我該如何實現這個目標?

謝謝。

回答

1

你要做的事情叫做「委託」 - 確定按鈕的動作被委託給另一個對象,在這種情況下是根控制器。試着改變你的視圖控制器的初始化這樣:

-(UserInputViewController*) initWithTitle:(NSString*)title Text:(NSString*)text delegate:(id)delegate; 

存儲在一個實例變量委託(無需保留它),在popToRootWithOKAction電話:

if([delegate respondsToSelector:@selector(OKButtonAction)]) 
    [delegate performSelector:@selector(OKButtonAction)]; 

委託方法甚至都不需要在你的根控制器的.h文件中聲明。在UserInputViewController的頭文件,只需添加一個第二@interface

@interface NSObject (UserInputViewControllerDelegate) 
    -(void)OKButtonAction; 
@end 
1

[self performAction:OKButtonAction]將調用對象的OKBUttonAction選擇器。最有可能的是你想要在委託上給它打電話。雖然這將工作:

[[self.navigationController rootViewController] performSelector:OKButtonAction];

這不是大多數框架完成它的方式。我推薦的兩種方法是:

  • 添加一個「ID目標;」實例變量,並在你的init方法中傳遞它。然後你可以使用[delegate performSelector:OKButtonAction]。這將視圖控制器從根視圖控制器中分離出來,並允許您在其他情況下使用此視圖控制器。
  • 除了「目標」,我還會考慮使用代理和Protocol而不是使用選擇器。這給了你強有力的方法,比如像UITableViewDelegate這樣的其他代表。
1

我會建議在蘋果的網站上的Objective-C編程語言文檔中讀取section on selectors

除非你正在進行沉重的反省,否則沒有什麼理由真正將選擇器聲明爲變量。無論何時需要,請使用@selector()指令來創建它。