伙计们,我从FoursquareAPI获取数据,下面是我的代码。
但是我在cellForRowAtIndexPath得到了一个零错误venueItems是零

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        // Table View
        self.tableView = UITableView()

        // Location Manager Stuff
        self.locationManager = CLLocationManager()
        self.locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
        self.locationManager.delegate = self

        let status = CLLocationManager.authorizationStatus()

        if status == .notDetermined {
            self.locationManager.requestWhenInUseAuthorization()
        } else if status == CLAuthorizationStatus.authorizedWhenInUse
            || status == CLAuthorizationStatus.authorizedAlways {
            self.locationManager.startUpdatingLocation()
        } else {
            showNoPermissionsAlert()
        }

        exploreVenues()
    }

    // Func's

    func exploreVenues() {

        guard let location = self.locationManager.location else {
            return
        }
        var parameters = [Parameter.query: "Pubs"]
        parameters += location.parameters()

        let task = self.session.venues.explore(parameters) {
            (result) -> Void in

            if self.venueItems != nil {
                return
            }

            if !Thread.isMainThread {
                fatalError("!!!")
            }

            if let response = result.response {

                if let groups = response["groups"] as? [[String: AnyObject]] {
                    var venues = [[String: AnyObject]]()

                    for group in groups {
                        if let items = group["items"] as? [[String: AnyObject]] {
                            venues += items
                        }
                    }

                    self.venueItems = venues
                }

                self.tableView.reloadData()
            } else if let error = result.error, !result.isCancelled() {
                self.showErrorAlert(error)
            }
        }

        task.start()
    }

    // Table View Data source
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        if let venueItems = self.venueItems {
            return venueItems.count
        }

        return 10
    }


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

        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! VenueTableViewCell
        // This is where the error occurs
        let item = self.venueItems![(indexPath as NSIndexPath).row] as JSONParameters!
        self.configureCellWithItem(cell, item: item!)

        return cell
    }

    func configureCellWithItem(_ cell: VenueTableViewCell, item: JSONParameters) {

        if let venueInfo = item["venue"] as? JSONParameters {
            cell.nameLabel.text = venueInfo["name"] as? String
        }
    }

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {

        let cell = cell as! VenueTableViewCell

        let tips = self.venueItems![(indexPath as NSIndexPath).row]["tips"] as? [JSONParameters]

        guard let tip = tips?.first, let user = tip["user"] as? JSONParameters,
            let photo = user["photo"] as? JSONParameters else {
                return
        }

        let URL = photoURLFromJSONObject(photo)

        if let imageData = session.cachedImageDataForURL(URL) {
            cell.venueImageView.image = UIImage(data: imageData)
        } else {

            cell.venueImageView.image = nil

            session.downloadImageAtURL(URL) { (imageData, error) -> Void in
                let cell = tableView.cellForRow(at: indexPath) as? VenueTableViewCell

                if let cell = cell, let imageData = imageData {
                    let image = UIImage(data: imageData)
                    cell.venueImageView.image = image
                }
            }
        }
    }

}

我个人对编程很陌生,我认为venueItems是零的,因为cellForRowAtIndexPath是先执行的。如果这是一个错误,我如何修复它,使cellForRowAtIndexpath中的代码在我的venueItems有值之后运行。。或者其他更有效的方法?

最佳答案

numberOfRowsInSection为零时,10返回self.venueItemsself.venueItems在您的网络请求完成之前似乎为nil,因此在被告知表视图有10行要显示时,表视图会为每行请求一个单元格。然后尝试强制展开可选属性(self.venueItems!)并崩溃。
看起来您的self.venueItems是可选的,原因很好,不要使用强制展开(!)来丢弃该信息。当这个属性为nil时,您可以返回0行,或者将它初始化为一个非可选的空数组,然后您可以一直请求它的count
一般来说,对于这类问题,您不想集中精力防止cellForRowAtIndexPath被调用,而是计划在任何时候调用它,并在后台任务尚未完成时返回合理的结果(如报告表有0行)。

08-19 12:27