2016-07-23 10 views
0

Hier ist mein Problem:Swift - Aufruf einer func eines UIViewController aus einem benutzerdefinierten UITableViewCell

ich einen MainTableViewController mit einem Auslass für eine Tabelle haben, die benutzerdefinierte UITableViewCells verwendet. Ich habe auch eine Steckdose für eine UIView, genannt BlackView, in MainTableViewController.

Was ich tun möchte: In myCustomCell möchte ich "BlackView.hidden = false" setzen. Ich versuche, "Klasse func" in meiner MainTableViewController-Datei zu verwenden, und es von MyCustomCell aufzurufen, aber es funktioniert nicht, da Xcode keine BlackView erkennt, wenn ich das Wort "Klasse" vor "func" setze.

Also, ich möchte eine Funktion eines MainTableViewController oder Zugriff auf seine Steckdose aus dem .swift meiner .xib-Datei aufrufen.

Weiß jemand, wie man das macht?

Hier Datei meine .xib ist:

My .xib file

Hier ist die .swift für meine .xib Datei:

class myCustomCell: UITableViewCell { 

    @IBOutlet weak var commentTextView: UITextView! 


    override func awakeFromNib() { 

     commentTextView.delegate = self 

     super.awakeFromNib() 

    } 


    func textViewDidBeginEditing(textView: UITextView) { 

     MainTableViewController.hideBlackView(true) 

    } 

    func textViewDidEndEditing(textView: UITextView) { 

     var comment = commentTextView.text 

    } 

} 

Hier ist meine MainTableViewController:

class MainTableViewController: UIViewController 

    @IBOutlet weak var MyTable: UITableView! 

    @IBOutlet weak var BlackView: UIView! 

    override func viewDidLoad() { 

     BlackView.hidden = true; 

     MyTable.registerNib(UINib(nibName: "myCustomCell", bundle: nil), forCellReuseIdentifier: "myCustomCellID") 

    } 

    class func hideBlackView(setToHidden: Bool) { 

     if setToHidden == true { 

      BlackView.hidden = true 

     } else { 

      BlackView.hidden = false 

     } 


    } 


    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 


      let cell = tableView.dequeueReusableCellWithIdentifier("myCustomCellID") as! PublishHeaderTableViewCell 

      cell.selectionStyle = UITableViewCellSelectionStyle.None 


      return cell 


    } 

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 

     return 1 

    } 

} 

Hier ist mein Main.storyboard:

My Main.storyboard

Antwort

3

Die Antwort ist Delegation

Blackview eine Instanz ist, die durch das Betriebssystem erstellt wird. Die Steckdose ist eine spezielle Eigenschaft (eine Steckdose genannt), die auf diese Instanz verweist. Wenn MainTableViewController angezeigt wird, wird eine Instanz davon vom Betriebssystem erstellt.

Sie möchten wahrscheinlich eine Instanzmethode und keine Klassenmethode verwenden, um die ausgeblendete Eigenschaft für eine Instanz von BlackView zu ändern. Dazu müssen Sie eine Referenz der MainTableViewController-Instanz an myCustomCell übergeben. Dies nennt man Delegation, die ios Programmierung und die meisten MVC-Modelle funktioniert.

dieses Add Gehen Sie einen Delegaten Protokoll definieren (knapp über der Definition für die benutzerdefinierte Zelle wäre normal) und fügen Sie eine schwache var an die Zelle dieser Art:

// use a class protocol for delegates so weak properties can be used 
    protocol MyCustomCellDelegate: class { 
     func hideBlackView(setToHidden: Bool) 
    } 

    class MyCustomCell: UITableViewCell { 

      weak var delegate: MyCustomCellDelegate? 
      @IBOutlet weak var commentTextView: UITextView! 

      override func awakeFromNib() { 

       commentTextView.delegate = self 

       super.awakeFromNib() 
      } 


      func textViewDidBeginEditing(textView: UITextView) { 

       delegate?.hideBlackView(true) 
      } 

      func textViewDidEndEditing(textView: UITextView) { 

       var comment = commentTextView.text 
      } 
    } 

Dann, wenn Sie nach oben setzen Die Zellen in cellForRowAtIndexPath werden als der richtige Zelltyp umgewandelt, der MyCustomCell in dem Beispiel sein sollte, das Sie nicht PublishHeaderTableViewCell angegeben haben (Beachten Sie auch, dass ich den Namen Ihrer benutzerdefinierten Zellklasse auf Großbuchstaben umgestellt habe, wie es in ios Industriestandard ist) Entwicklung). Setzen Sie den Delegaten schließlich auf die Instanz von MainTableViewController (die innerhalb von Instanzfunktionen "self" genannt wird).

