在 ViewController 中连接 TableView - self.tableView.reloadData() 在 Swift 中不起作用

Connecting TableView within ViewController - self.tableView.reloadData() not working in Swift

我是学习 iOS 和 Swift 的新手,所以提前致歉。目前我正在尝试在 viewController 中设置一个 tableView 并在屏幕的一部分的单元格中显示数据。我当前的问题似乎是在为 numberOfRowsInSection() 调用 viewDidLoad() 中的 Alamofire HTTP 请求后重新加载 tableView 数据。这是代码:

import UIKit
import Alamofire
import SwiftyJSON

class CourseDetailViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var titleLabel: UILabel?
    @IBOutlet weak var creditsLabel: UILabel?
    @IBOutlet weak var descriptionLabel: UILabel?

    @IBOutlet weak var tableView: UITableView!

    var detailCourse: Course? {
        didSet {
            configureView()
        }
    }

    var course: Course!

    func configureView() {
        self.title = detailCourse?.abbr
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "SectionCell")
        tableView.delegate = self
        tableView.dataSource = self

        if let theCourse: Course = self.detailCourse as Course! {

            var abbr: String = theCourse.abbr!

            APIService.getCourseByAbbr(abbr) { (data) -> Void in
                self.course = Course(courseJSON: data)

                // Set labels
                self.titleLabel?.text = self.course.title!
                self.descriptionLabel?.text = self.course.description!

                if let creditsArray = self.course.credits {
                    let minimumCredit = creditsArray[0] as Int
                    self.creditsLabel?.text = String(minimumCredit)
                }

                self.tableView.reloadData()
            }
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: - Table view data source

    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // Return the number of sections.
        return 1
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // Return the number of rows in the section.
        return course.sections.count
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        // Configure the cell...
        let cell = tableView.dequeueReusableCellWithIdentifier("SectionCell", forIndexPath: indexPath) as! SectionTableViewCell
        let sectionCell = course.sections[indexPath.row]

        cell.termLabel?.text = sectionCell.term
        cell.timeLabel?.text = sectionCell.startTime
        cell.instructorLabel?.text = sectionCell.instructor

        return cell
    }
}

当我 运行 时,出现以下错误:

fatal error: unexpectedly found nil while unwrapping an Optional value

我认为原因可能是我在 viewController 中设置的 tableView 不正确。

对于完整的项目,这里是 link 到 repo:https://github.com/classmere/app/tree/develop

问题是您正在尝试解包一个值为 nil 的可选值。当你声明课程 属性 时,因为它是可选的,所以它的初始值为 nil。通常,可选值是用 ? 声明的,编译器会在不检查值是否仍然是 nil 的情况下阻止您访问基础值。然而,在这种情况下,您已将课程 属性 设置为预期的可选课程:

var course: Course!

这就像在说 "I know that course will always have a value and will never be nil"。但是我们不知道,因为它的值为 nil,直到 Alamofire 回调成功完成。

要解决此问题,请先将 course 设为标准可选:

var course: Course?

现在 Xcode 会抱怨您正在访问 course 而不打开它,因为您对 course 的声明不再打开它。

通过强制展开 Alamofire 回调中的所有内容来解决此问题:

APIService.getCourseByAbbr(abbr) { (data) -> Void in
    println("APIService()")
    self.course = Course(courseJSON: data)

    // Notice we can access self.course using ! since just assigned it above
    self.titleLabel?.text = self.course!.title!
    self.descriptionLabel?.text = self.course!.description!

    if let creditsArray = self.course!.credits {
        let minimumCredit = creditsArray[0] as Int
        self.creditsLabel?.text = String(minimumCredit)
    }

    self.tableView.reloadData()
}

然后在 cellForRowAtIndexPath 中,我们将使用可选链接来确保我们只访问 course 存在的属性:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    // Configure the cell...
    let cell = tableView.dequeueReusableCellWithIdentifier("SectionCell", forIndexPath: indexPath) as! SectionTableViewCell
    if let section = course?.sections[indexPath.row] {
        cell.termLabel?.text = section.term
        cell.timeLabel?.text = section.startTime
        cell.instructorLabel?.text = section.instructor
    }
    return cell
}

最后在 numberOfRowsForSection 中确保获得实际的部分数量而不是总是 returning 50。如果 coursenil:

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

这应该可以解决您的问题!