2015-02-04 14 views
11

Ich stoße auf Probleme mit meinen UITableViewCells. Ich habe meine UITableView mit einer API verbunden, um meine Zellen zu füllen.Schieb den Übergang von UITableViewCell zu ViewController in Swift

Dann habe ich eine Funktion erstellt, die indexPath.row ergreift, um zu identifizieren, welches JSON-Objekt innerhalb des Arrays, das an die RestaurantViewController gesendet werden soll.

Link to my Xcode Project for easier debugging and problem-solving

Hier ist, wie mein kleiner Ausschnitt schaut auf eine globale Variable, die "row-Klicks" für die Einstellung.

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 
    i = indexPath.row 
} 

Und hier ist meine prepareForSegue() Funktion, die meinen Push-segue zum RestaurantViewController anschließen sollte.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) { 
    if segue.identifier == "toRestaurant"{ 
    let navigationController = segue.destinationViewController as UINavigationController 
    let vc = navigationController.topViewController as RestaurantViewController 
    vc.data = currentResponse[i] as NSArray 
} 
} 

Und so habe ich meine segue aus dem Hier

UITableViewCell aufgebaut ist mein Ergebnis habe ich versucht, jede einzelne dieser Zellen zu klicken, aber ich werde nicht verschoben werden ein anderer ViewController ... Ich bekomme auch keinen Fehler. Was ist hier falsch?

Versuchte Lösungen, die nicht funktionieren

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) { 
     if segue.identifier == "toRestaurant"{ 
      let vc = segue.destinationViewController as RestaurantViewController 
      //let vc = navigationController.topViewController as RestaurantViewController 
      vc.data = currentResponse[i] as NSArray 
     } 
    } 
+0

Ist der Fehler nicht von der Zeile gekommen: Lassen Sie navigationController = segue.destinationViewController als UINavigationController? Ich denke, der destinationController ist kein navigationController, sondern der uiviewcontroller selbst. –

+0

@ DánielNagy Ich habe auskommentiert '' vc = navigationController.topViewController als RestaurantViewController'' und editiere die Zeile oben, um "RestaurantViewController" zu haben. Kompiliert und ausgeführt, keine Fehler, keine Antwort vom Klicken auf die Zellen. – Jack

+0

Ich habe gerade überprüft, dass das Push-Segment veraltet ist, ich bin mir nicht sicher, aber was ist, wenn Sie das in Show (z. B. Push) ändern? –

Antwort

20

Das Problem ist, dass Sie nicht richtig für die Datenverarbeitung. Wenn Sie in Ihr Array schauen, sehen Sie, dass es NSDictionaries enthält, aber in Ihrem prepareForSegue Sie versuchen, ein NSDictionary zu einem NSArray zu werfen, das die Anwendung zum Absturz bringen wird.

Ändern der data Variable in RestaurantViewController zu einem NSDictionary und Ihre prepareForSegue ändern aa NSDictionary

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) { 
    if let cell = sender as? UITableViewCell { 
     let i = redditListTableView.indexPathForCell(cell)!.row 
     if segue.identifier == "toRestaurant" { 
      let vc = segue.destinationViewController as RestaurantViewController 
      vc.data = currentResponse[i] as NSDictionary 
     } 
    } 
} 
+0

Ich bekomme einen Fehler in Zeile 54: '' self.tableData = Ergebnisse als NSDictionary! ''. Der Fehler ist: '' 'NSDictionary' ist nicht konvertierbar in 'NSArray''' – Jack

+0

in welchem ​​viewcontroller? – ergoon

+0

'' AutomaticCitySelectionViewController'' – Jack

1

Versuchen Zellen wie dies in Ihrem cellForRow Methode zu erstellen:

let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("MyTestCell", forIndexPath: indexPath) 
+0

Jetzt Ich habe einen Fehler, "Beenden App aufgrund der nicht abgefangenen Ausnahme 'NSInternalInconsistencyException', Grund: 'nicht in der Lage, eine Zelle mit Bezeichner MyTestCell aus einer Warteschlange zu entfernen - muss eine Feder oder eine Klasse für den Bezeichner registrieren oder eine Prototypzelle in einem Storyboard''' verbinden – Jack

