In my current project I'm trying to fetch news from a REST-Endpoint and I wanna refresh the UITableView
once the network request is finished. So I call reloadData()
but unfortunately cellForRowAtIndexPath
isn't called however numberOfRowsInSection
gets called and returns the correct number of items.
Following my code stripped down to the relevant parts:
class NewsTableViewController: UIViewController {
private var newsItems: Array<NewsItem>!
private var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
newsItems = []
addDummyItem()
prepareTableView()
getNews()
}
func addDummyItem(){
let newsItem = NewsItem()
newsItem.dateString = "12th May"
newsItem.title = "Lorem ipsum"
newsItem.imgUrl = "URL"
newsItem.url = "URL"
newsItem.message = "Lorem ipsum dolor sit amet"
self.newsItems.append(newsItem)
}
func getNews(){
let url = NSURL(string: "http://someurl.com/news")
let urlRequest: NSMutableURLRequest = NSMutableURLRequest(URL: url!)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithRequest(urlRequest) { data, response, error in
guard data != nil && error == nil else {
print(error)
return
}
guard let httpResponse = response as? NSHTTPURLResponse where httpResponse.statusCode == 200 else {
print("status code not 200; \(response)")
return
}
let json = String(data:data!, encoding: NSISOLatin1StringEncoding)
let arr: AnyObject? = json?.parseJSONString
for item in arr as! Array<AnyObject>{
let newsItem = NewsItem()
newsItem.dateString = (item["dateString"] as AnyObject? as? String) ?? ""
newsItem.title = (item["title"] as AnyObject? as? String) ?? ""
newsItem.imgUrl = (item["imgUrl"] as AnyObject? as? String) ?? ""
newsItem.url = (item["url"] as AnyObject? as? String) ?? ""
newsItem.message = (item["message"] as AnyObject? as? String) ?? ""
self.newsItems.append(newsItem)
}
print("Network request finished - call reloadData()")
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
}
task.resume()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
automaticallyAdjustsScrollViewInsets = false
}
private func prepareTableView() {
tableView = UITableView()
tableView.dataSource = self
tableView.delegate = self
tableView.separatorColor = UIColor.clearColor()
}
}
extension NewsTableViewController : UITableViewDataSource{
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("Item count: ", newsItems.count)
return newsItems.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
print("cellForRowAtIndexPath called with indexPathRow: ", indexPath.row)
let cell = tableView.dequeueReusableCellWithIdentifier("ImageCardViewCell") as! NewsImageCardViewCell
let item: NewsItem = newsItems[indexPath.row]
getImageCardView(item.url, btnDate: item.dateString, textTitle: item.title, textDetail: item.message, imageCardView: cell.imageCardView, imageName: "news_1", indexPath: indexPath)
return cell
}
}
extension NewsTableViewController : UITableViewDelegate{
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
As you can see: The UITableView
is correctly setup by setting the dataSource
and delegate
to my class. The reloadData()
method is called on the main thread. Following the log-output:
Item count: 1
cellForRowAtIndexPath called with indexPathRow: 0
Network request finished - call reloadData()
Item count: 72
Note: At first there's one dummy item my array just to show you that cellForRowAtIndexPath
is indeed called but only one time. After triggering reloadData()
on numberOfRowsInSection
is called but not the cellForRowAtIndexPath method.
I know that there're a lot of similar issues like this and I've checked them all for possible solutions but none were working. I appreciate any help.
Please note that the dummy view which is added before the network request is visible. So the UITableView
s' height is not 0.
Thanks to everyone for your answers. I've found the issue. I've instantiated the ViewController
via the Storyboard
but I missed to set an IBOutlet
. Due that the bounds of my UITableView
were 0,0,0,0.
That because your table view did not add to your window, If the table view is not visible, the UIKit will not deal with UI related methods. It's kind of Apple's lazy load
.
Change your prepareTableView
function as below:
private func prepareTableView() {
tableView = UITableView(frame: self.view.bounds, style: .Plain)
tableView.dataSource = self
tableView.delegate = self
tableView.separatorColor = UIColor.clearColor()
self.view.addSubview(tableView)
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With