2011-05-29 43 views
124

我有兩個UITableViewControllers並需要使用委託將值從子視圖控制器傳遞給父級。我知道代表是誰,只是想看一個簡單的例子。如何設置一個簡單的代理來在兩個視圖控制器之間進行通信?

謝謝

+1

如果您嘗試使用「實用工具」Xcode模板,則已經實現了委託模式。你需要更多的幫助嗎? – phi 2011-05-29 16:35:58

+0

這是一個非常簡單的教程。 http://www.tutorialspoint.com/ios/ios_delegates.htm – 2014-07-24 11:00:14

回答

295

簡單的例子網站...

假設子視圖控制器具有UISlider,我們希望通過委託傳遞滑塊的值回父。

在子視圖控制器的頭文件,聲明委託類型及其方法:

ChildViewController.h

#import <UIKit/UIKit.h> 

// 1. Forward declaration of ChildViewControllerDelegate - this just declares 
// that a ChildViewControllerDelegate type exists so that we can use it 
// later. 
@protocol ChildViewControllerDelegate; 

// 2. Declaration of the view controller class, as usual 
@interface ChildViewController : UIViewController 

// Delegate properties should always be weak references 
// See http://stackoverflow.com/a/4796131/263871 for the rationale 
// (Tip: If you're not using ARC, use `assign` instead of `weak`) 
@property (nonatomic, weak) id<ChildViewControllerDelegate> delegate; 

// A simple IBAction method that I'll associate with a close button in 
// the UI. We'll call the delegate's childViewController:didChooseValue: 
// method inside this handler. 
- (IBAction)handleCloseButton:(id)sender; 

@end 

// 3. Definition of the delegate's interface 
@protocol ChildViewControllerDelegate <NSObject> 

- (void)childViewController:(ChildViewController*)viewController 
      didChooseValue:(CGFloat)value; 

@end 

在子視圖控制器的實現,調用委託方法的要求。

ChildViewController.m

#import "ChildViewController.h" 

@implementation ChildViewController 

- (void)handleCloseButton:(id)sender { 
    // Xcode will complain if we access a weak property more than 
    // once here, since it could in theory be nilled between accesses 
    // leading to unpredictable results. So we'll start by taking 
    // a local, strong reference to the delegate. 
    id<ChildViewControllerDelegate> strongDelegate = self.delegate; 

    // Our delegate method is optional, so we should 
    // check that the delegate implements it 
    if ([strongDelegate respondsToSelector:@selector(childViewController:didChooseValue:)]) { 
     [strongDelegate childViewController:self didChooseValue:self.slider.value]; 
    } 
} 

@end 

在父視圖控制器的頭文件中,聲明它實現了ChildViewControllerDelegate協議。

RootViewController.h

#import <UIKit/UIKit.h> 
#import "ChildViewController.h" 

@interface RootViewController : UITableViewController <ChildViewControllerDelegate> 

@end 

在父視圖控制器的實現,適當地實現委託方法。

RootViewController.m

#import "RootViewController.h" 

@implementation RootViewController 

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 
    ChildViewController *detailViewController = [[ChildViewController alloc] init]; 
    // Assign self as the delegate for the child view controller 
    detailViewController.delegate = self; 
    [self.navigationController pushViewController:detailViewController animated:YES]; 
} 

// Implement the delegate methods for ChildViewControllerDelegate 
- (void)childViewController:(ChildViewController *)viewController didChooseValue:(CGFloat)value { 

    // Do something with value... 

    // ...then dismiss the child view controller 
    [self.navigationController popViewControllerAnimated:YES]; 
} 

@end 

希望這有助於!

+1

父母如何註冊爲孩子的代表? – Madbreaks 2013-01-16 01:36:20

+2

