2017-07-01 2 views
-1

Ich möchte Sie fragen, wie Sie eine Datenstruktur für mehrstufige Drill-Down-Tabellenansicht in Swift erstellen. Als ich weiß ich, wie es geht und Daten auf diese Weise TableView -> TableView -> DetailViewController mit NSObject für die Erstellung von Swift-Modellen übergeben. Aber seit einigen Wochen habe ich Mühe mit der Suche, wie man das macht: TableView -> TableView -> DetailViewController -> TableView wieder.Wie erstellt man eine Datenstruktur für mehrstufiges Drill-Down-TableView?

Da die App, die ich jetzt mache, ist Bildung bezogen, die erste TableView würde Abschnitte von Themen und leesons in ihnen enthalten, dann, wenn der Benutzer die Lektion wählt, führt die Überleitung und zeigt Inhalt als ViewController, dann drückt der Benutzer die Schaltfläche und er wird zu einem anderen TableView mit Aufgaben im Zusammenhang mit der Lektion in ihm umgeleitet. Also in allem sollte es so sein: LessonsTableView -> LessonDetailViewController -> TasksTableView -> TaskDetailViewController.

Ich kann sagen, dass das Hauptproblem darin besteht, die TableView von Aufgaben aus LessonDetailViewController aufgelistet zu bekommen. Da ich weiß, wie man 2 Datenebenen macht, kann ich 3 oder mehr nicht machen. Ich habe das ganze Internet durchsucht, ich habe Beispiele in Obj-C gefunden, aber einfach verstehe ich diese Programmiersprache nicht (versuchte, den Code in XCode zu konvertieren). Kann mir jemand sagen, wie ich das erreichen kann? Vielleicht gibt es eine Verbindung mit einem kurzen Tutorial, das ihr kennt.

aktualisieren

Ich habe es geschafft, die erste und Tableview Viewcontroller, aber mit Weitergabe von Daten von LessonViewController zu TasksTableView, immer diese Fehler stecken zu tun: Expression Typ ‚[Lektion]‘ ist ohne mehr Kontext nicht eindeutig. Vielleicht könnte jemand mir dabei helfen, mein Model:

import Foundation 

struct Aufgabe { var name: String } struct Lektion { var name: String var info: String var Aufgaben: [Aufgabe] }

Klasse LessonList {

var name: String 
var lessons = [Lesson]() 

init(name: String, lessons: [Lesson]) { 

    self.name = name 
    self.lessons = lessons 

} 

class func lessonsSection() -> [LessonList] { 
    return [self.intro(), self.can()] 
} 

private class func intro() -> LessonList { 

    let tasks: [task] = [task(name: "hello"), task(name: "Hey")] 
    let tasks1: [task] = [task(name: "is He?"), task(name: "are they?")] 

    var lessons = [Lesson]() 

    lessons.append(Lesson(name: "I am", info: "This class is I am", tasks: tasks)) 
    lessons.append(Lesson(name: "He is", info: "This class is He is", tasks: tasks1)) 

    return LessonList(name: "Intro", lessons: lessons) 

} 

private class func can() -> LessonList{ 

    let tasks: [task] = [task(name: "bye"), task(name: "can have")] 
    let tasks1: [task] = [task(name: "Can he?"), task(name: "They can't")] 

    var lessons = [Lesson]() 

    lessons.append(Lesson(name: "I can", info: "This class is I can", tasks: tasks)) 
    lessons.append(Lesson(name: "He can't", info: "This class is He can't", tasks: tasks1)) 

    return LessonList(name: "Can", lessons: lessons) 

} 

}

Die CourseTableView (erste) `Import UIKit

Klasse CourseTableVC: UITableViewController {

let lessonLists : [LessonList] = LessonList.lessonsSection() 

override func viewDidLoad() { 
    super.viewDidLoad() 

    title = "Horizon English" 

} 

// MARK: - Table view data source 

override func numberOfSections(in tableView: UITableView) -> Int { 
    return lessonLists.count 
} 

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

    return lessonLists[section].lessons.count 
} 

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

    let cell = tableView.dequeueReusableCell(withIdentifier: "lessonCell", for: indexPath) 

    let lessonList = lessonLists[indexPath.section] 
    let lessons = lessonList.lessons 
    let lesson = lessons[indexPath.row] 
    cell.textLabel?.text = lesson.name 

    return cell 
} 

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { 

    let lessonList = lessonLists[section] 

    return lessonList.name 

} 

//MARK: - UITableViewdelegate, navigation segue 

var selectedLesson: Lesson? 

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 

    let lessonLine = lessonLists[indexPath.section] 
    var lesson = lessonLine.lessons[indexPath.row] 
    selectedLesson = lesson 

} 

override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 

     if segue.identifier == "lessonDetailView" { 

      let lessonDetailVC = segue.destination as! LessonViewController 
      lessonDetailVC.lesson = selectedLesson 

     } 

} 

}`