+0

Die Zelle, mit der du dein Segment in IB verlinkt hast, sollte eine Wiederverwendungskennung als "MyTestCell" haben – Starscream

+0

Die '' MyTestCell'' wurde zum TableViewCell Bezeichner hinzugefügt und bekam eine Konsole '' (lldb) '' im grünen Text und öffnete den Thread. Er sagt: '' EXC_REAKPOINT'' – Jack

2

ich, dass in Ihrem Screenshot bemerkt von deinem Storyboard verbindet sich der Übergang die erste Prototypzelle zum RestaurantViewController. Diese Prototyp-Zelle sieht aus wie der "Basic" -Stil der Zelle mit einem Enthüllungsanzeige-Zubehör auf der rechten Seite. Aber sieh dir den Screenshot deiner laufenden App an. Die Tabelle wird mit Zellen gefüllt, die wie der "Untertitel" -Stil der Zelle aussehen, ohne dass auf der rechten Seite ein Zubehörteil für die Offenlegung angezeigt wird.

Der Grund dafür, dass Ihr Segment nie feuert, egal, was Sie tun, ist, dass das Segment nur für eine bestimmte Prototypzelle konfiguriert ist, aber diese Prototypzelle wird nie verwendet, wenn Sie die Tabelle auffüllen. Was auch immer Sie in tableView:cellForRowAtIndexPath: tun, verwenden Sie nicht die Prototyp-Zelle, die Sie möchten.

@Starscream hat die richtige Idee, die rechte Zelle mit dem richtigen Bezeichner aus der Warteschlange zu entfernen und sie mit dem Bezeichner der Prototypzelle in Interface Builder abzugleichen. Der Absturz, den Sie selbst nach dem Absturz bekommen, liegt möglicherweise am vorherigen Problem, das in den obigen Kommentaren erwähnt wurde. Ihr Abschnitt im Storyboard zeigt deutlich auf UITableViewController. Ihr Code in prepareForSegue:sender: sollte let vc = segue.destinationViewController as RestaurantViewController sein, solange RestaurantViewController eine Unterklasse von UITableViewController ist. Sie werden abstürzen, wenn Sie versuchen, es als UINavigationController zu werfen. Stellen Sie außerdem sicher, dass die Klasse für das Ziel UITableViewController im Storyboard im Bereich "Identity Inspector" als RestaurantController aufgeführt ist. Sie werden abstürzen, wenn Ihr Programm kompiliert denkt, dass das Storyboard nur eine generische UITableViewController dort enthält.

Zurück zum ursprünglichen Problem mehr, ich weiß nicht, wie Sie tableView:cellForRowAtIndexPath: implementiert haben, was von entscheidender Bedeutung sein könnte. Vielleicht ist es nicht so einfach. Vielleicht planen Sie, viele Prototyp-Zellen zu handhaben oder benutzerdefinierte Zellen zur Laufzeit zu generieren. In diesem Fall besteht eine Möglichkeit, dies für Sie einfach zu machen, darin, das Segment programmatisch auszuführen, wenn der Benutzer auf eine Zelle klickt. Anstatt eine bestimmte Prototyp-Zelle zu verwenden, machen Sie den Abschnitt eine Verbindung, die von der "Restauranger nära mig" UITableViewController zum RestaurantViewController stammt. (Verbinden Sie sich im Interface Builder, indem Sie bei gedrückter Ctrl-Taste vom Tabellenansicht-Controller-Symbol am oberen Rand des ersten auf den Körper des zweiten ziehen). Sie müssen diesem Segment eine Kennung im Bereich "Informationen" hinzufügen, um dies sinnvoll zu machen. Sagen wir es ist "toRestaurant". Fügen Sie dann am Ende Ihrer tableView:didSelectRowAtIndexPath: Methode diese Codezeile ein: self.performSegueWithIdentifier("toRestaurant", sender: self). Jetzt wird unabhängig davon, welche Zelle in der Tabelle ausgewählt ist, dieses Segment immer für Sie ausgelöst.

3

