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

标签 ios swift uitableview delegates datasource

我是一个学习 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 不正确。

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

最佳答案

问题是您正在尝试解包一个值为 nil 的可选值。当您声明类(class)属性时,由于它是可选的,因此其初始值为 nil。通常,可选值用 ? 声明,编译器将阻止您访问底层值,而不检查该值是否仍然为 nil。然而,在这种情况下,您已将类(class)属性设为预期的可选属性:

var course: Course!

这就像在说“我知道 course 总是有一个值,永远不会是 nil”。但是我们不知道,因为在 Alamofire 回调成功完成之前它的值为 nil

要解决这个问题,首先要将 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 中,确保获取实际的节数,而不是始终返回 50。如果 course 是,我们将使用 nil-coalescing 运算符返回 0 :

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

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

关于ios - 在 ViewController 中连接 TableView - self.tableView.reloadData() 在 Swift 中不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32491307/

相关文章:

objective-c - 在 iOS 上访问最近通话

ios - 注册单元重用调用实际上有什么作用?

ios - 在 UITableView 的自定义 Prototype Cell 中,UITextField 值替换为其他 Prototype Cell

ios - 在 SWIFT 4 中将文本字段限制为仅正整数

ios - 如何以编程方式使用安全区域布局?

iOS 11 NSPredicate 搜索 Swift 数组崩溃 - NSUnknownKeyException

ios - Collectionview.reloaddata() 之后无法选择 UICollectionViewcell

ios - 如何从 TodayViewController 按钮单击导航到包含的应用程序的特定 View Controller

ios - 每次重新加载表格时,自定义 UITableViewCell 中的 UILabel 都会向上移动

ios - AutoLayout 问题 UITable View 标题部分 : Adding image in the left does not works fine