LessonViewController , wo ich Fehler bekommen (in für segue vorbereiten) `Import UIKit

Klasse LessonViewController: UIViewController {

@IBOutlet weak var infoLabel: UILabel! 
@IBAction func toTasksButton(_ sender: Any) { 
} 

var lesson: Lesson? 

override func viewDidLoad() { 
    super.viewDidLoad() 

    title = lesson?.name 
    infoLabel.text = lesson?.info 

} 

// MARK: - navigation 
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 

    if segue.identifier == "showTasks" { 

     var taskTV = segue.destination as! TasksTableVC 

     taskTV.tasksList = lesson?.tasks as! [Lesson] 
     // Error: Expression type '[Lesson]' is ambiguous without more context 
    } 

} 

} `

und TasksTableView:` Import UIKit

Klasse TasksTableVC: UITableViewController {

var tasksList = [Lesson]() 

override func viewDidLoad() { 
    super.viewDidLoad() 

    title = "Tasks" 

} 

    // MARK: - Table view data source 

override func numberOfSections(in tableView: UITableView) -> Int { 
    return 1 
} 

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    return tasksList.count 
} 

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 

    let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell", for: indexPath) 

    let taskList = tasksList[indexPath.section] 
    let tasks = taskList.tasks 
    let task = tasks[indexPath.row] 

    cell.textLabel?.text = String(describing: task) 

    return cell 
} 

} `

Vielen Dank im Voraus.

+0

können Sie eine bildliche Darstellung oder einen Screenshot posten und es nebeneinander erklären . Es ist wirklich schwer, es so zu verstehen –

+0

Hey, ich habe Valcaniaia Vorschlag genommen und es mit Structs gemacht, alles funktioniert gut, bis der Segue in LessonViewController-Datei, der Fehler, den ich bekomme, ist "Ausdruckstyp [Lektion]" ist mehrdeutig ohne mehr Kontext ". Vielleicht können Sie es lösen? – Julius

+0

Dieser Fehlertyp tritt normalerweise auf, wenn der Compiler nicht genügend Informationen über Ihren benutzerdefinierten Typ enthält. Zum Beispiel haben Sie Ihr Array explizit als [Lektion] gegossen? aber es hätte [Lektion] sein sollen. Ich sage nur, nimm es nicht wörtlich im Zusammenhang mit deinem Code. Also müssen Sie Typen überprüfen und explizit definieren, wo Sie gedacht haben, dass der Compiler das für Sie tun sollte. Bearbeiten Sie Ihre Frage, ich werde es mir ansehen –

Antwort

0

Ich kann sagen, dass das Hauptproblem darin besteht, die TableView der Aufgaben von LessonDetailViewController aufgelistet zu bekommen.

Ich weiß nicht, was Sie schon werde ich tat Schritte so sagen, wie ich es tun würde:

1 - die Struktur implementiert haben. Das ist mein Vorschlag:

struct Task { 
    var name = "" 
} 
struct Lesson { 
    var name = "" 
    var tasks: [Tasks] // list of tasks for this lesson 
} 

ODER

struct Task { 
    var name = "" 
    var lesson: Lesson // the leasson which the task belongs to 
} 
struct Lesson { 
    var name = "" 
} 

2 - ich nehme an, Sie wissen, wie Daten zwischen View-Controller zu übergeben, so dass, wenn der Benutzer die Zelle der Lektion auswählen er will, man würde passieren das Unterrichtsobjekt an die LessonDetailVC und zeigen Sie die Daten. So etwas wie

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
    let selectedLesson = lessons[indexPath.row] 
    // code to pass to the next vc here or in prepareForSegue 
} 

3 - Um die Tableview für die Aufgaben zu erstellen Sie einfach filtern müssen (oder Abfrage oder holen, ich weiß nicht, wie Sie die Daten sind immer), um die Aufgaben zu erhalten. Lassen Sie uns zeigen, dass Sie den ersten Code von Punkt 1 verwendet haben, so dass Sie einfach das Array lesson.tasks in Ihrer Tabellenansicht anzeigen. Wenn Sie den zweiten Code von Punkt 1 gewählt haben, müssen Sie eine Abfrage mit einem Filter durchführen, der die Lektion an Sie weitergibt, etwa query.where("lesson", lesson), und Sie werden das Array tasks haben.

