2016-04-25 4 views
0

Meine benutzerdefinierte UIViewController-Unterklasse verfügt über eine gespeicherte closure-Eigenschaft. Der Verschluss Signatur wird definiert als ein einziges Argument des gleichen Typs der Klasse zu nehmen:Verwechslung hinsichtlich der Verwendung von Erfassungslisten zum Vermeiden eines Referenzzyklus

class MyViewController { 

    var completionHandler : ((MyViewController)->(Void))? 

    // ... 
} 

... Die Idee ist, das Objekt selbst vorbei als Argument des Handlers zurück, ein wenig like the UIAlertAction initializer.

Zusätzlich und der Einfachheit halber habe ich eine Fabrik (ish) Klassenmethode:

class func presentInstance(withCompletionHandler handler:((MyViewController)->(Void))) 
{ 
    // ... 
} 

... das führt die folgenden Aktionen:

  1. Erstellt eine Instanz der Ansicht, controller,
  2. Weist der Eigenschaft den Beendigungshandler zu,
  3. Stellt es modal von dem dar, was zum Zeitpunkt des Aufrufs der Top-/Root-View-Controller ist.

My-View-Controller definitiv undicht: stelle ich einen Haltepunkt auf deinit(), aber die Ausführung nie trifft, sogar Art und Weise, nachdem ich mit meiner Ansicht-Controller getan und es wird zurückgewiesen.

Ich bin mir nicht sicher, wie oder wo ich eine Aufnahmeliste angeben sollte, um den Zyklus zu vermeiden. Jedes Beispiel, das ich gefunden habe, scheint es dort zu platzieren, wo der Schließkörper definiert ist, aber ich kann meinen Code nicht kompilieren.

  1. Wo deklariere ich die Verschlusseigenschaft? (wie?)

    var completionHandler : ((MyViewController)->(Void))? 
    // If so, where does it go? 
    
  2. Wo deklariere ich den Verschlussparameter?

    class func presentInstance(withCompletionHandler handler:((MyViewController)->(Void))) 
    { 
    // Again, where could it go? 
    
  3. Wo ich die obige Funktion aufrufen und den Verschlusskörper passieren?

    MyViewController.presentInstance(withCompletionHandler:{ 
        [unowned viewController] viewController in 
    
        // ... 
    }) 
    //^Use of unresolved identifier viewController 
    //^Definition conflicts with previous value 
    
  4. Wo ich eigentlich Anruf die Schließung, in Richtung self? Nichts davon wird kompilieren:

    self.completionHandler?(unowned self) 
    self.completionHandler?([unowned self] self) 
    self.completionHandler?([unowned self], self) 
    

Antwort

0

Nun, es meiner Ansicht nach stellt sich heraus Controller durch einen Block zurückgehalten wurde, aber nicht das, was ich dachte:

class MyViewController 
{ 
    deinit(){ 
     print("Deinit...") 
    } 

    // ... 

    @IBAction func cancel(sender:UIButton) 
    { 
     completionHandler(self) 
     // View controller is dismissed, AND 
     // deinit() gets called.  
    } 

    @IBAction func punchIt(sender: UIButton) 
    { 
     MyWebService.sharedInstance.sendRequest( 
      completion:{ error:NSError? in 

       self.completionHandler(self) 
       // View controller is dismissed, BUT 
       // deinit() does NOT get called. 
      } 
     ) 
    } 

... Also ist es die Schließung, die an MyWebService.sharedInstance.sendRequest() übergeben wurde, die meinen Ansichtcontroller lebendig hielt. Ich reparierte sie durch eine Aufnahmeliste wie folgt ergänzt:

MyWebService.sharedInstance.sendRequest( 
      completion:{ [unowned self] error:NSError? in 

jedoch, ich immer noch nicht ganz verstehen, warum die kurzlebige Abschluss-Handler, an den Webservice-Klasse übergeben, einmal ausgeführt und angeordnet sind, hielt meinen View Controller am Leben. Diese Schließung, die nirgendwo als Eigentum gespeichert ist, sollte freigegeben werden, sobald sie verlassen wird, nicht wahr?

Ich muss etwas verpassen. Ich denke, ich denke immer noch nicht in Portale Schließungen.

Verwandte Themen