Dropbox link to stack3 directory

  1. Ich habe Schwierigkeiten zu verstehen, warum die Software viel anders als eine Standard-2-Ebene Tableview Struktur ist. Also habe ich ein kurzes Beispiel programmiert, auf das Sie über diesen Link zugreifen können. Ich habe auch den Quellcode unten eingefügt.

  2. Das Programm ahmt, was Sie haben (so gut ich es verstanden habe). Der Tabellencontroller 1 wechselt von der Tabellenansichtszelle zum Tabellencontroller 2. Ich hatte keine Probleme mit dem Seguing. Beachten Sie, dass ich das Storybook nicht erweitern muss und auch nicht muss, um den Übergang zu starten.

  3. Ich habe beide Controller in Navigation Controllers eingebettet. Meine Erfahrung ist, dass es viel Aufwand beim Einrichten der Navigation kostet.

  4. Alternativ könnte ich die Kontrolle über das erste TableViewController-Symbol oben auf dem Bildschirm auf den zweiten Controller ziehen und das Segment einrichten.

  5. Ich habe eine globale Variable (selectedRow) verwendet, obwohl es keine empfohlene Übung ist. Sie können aber auch preparedForSegue verwenden, um eine Variable in der RestaurantTableViewController (ich zeige ein Beispiel)

    1. Schließlich empfehlen, überprüfen Sie die Connections Inspector (für die Tabellenansicht Zelle in der ersten Controller), um zu bestätigen, dass ein Übergang zum zweiten Controller besteht. Wenn Sie die Steuerelemente ordnungsgemäß ziehen, sollten Sie eine Bestätigungsaufforderung sowie einen Eintrag im Inspektor "Verbindungen" eingeben.

Leider

richtig Ich kann nicht nur erhalte den Code Formatter
import UIKit 

var selectedRow = -1 

class TableViewController: UITableViewController { 

var firstArray = ["Item1","Item2","Item3","Item4"] 

override func viewDidLoad() { 

super.viewDidLoad() 

} 

override func didReceiveMemoryWarning() { 

super.didReceiveMemoryWarning() 

} 

// MARK: - Table view data source 

override func numberOfSectionsInTableView(tableView: UITableView) -> Int { 

return 1 
} 

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

return firstArray.count 

} 


let nameOfCell = "RestaurantCell" 

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

let cell = tableView.dequeueReusableCellWithIdentifier(nameOfCell, forIndexPath: indexPath) as UITableViewCell 

cell.textLabel!.text = firstArray[indexPath.row] 

return cell 

} 

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 

selectedRow = indexPath.row 

} 

// MARK: - Navigation 

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 

let vc = segue.destinationViewController as RestaurantTableViewController 

// can write to variables in RestaurantTableViewController if required 

vc.someVariable = selectedRow 

} 


} 


import UIKit 

class RestaurantTableViewController: UITableViewController { 

var secondArray = ["Item 2.1", "Item 2.2", "Item 2.3", "Item 2.4"] 

var someVariable = -1 

override func viewDidLoad() { 

super.viewDidLoad() 

} 

override func didReceiveMemoryWarning() { 

super.didReceiveMemoryWarning() 

} 

// MARK: - Table view data source 

override func numberOfSectionsInTableView(tableView: UITableView) -> Int { 

return 1 

} 

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

return secondArray.count 

} 

let nameOfCell = "RestaurantCell" 

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

let cell = tableView.dequeueReusableCellWithIdentifier(nameOfCell, forIndexPath: indexPath) as UITableViewCell 

cell.textLabel!.text = secondArray[indexPath.row] 

if indexPath.row == selectedRow { 

cell.textLabel!.text = cell.textLabel!.text! + " SELECTED" 

} 

return cell 

} 

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 

selectedRow = indexPath.row 

} 

} 
+0

So stelle ich auch mein Projekt auf, nur dass ich verwirrt bin warum Ihr 2. Tabellenansicht-Controller modal geschoben wird, anstelle des Standard-Navigationscontrollers ... und warum auch kein Zurück-Button erscheint. – PostCodeism

1

