2017-07-01 68 views
-1

我想問你們如何在Swift中爲多級鑽取TableView製作一個數據結構。就我自己而言,我知道如何去做,並通過這種方式傳遞數據。TableView - > TableView - > DetailViewController使用NSObject創建Swift模型。但是現在幾個星期,我正在努力尋找如何做到這一點:TableView - > TableView - > DetailViewController - > TableView再次。如何爲多級鑽取TableView製作數據結構?

由於我現在所做的應用程序與教育有關,第一個TableView將包含主題和Leesons部分,然後當用戶選擇課程時,Segue將執行內容顯示爲ViewController,然後用戶按下按鈕,然後他被重定向到另一個TableView,其中包含與課程相關的任務。 所以它應該是這樣的:LessonsTableView - > LessonDetailViewController - > TasksTableView - > TaskDetailViewController

我可以說主要問題是從LessonDetailViewController列出任務的tableView。因爲我知道如何製作2個級別的數據,但不能做3個或更多。 我已經搜索了所有的互聯網,我已經在Obj-C中找到了一些例子,但我不明白編程語言(試圖轉換XCode中的代碼)。任何人都可以指導我如何實現這一目標?也許你們知道有一個簡短教程的鏈接。

更新

我已經成功地做到了第一的TableView和ViewController,但堅持通過數據從LessonViewController到TasksTableView,收到此錯誤:表達式類型「[教訓]」是沒有更多的上下文曖昧。 也許有人可以幫助我這個問題,我的模型:

import Foundation 

結構任務{ 變數名稱:字符串 } 結構課程{ 變數名稱:字符串 VAR信息:字符串 VAR任務:[任務] }

類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) 

} 

}

的CourseTableView(第一)`進口的UIKit

類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 在那裏我得到錯誤(在賽格瑞準備)`進口的UIKit

class LessonViewController:UIViewController {

提前的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 
} 

}`

感謝:

@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 
    } 

} 

}`

和TasksTableView:`進口的UIKit

類TasksTableVC。

+0

您可以發佈的圖示或屏幕截圖,並通過邊解釋邊。這真的很難理解像這樣 –

+0

嘿,我已經採取了Valcanaia的建議,並用結構做了,所有工作都很好,直到LessonViewController文件中出現segue,我得到的錯誤是「Expression type'[Lesson]'不明確沒有更多的上下文「。也許你知道如何解決它? – Julius

+0

這種類型的錯誤通常發生在編譯器沒有足夠的自定義類型信息時。例如,你明確地將你的數組轉換爲[Lesson]?但它應該是[課程]。我只是說,不要從字面上理解你的代碼。所以你需要驗證類型並明確定義它,你認爲編譯器應該爲你做什麼。編輯你的問題,我會看看它 –

回答

0

我可以說主要問題是從LessonDetailViewController列出任務的tableView。

我不知道你已經這樣做了,我會說我怎麼會做它什麼步驟:

1 - 具有結構來實現。這是我的建議:

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

OR

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

2 - 我想你知道如何通過視圖控制器之間的數據,因此當用戶選擇他想要的教訓的細胞,你會通過將課程對象添加到LessonDetailVC並顯示數據。像

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

3的東西 - 要爲你只需要過濾的任務的實現代碼如下(或查詢,或者取,我不知道你是如何得到的數據),以獲得任務。假設您使用了第1項中的第一個代碼,因此您只需在表格視圖中顯示lesson.tasks數組。如果您選擇第1項中的第二個代碼,則必須使用通過您的課程的篩選器執行一些查詢,如query.where("lesson", lesson),您將擁有任務數組。

UPDATE

既然你是新上Swift這裏有一個關於如何您的視圖控制器模式的構想:

// 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

謝謝,我想應該這樣做。但問題是我是Swift新手,我不知道如何將任務添加到課程中。我應該創建一個函數或類嗎?或者一個單獨的模型文件將在哪裏完成? – Julius

+0

你可以這樣做,感覺很舒服。我的意思是,這取決於你的API獲取數據的工作原理,當你需要這些數據,你想如何表達等等。我只是用一種方法更新了答案。希望能幫助到你! – valcanaia

+0

感謝您花時間編寫所有代碼。這真的很好。這是一個很好的例子,因爲我對某些事情缺乏實用的編程知識,特別是當主要學習「幹」理論時。我沒有複製你的代碼,看看它是如何工作的,並且我在'return allTask​​s.filter {$ 0.lesson == lesson}'()DataManager類的行中得到錯誤,錯誤消息是「Binary operator'= ='不能應用於兩個「課程」操作數「。任何想法如何解決這個問題?歡呼 – Julius