为什么我不能用填充了从json获取的数据的单元格填充我的uiTableView?

时间:2016-02-21 17:18:15

标签: ios swift uitableview

这是我的班级:

import UIKit
import SwiftyJSON

class ListOfEvents: UIViewController, UITableViewDataSource, UITableViewDelegate {

    var tableView:UITableView?
    var items = NSMutableArray()

    override func viewDidLoad() {
        let frame:CGRect = CGRect(x: 0, y: 100, width: self.view.frame.width, height: self.view.frame.height-100)
        self.tableView = UITableView(frame: frame)
        self.tableView?.dataSource = self
        self.tableView?.delegate = self
        self.view.addSubview(self.tableView!)
        print("aaa")
        getAllRequests()

    }


    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.items.count;
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        tableView.registerClass(SingleEventCell.self, forCellReuseIdentifier: "cell")
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! SingleEventCell

        let user:JSON =  JSON(self.items[indexPath.row])
       print(user["username"].description)
       // cell.username.text = user["username"].description
       // cell.descr.text = "ggg"
        print(cell)
        return cell
    }

    func getAllRequests() {
        print("getAllRequests")
        RestApiManager.sharedInstance.getRequests { json in
            let results = json//["username"]
            for (index: String, subJson: JSON) in results {
                let user: AnyObject = JSON.object
                self.items.addObject(user)
                dispatch_async(dispatch_get_main_queue(),{
                    self.tableView?.reloadData()
                })
            }
        }
    }

}

我尝试使用从webservice获取的数据填充我的自定义UITableViewCell。我的问题是:

print(user["username"].description) //that prints perfectly

但如果我取消注释以下其中一行:

// cell.username.text = user["username"].description 
// cell.descr.text = "ggg"

我收到错误:

fatal error: unexpectedly found nil while unwrapping an Optional value

我怀疑在尝试初始化/可见算法之前我会尝试引用这些单元格,但如果是这样的话 - 我该如何防止它?我使用的是viewDidLoad()方法,但这并没有改变任何内容 - 错误仍然相同。

我该如何解决?

==== EDIT

@vadian建议它在故事板和代码中有不同的表格视图。我接受了这个建议并从故事板创建了一个桌面视图的出口,代码中的所有地方都改变了{{1}的引用到新创建的插座:

导入UIKit 导入SwiftyJSON

tableview

但现在当我运行它时,我得到了错误;

class ListOfEvents: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet weak var tview: UITableView!
    var tableView:UITableView?
    var items = NSMutableArray()

    override func viewDidLoad() {
        let frame:CGRect = CGRect(x: 0, y: 100, width: self.view.frame.width, height: self.view.frame.height-100)
        tview = UITableView(frame: frame)
        tview.dataSource = self
        tview.delegate = self
        self.view.addSubview(tview!)
        print("aaa")
        getAllRequests()

    }


    func tableView(tview: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.items.count;
    }

    func tableView(tview: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        tview.registerClass(SingleEventCell.self, forCellReuseIdentifier: "cell")
        let cell = tview.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! SingleEventCell

        let user:JSON =  JSON(self.items[indexPath.row])
       print(user["username"].description)
       // cell.username.text = user["username"].description
        cell.descr.text = "ggg"
        print(cell)
        return cell
    }

    func getAllRequests() {
        print("getAllRequests")
        RestApiManager.sharedInstance.getRequests { json in
            let results = json
            for (index: String, subJson: JSON) in results {
                let user: AnyObject = JSON.object
                self.items.addObject(user)
                dispatch_async(dispatch_get_main_queue(),{
                    self.tview.reloadData()
                })
            }
        }
    }

}

这里:

fatal error: unexpectedly found nil while unwrapping an Optional value

有没有办法解决它?

3 个答案:

答案 0 :(得分:2)

这一行有一个明显的问题:

tview = UITableView(frame: frame)

这不是您在代码中创建表视图的方式。您必须调用指定的初始化程序,即initWithFrame:style:。例如:

tview = UITableView(frame: frame, style: .Plain)

但请注意,您的代码存在各种其他问题,这些问题也可能存在问题。例如,这一行:

let frame:CGRect = CGRect(x: 0, y: 100, width: self.view.frame.width, height: self.view.frame.height-100)

该行取决于具有帧的self.view和足够大小的帧(即高度超过100个像素)。但是你不知道这一点,因为在viewDidLoadself.view仅仅存在 - 它还没有达到它的最终帧,因为它尚未被放入界面中布局。所以那条线在那时非常危险。

答案 1 :(得分:0)

我猜你可能没有在username内正确设置descr和/或SingleEventCell个插座。

看看here,了解如何正确连接插座。

答案 2 :(得分:0)

您的问题是,tableView.cellForRowAtIndexPath想要加载它时尚未提取您的JSON对象,因此会出现意外发现的错误。

你可以做的是:

创建新的委托协议:

protocol NetworkingDelegate {

    func didFinishLoadingData()
}

创建一个类Networking,您可以将API请求放在:

class Networking {

var networkingDelegate: NetworkingDelegate?


// (I am using Alamofire here so the function itself will differ a little.)

    func getAllRequests() {

        Alamofire.request(.GET, "YOUR_API_ENDPOINT")
            .responseJSON { response in

                if response.result.isSuccess {
                    let jsonObject = JSON(response.result.value!)

                    User.populateUserDataSourceFromJSON(jsonObject)

                    self.dispatchAndRefresh()
                }
        }
    }
}


func dispatchAndRefresh() {
    dispatch_async(dispatch_get_main_queue()) {
        if let delegate = self.networkingDelegate {
            delegate.didFinishLoadingData()
        }
    }
}

在你的Modelclass中有一个名为populateUserDataSourceFromJSON

的函数
class User {

let name = String()
let age = Int()
//...

init() {
}


class func populateUserDataSourceFromJSON(json: JSON) {

    userDataSource = [User]()

    for (_, user): (String, JSON) in json {

        let currentUser = User()

        currentUser.name = user["name"].stringValue
        currentUser.age = user["age"].intValue
        //...

        userDataSource.append(currentUser)
    }
}

在ViewController中添加我们创建的代理:

class ListOfEvents: UIViewController, UITableViewDataSource, UITableViewDelegate, NetworkingDelegate { 
    //...

创建Networking类的引用:

let networking = Networking()

并将其委托给自己:

override func viewDidLoad() {
    super.viewDidLoad()

    networking.networkingDelegate = self
    //...

唯一要做的就是通过实现didFinishloadingData()

使ViewController符合Delegate
func didFinishLoadingData() {

    tableView.reloadData()
}

我希望这会有所帮助。