UPDATE

Da Sie auf Swift neu sind hier eine Idee, wie Sie Ihren View-Controller modellieren:

// Your models 
struct Task { 
    var name = "" 
    var lesson: Lesson // the leasson which the task belongs to 
} 

struct Lesson { 
    var name = "" 
} 

// This is just a DataManager to help you get your data 
class DataManager { 

    func getLessons() -> [Lesson]? { 
     return [Lesson(name: "Lesson 1"), Lesson(name: "Lesson 2"), Lesson(name: "Lesson 3")] 
    } 

    func getTasks(for lesson: Lesson) -> [Task]? { 
     guard let lessons = getLessons() else { 
      return nil 
     } 

     let allTasks = [ 
      Task(name: "T1", lesson: lessons[0]), 
      Task(name: "T2", lesson: lessons[0]), 
      Task(name: "T3", lesson: lessons[0]), 

      Task(name: "T1", lesson: lessons[1]), 
      Task(name: "T2", lesson: lessons[1]), 

      Task(name: "T1", lesson: lessons[2]), 
      Task(name: "T2", lesson: lessons[2]), 
      Task(name: "T3", lesson: lessons[2]), 
      Task(name: "T4", lesson: lessons[2]) 
     ] 

     return allTasks.filter{ $0.lesson == lesson } 
    } 

} 

class LessonsViewController: UIViewController, UITableViewDataSource { 
    @IBOutlet weak var tableView: UITableView! 

    private var lessons: [Lesson]? { 
     didSet { 
      tableView.reloadData() 
     } 
    } 

    private var selectedLesson: Lesson? 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     tableView.dataSource = self 
     lessons = DataManager().getLessons() 
    } 

    func numberOfSections(in tableView: UITableView) -> Int { 
     return 1 
    } 

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
     return lessons?.count ?? 0 
    } 

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
     let cell = tableView.dequeueReusableCell(withIdentifier: "lessonCell", for: indexPath) 

     let lesson = lessons[indexPath.section] 
     cell.textLabel?.text = lesson.name 

     return cell 
    } 

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { 
     var lesson = lessons[indexPath.row] 
     selectedLesson = lesson 
    } 

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) { 
     if segue.identifier == "lessonDetailView" { 
      let lessonDetailVC = segue.destination as! LessonViewController 
      if selectedLesson != nil { 
       lessonDetailVC.lesson = selectedLesson! 
      } 
     } 
    } 

} 

class TasksViewController: UIViewController, UITableViewDataSource { 
    var lesson: Lesson! 
    private var tasks: [Task]? { 
     didSet { 
      tableView.reloadData() 
     } 
    } 

    @IBOutlet weak var tableView: UITableView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     tableView.dataSource = self 

     tasks = DataManager().getTasks(for: lesson) 
    } 
} 
+0

danke, ich nehme an, es sollte so gemacht werden. Aber das Problem ist, dass ich Swift neu bin und nicht weiß, wie man Aufgaben an Lesson anhängt. Soll ich eine Funktion oder Klasse erstellen? Oder eine separate Modelldatei, wo die Dinge gemacht werden? – Julius

+0

Sie können dies tun, wie es sich angenehm anfühlt. Ich meine, es hängt davon ab, wie Ihre API funktioniert, wenn Sie diese Daten benötigen, wie Sie diese Daten präsentieren möchten, etc. Ich habe die Antwort nur mit einer Möglichkeit aktualisiert, dies zu tun. Ich hoffe es hilft! – valcanaia

+0

Danke, dass du dir Zeit genommen hast und all diesen Code geschrieben hast. Das ist wirklich nett. Das ist ein gutes Beispiel, da es mir an einigen Dingen etwas Programmierkenntnisse fehlt, besonders wenn man hauptsächlich trockene Theorie lernt. Ich habe Ihren Code kopiert, um zu sehen, wie es funktioniert, und ich bekomme einen Fehler in der Zeile, wo ist 'Return allTasks.filter {$ 0.lesson == Lektion}'() DataManager-Klasse), die Fehlermeldung ist "Binary Operator '= = 'kann nicht auf zwei' Lesson 'Operanden angewendet werden ". Irgendeine Idee, wie man das löst? Prost – Julius

Verwandte Themen