2017-07-01 35 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