通過調用'detailViewController.delegate = self;'(它位於上述代碼片段中的「-tableView:didSelectRowAtIndexPath:'中 – 2013-01-16 11:04:24

+0

如果ChildViewController委託給UITableView,那麼UITableView方法應該放在哪兒? parent? – Dejell 2013-03-19 10:01:50

30

下面的代碼只是顯示委託概念的最基本的用法。您根據您的要求命名變量和類。

首先,你需要聲明一個協議:

我們稱之爲MyFirstControllerDelegate.h

@protocol MyFirstControllerDelegate 
- (void) FunctionOne: (MyDataOne*) dataOne; 
- (void) FunctionTwo: (MyDatatwo*) dataTwo; 
@end 

導入MyFirstControllerDelegate。^ h文件並確認您的FirstController與協議MyFirstControllerDelegate

#import "MyFirstControllerDelegate.h" 

@interface FirstController : UIViewController<MyFirstControllerDelegate> 
{ 

} 

@end 

在實現文件中,你需要實現協議的兩個功能:在

@implementation FirstController 


    - (void) FunctionOne: (MyDataOne*) dataOne 
     { 
      //Put your finction code here 
     } 
    - (void) FunctionTwo: (MyDatatwo*) dataTwo 
     { 
      //Put your finction code here 
     } 

    //Call below function from your code 
    -(void) CreateSecondController 
    { 
      SecondController *mySecondController = [SecondController alloc] initWithSomeData:.]; 
      //..... push second controller into navigation stack 
      mySecondController.delegate = self ; 
      [mySecondController release]; 
    } 

@end 

SecondController

@interface SecondController:<UIViewController> 
{ 
    id <MyFirstControllerDelegate> delegate; 
} 

@property (nonatomic,assign) id <MyFirstControllerDelegate> delegate; 

@end 

在執行文件SecondController

@implementation SecondController 

@synthesize delegate; 
//Call below two function on self. 
-(void) SendOneDataToFirstController 
{ 
    [delegate FunctionOne:myDataOne]; 
} 
-(void) SendSecondDataToFirstController 
{ 
    [delegate FunctionTwo:myDataSecond]; 
} 

@end 

Here是關於委託的維基文章。

+0

雖然這涵蓋了如何設置工作委託協議。我認爲它忽略了幾個要點。首先,在委託上調用方法時,應首先檢查委託對該選擇器的響應。如果它沒有你的應用程序將崩潰。其次,您需要將「@protocol MyFirstControllerDelegate」設置爲@protocol MyFirstControllerDelegate CW0007007 2014-06-19 07:02:31

0

以下解決方案是使用委託將數據從VC2發送到VC1的非常基本和簡單的方法。

PS:該溶液在的Xcode 9.X製成,夫特4

聲明的協議和創建的委託變種成ViewControllerB

import UIKit 

    //Declare the Protocol into your SecondVC 
    protocol DataDelegate { 
     func sendData(data : String) 
    } 

    class ViewControllerB : UIViewController { 

    //Declare the delegate property in your SecondVC 
     var delegate : DataDelegate? 
     var data : String = "Send data to ViewControllerA." 
     override func viewDidLoad() { 
      super.viewDidLoad() 
     } 

     @IBAction func btnSendDataPushed(_ sender: UIButton) { 
       // Call the delegate method from SecondVC 
       self.delegate?.sendData(data:self.data) 
       dismiss(animated: true, completion: nil) 
      } 
     } 

ViewControllerA確認協議,並希望通過代理方法接收數據sendData

import UIKit 
     // Conform the DataDelegate protocol in ViewControllerA 
     class ViewControllerA : UIViewController , DataDelegate { 
     @IBOutlet weak var dataLabel: UILabel! 

     override func viewDidLoad() { 
      super.viewDidLoad() 
     } 

     @IBAction func presentToChild(_ sender: UIButton) { 
      let childVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier:"ViewControllerB") as! ViewControllerB 
      //Registered delegate 
      childVC.delegate = self 
      self.present(childVC, animated: true, completion: nil) 
     } 

     // Implement the delegate method in ViewControllerA 
     func sendData(data : String) { 
      if data != "" { 
       self.dataLabel.text = data 
      } 
     } 
    } 
相關問題