[英]Why I can't populate my uiTableView with cells filled with data fetched from json?
This is my class: 这是我的课:
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()
})
}
}
}
}
I try to fill my custom UITableViewCell
s with data fetched from webservice. 我尝试用从Web服务获取的数据填充自定义
UITableViewCell
。 My problem is that: 我的问题是:
print(user["username"].description) //that prints perfectly
but if I uncomment one of the lines below: 但是,如果我取消注释以下行之一:
// cell.username.text = user["username"].description
// cell.descr.text = "ggg"
I'm getting the error: 我收到错误消息:
fatal error: unexpectedly found nil while unwrapping an Optional value
I suspect that I try to refer to the cells before they are initialized/visible for the algorithm, but if so - how can I prevent it? 我怀疑我尝试在对算法进行初始化/可见之前引用这些单元格,但是如果是这样,我该如何防止呢? I'm using
viewDidLoad()
method but that doesn't change anything - the error is still the same. 我正在使用
viewDidLoad()
方法,但是它什么都没有改变-错误仍然相同。
How can I fix it? 我该如何解决?
====EDIT ====编辑
@vadian suggested that it's a different table view in storyboard and in the code.I went with that advice and created an outlet for the tableview from storyboard and in all places in code changed the reference from tableview
to newly created outlet: @vadian建议,它在情节串连图板,并在code.I不同的表视图去与建议创建了一个出口从故事板的tableview,并在代码中的所有地方改变从参考
tableview
到新形成的出口:
import UIKit import SwiftyJSON 导入UIKit导入SwiftyJSON
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()
})
}
}
}
}
But now when I run it I'm getting error; 但是现在当我运行它时,我得到了错误;
fatal error: unexpectedly found nil while unwrapping an Optional value
here: 这里:
tview.dataSource = self
Is there a way to fix it? 有办法解决吗?
One obvious problem is this line: 这行是一个明显的问题:
tview = UITableView(frame: frame)
That is not how you create a table view in code. 这不是您在代码中创建表视图的方式。 You must call its designated initializer , which is
initWithFrame:style:
. 您必须调用其指定的初始化程序 ,它是
initWithFrame:style:
For example: 例如:
tview = UITableView(frame: frame, style: .Plain)
Note, however, that your code has various other problems that could also be an issue here. 但是请注意,您的代码还有其他各种问题,在这里也可能是一个问题。 For example, this line:
例如,这一行:
let frame:CGRect = CGRect(x: 0, y: 100, width: self.view.frame.width, height: self.view.frame.height-100)
That line depends on self.view
having a frame, and a frame of sufficient size (ie more than 100 pixels in height). 那条线取决于
self.view
有一个框架和一个足够大的框架(即高度超过100个像素)。 But you don't know this, because in viewDidLoad
, self.view
merely exists — it has not yet achieved its final frame because it has not yet been put into the interface and laid out. 但是您不知道这一点,因为在
viewDidLoad
, self.view
仅存在 —由于尚未放入接口并进行布局,因此尚未达到最终框架。 So that line is very risky at that point. 因此,那条线在那时非常冒险。
Your problem is, that your JSON object is not yet fetched at the time tableView.cellForRowAtIndexPath
wants to load it, therefor giving you an unexpectedly found nil error. 您的问题是,
tableView.cellForRowAtIndexPath
要加载它时尚未提取JSON对象,因此给您一个意外发现的nil错误。
What You can do is this: 您可以执行以下操作:
Create a new Delegate protocol: 创建一个新的委托协议:
protocol NetworkingDelegate {
func didFinishLoadingData()
}
Create a class Networking
where you put your API request in: 创建一个类
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()
}
}
}
In your Modelclass have a function called populateUserDataSourceFromJSON 在您的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)
}
}
In your ViewController add the Delegate we created: 在您的ViewController中,添加我们创建的Delegate:
class ListOfEvents: UIViewController, UITableViewDataSource, UITableViewDelegate, NetworkingDelegate {
//...
create a reference of your Networking class: 创建您的网络类的引用:
let networking = Networking()
and set it's delegate to self: 并将其委托设置为self:
override func viewDidLoad() {
super.viewDidLoad()
networking.networkingDelegate = self
//...
Only thing left to do is to make your ViewController conform to the Delegate by implementing didFinishloadingData() 剩下要做的就是通过执行didFinishloadingData()使ViewController符合Delegate。
func didFinishLoadingData() {
tableView.reloadData()
}
I hope this helps. 我希望这有帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.