2016-09-02 4 views
0

Ich habe eine Klasse mit dem Namen ‚MyWearablesViewController‘ in dem ich ein Protokoll alsDer Versuch, die Delegierten zu verstehen

writen
protocol MyWearablesViewControllerDelegate { 
    func myWearablesViewControllerDidFinishedChangingTracker(viewController: UIViewController) 
} 

ich eine globale Variablen wie

erstellt haben
var delegate: MyWearablesViewControllerDelegate? 

und ich habe diese Methode verwendet mehrere Male in 'MyWearablesViewController' wie

self.delegate?.myWearablesViewControllerDidFinishedChangingTracker(self) 

Jetzt möchte ich dies eine Met auslösen hod in meiner anderen Klasse mit dem Namen 'HomeViewController' wird die Klasse deklariert als

class HomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource,MyWearablesViewControllerDelegate 

in meinem ViewWillAppear ich diesen Code

let myViewControllrer = MyWearablesViewController() 
myViewControllrer.delegate = self 

und implementiert seine Funktion als

func myWearablesViewControllerDidFinishedChangingTracker(viewController: UIViewController) { 
    // some code 
} 

Aber meine geschrieben haben Der Delegat wird nicht angerufen. Bitte führe mich, was fehlt mir?

Edit: 'HomeViewController' ist in einem TabBarController, der einen anderen ViewController mit dem Namen 'MoreViewController' enthält, der im Grunde ein TableView ist. 'MyWearablesViewController' wird gedrückt, wenn der Benutzer auf eine Zelle in 'MoreViewController'

+0

Haben Sie präsentieren die 'MyWearablesViewController'? Wenn es nie präsentiert wird, wie kann die Delegate-Methode jemals aufgerufen werden? – Sweeper

+0

@NDoc das war ein Typo Sorry dafür. – Byte

+0

@Sweeper Ich schiebe es, und es wird für den Benutzer angezeigt, aber der Delegat wurde nicht aufgerufen. – Byte

Antwort

0

Okay, gute und schlechte Nachrichten ...

Die gute Nachricht ist, dass Sie, dass Ihr Verständnis für die Delegierten ist absolut richtig! Aber die schlechte Nachricht ist, dass Sie ein grundlegenderes Konzept missverstanden haben.

Sie sagten, in viewDidAppear Sie diesen Code haben:

let myViewControllrer = MyWearablesViewController() 
myViewControllrer.delegate = self 

Sie eine neue Instanz von MyWearablesViewController erstellt und Sie self zum delegate Variablen zugewiesen. So weit, ist es gut.

jedoch in tableView(_:didSelectRowAtIndexPath:) Methode, haben Sie dies:

let myViewController = MyWearablesViewController() 
navigationController?.pushViewController(myViewController, animated: true) 

Sie erstellt andere Instanz MyWearablesViewController! Und diese Instanz ist nicht die Instanz, die Sie in der viewDidAppear Methode erstellt haben! Daher ist diese neue Instanz unabhängig von der anderen Instanz, die Sie zuvor erstellt haben. Und seine delegate Eigenschaft ist tatsächlich nil.

Also, wie können Sie es beheben?

Gemäß Ihrem Kommentar zu NDocs Antwort möchten Sie, dass der Delegat auf die HomeViewController Instanz gesetzt wird.

Um auf die HomeViewController Instanz zugreifen zu können, müssen Sie zunächst den Registerkartencontroller aufrufen und die viewControllers-Eigenschaft verwenden.

// in the didSelectRowAtIndexPath method 
let tabBarController = self.parentViewController!.parentViewController! as! UITabBarController 
let homeVC = (tabBarController.viewControllers![0] as! UINavigationController).topViewController as! HomeViewController 

Beachten Sie, dass ich Ihre HomeViewController übernehme in einer Navigationssteuerung eingebettet. Wenn nicht, verwenden Sie stattdessen:

let homeVC = tabBarController.viewControllers![0] as! HomeViewController 

Und schließlich können Sie den Delegaten festgelegt:

// in the didSelectRowAtIndexPath method 
let myViewController = MyWearablesViewController() 
myViewController.delegate = homeVC 
navigationController?.pushViewController(myViewController, animated: true) 
+0

Danke für Explainnig im Detail. Aber noch eine Frage, warum wir uns selbst brauchen. delegate = self right bevor man viewController drückt? Warum nicht in ViewDidLoad? – Byte

+1

@Byte Eigentlich können Sie es in 'viewDidLoad' tun. Aber Sie müssen verstehen, dass Sie, wann immer Sie 'MyWearablesViewController()' schreiben, eine _new_ Instanz dieser Klasse erstellen. Sie müssen also irgendwie auf eine Instanz verweisen, die in 'HomeViewController' von' MoreViewController' erstellt wurde. Solange Sie den Delegaten festlegen und die _same_ -Instanz von 'MyWearablesViewController' präsentieren, wird es funktionieren. Aber der Code in Ihrer Frage erstellt und präsentiert eine andere Instanz von "MyWearablesViewController" von der, die Sie in "viewDidAppear" erstellt haben. – Sweeper

+0

hab es dank :-) – Byte

0

auf Ihrem MoreViewController für die Vorbereitung trifft, kurz bevor Sie MyWearablesViewController drücken. Sie können tun, um diese

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 
     if segue.identifier == "pushSegue" { 
      let vc: MyWearablesViewControllerDelegate = segue.destinationViewController as! MyWearablesViewControllerDelegate 
      vc.delegate = self 
     } 
} 
+0

Ich benutze nicht Segues und storyBoard. – Byte

+0

Also, wie implementieren Sie Ihren "Push" ohne Überleitung? – Tommy

+0

Ich benutze Xib und programmiere NavigationController programmatisch – Byte

Verwandte Themen