BTW, in Ihrem Fall verwenden Sie nur eine Zelle, so dass Sie wahrscheinlich Zellen nicht aus der Warteschlange nehmen und wiederverwenden müssen. Sie können dies einfach ausführen und eine einfache Instanz zurückgeben, die Sie in der cellForRowAtIndexPath-Methode für die Zelle erstellt haben. Wie auch immer, ich werde all das an Ort und Stelle belassen, falls Sie Ihren Code für Stack Overflow einfach vereinfacht haben.

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

      // you need to cast the cell to your custom class to use it 
      let cell = tableView.dequeueReusableCellWithIdentifier("myCustomCellID") as! MyCustomCell 

      cell.selectionStyle = UITableViewCellSelectionStyle.None 

      // set the delegate 
      cell.delegate = self 

      return cell 
    } 

Schließlich, und was sehr wichtig ist, müssen Sie erklären, dass MainTableViewController zu den Protokollen entspricht, dass sie so die Funktionen (Methoden) verwenden werden, dass andere Objekte, um es delegieren wollen erfolgreich sein wird. In Ihrem Fall muss es sowohl MyCustomCellDelegate entsprechen, das wir oben geschrieben haben, als auch, da Sie es für die Datenquelle der TabelleView (für cellForRowAtIndexPath und numberOfRowsInSection) verwenden, müssen Sie deklarieren, dass es UITableViewDataSource entspricht (Sie haben dies möglicherweise getan bereits über den Interface Builder (Storyboard) .. wenn nicht, kannst du es in der Klassendefinition tun.

// Declare objects conform to protocols by including protocol names separated by commas after the colon (or the class inherited from) 
    class MainTableViewController: UIViewController, MyCustomCellDelegate, UITableViewDataSource { 

      @IBOutlet weak var MyTable: UITableView! 
      @IBOutlet weak var BlackView: UIView! 

      override func viewDidLoad() { 
       BlackView.hidden = true 
       MyTable.registerNib(UINib(nibName: "myCustomCell", bundle: nil), forCellReuseIdentifier: "myCustomCellID") 
      } 

     func hideBlackView(setToHidden: Bool) { 
        // since they are both bools just set BlackView.hidden to the setToHidden parameter directly 
        BlackView.hidden = setToHidden 
      } 


      func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

        let cell = tableView.dequeueReusableCellWithIdentifier("myCustomCellID") as! MyCustomCell 
        cell.selectionStyle = UITableViewCellSelectionStyle.None 

        // set the delegate 
        cell.delegate = self 

        return cell 
      } 

      func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
       return 1 
      } 
    } 

Als abschließende Bemerkung, ich bin nicht sicher, für die UITextView den Delegaten setzt eine entsprechende in der awakeFromNib Methode in Ihrer benutzerdefinierten Zelle. Ich weiß, dass diese Methode nicht immer feuert. In Ihrem Fall, da es an einer Steckdose ist, denke ich, dass es OK ist, aber ich benutze XIB-Dateien nicht sehr viel von mir selbst, also möchten Sie vielleicht auf der Konsole drucken um sicherzustellen, dass es jedes Mal aufgerufen wird oder das Problem genauer untersucht.

+0

Vielen Dank! Es funktioniert jetzt! Ich musste nur die folgenden Änderungen in Ihrem Code vornehmen: 1. Löschen Sie "schwach" von "schwach var delegieren: MyCustomCellDelegate?"; 2.: Löschen Sie "class" von "class func hideBlackView (setToHidden: Bool)". –

+0

Netter Fang auf die Notwendigkeit, "Klasse" zu entfernen. Das war eine Kopie Paste Tippfehler. Keiner der obigen Codes wurde in XCode geschrieben oder getestet. Es kann also andere Fehler geben. Ich habe den Code aktualisiert, um den Fehler zu entfernen. Sie sollten nicht die schwachen von "schwachen var delegieren: MyCustomDelgate?" Eigentlich ist es eine schlechte Übung, das "Schwache" nicht zu haben, weil es einen starken Bezug auf das Objekt hat, das es besitzt. Dies verhindert die automatische Referenzzählung, die sich mit der Speicherverwaltung hinter den Szenen in ios beschäftigt. –

+0

Ich sollte hinzufügen, dass in Ihrem Fall die Zellen zerstört werden, wenn die Verweise auf sie, die von der UITableView gehalten werden, zerstört werden (wenn die Tabelle den Geltungsbereich verlässt). Dies wird mit ziemlicher Sicherheit passieren, bevor Ihre UIViewController-Instanz den Gültigkeitsbereich verlässt. In diesem Fall sollte dies nicht den gefürchteten "Retain-Zyklus" verursachen. Vielleicht warst du nicht in der Lage, es schwach zu machen, weil ich vergessen habe, es in meinem obigen Code als Klassenprotokoll zu deklarieren, was ich jetzt behoben habe. –