Im hier aus einer Laune heraus Ausgehen da ich gerade in schnellen jetzt immer bin, aber die Art und Weise ich es in meinem prepareForSegue() so etwas wie diese:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) { 
    if segue.identifier == "toRestaurant"{ 
     let navigationController = segue.destinationViewController as UINavigationController 
     let vc = navigationController.topViewController as RestaurantViewController 
     //notice I changed [i] to [index!.row] 
     vc.data = currentResponse[index!.row] as NSArray 
    } 
    } 

Was es wie ich aussieht, ist, dass Sie die Variable i nennen, die wie eine Art von privaten variabl ist e innerhalb einer Methode Ihrer Klasse.Sie können etwas tun, wie @Syed Tariq mit der selectRow Variable tat und legen Sie es über Ihre class SomeController: UIViewController /*, maybe some more here? */ { und melden Sie sich dann die Variable in Ihrem

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 

    selectedRow = indexPath.row 

} 

Verfahren wie oben, aber in beide Richtungen sollte eher gut funktionieren.

+0

Ich habe versucht, '' PrepareForSegue() '' aber kein Glück, und diese '' TableView''-Methode auch miteinander. Ich habe gerade den Fehler '' 0x102883662: nopw% cs: (% rax,% rax) '' beim Klicken auf die Tabellenzeile. – Jack

+0

Vielleicht könnte es Ihre '' 'currentResponse''' sein? Ich weiß nicht, was das genau ist. Hast du das irgendwo registriert? – KyleMassacre

+0

Denke nicht, es ist ein leeres '' NSArray'', das in einer Funktion aufgefüllt wird. – Jack

4

Die folgenden Schritte sollten Ihr Problem beheben. Wenn nicht, lass es mich wissen.

  1. Entfernen Sie Ihre tableView(tableView, didSelectRowAtIndexPath:) Implementierung.

  2. Make data auf RestaurantViewController Typ NSDictionary! haben

  3. Bestimmen Sie die ausgewählte Zeile in prepareForSegue:

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) { 
        if let cell = sender as? UITableViewCell { 
         let i = tableView.indexPathForCell(cell)!.row 
         if segue.identifier == "toRestaurant" { 
          let vc = segue.destinationViewController as RestaurantViewController 
          vc.data = currentResponse[i] as NSDictionary 
         } 
        } 
    } 
    
+0

Meine Konsole gibt '' (lldb) '' aus und * Thread 1 * öffnet sich ('' swift_dynamicCastObjCClassUnconditional''). – Jack

+0

Link zu meinem [Xcode-Projekt] (https://mega.co.nz/#!t89CiAKD!qOemhVZ6yCNDfsc-H43Yk4vady7yIqUx3V9d-4NrglQ) – Jack

+0

Erhalte den Fehler klingt wie 90% der Weg. Wenn Sie die innersten zwei Zeilen durch 'println (segue.destinationViewController!) Ersetzen, was erhalten Sie als Ausgabe? –

0

Ich hatte das gleiche Problem zu passieren, und ich fand die Lösung zu sein:

performSegueWithIdentifier ("toViewDetails ", Absender: Selbst)

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 
    var cellnumber = procMgr.processos[indexPath.row].numero 
    println("You selected cell #\(indexPath.row)") 
    println(cellnumber) 
    performSegueWithIdentifier("toViewDetails", sender: self) 
} 

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { 
    if segue.identifier == "toViewDetails" { 
     let DestViewController : ViewDetails = segue.destinationViewController as! ViewDetails 
    } 
} 
+0

Ich denke, zuerst preparedForSegue Methode dann didSelectRowAtIndexPath aufrufen ... –

0

Möglicherweise müssen Sie den ausgewählten Zellenindex der UItableview abrufen. Der folgende Code verwendete den ausgewählten Zellenindex (UItableview.indexPathForSelectedRow), um ein korrektes Element des Arrays zu erhalten.

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) { 
    if segue.identifier == "seguaVisitCardDetial" { 
     let viewController = segue.destinationViewController as! VCVisitCardDetial 
     viewController.dataThisCard = self.listOfVisitCards[(tblCardList.indexPathForSelectedRow?.row)!] 
    } 
} 
Verwandte Themen