I am trying to fetch some data from stack exchange api using alamofire and swifty json. I am able to print the required data in the log, but when i run the app the simulator shows only empty cells. I checked the identifier and i have set the prototype cell value to 1.`
class MainTableViewController: UITableViewController,UISearchResultsUpdating {
var searchKeyword: String = "questions"
// empty array to store the search results
var searchResults: [SearchResult] = []
func alamofireFunction() {
Alamofire.request(.GET, "https://api.stackexchange.com/2.2/questions?=%20\(searchKeyword)%20viewpage=1&fromdate=1183075200&todate=2554416000&order=asc&sort=activity&tagged=ios&site=stackoverflow").responseJSON { (response) -> Void in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
for (var idx=0; idx<=json["items"].count; idx++) {
let result = SearchResult()
//print(json["items"][idx]["title"].stringValue)
result.name = json["items"][idx]["owner"]["display_name"].stringValue
result.question = json["items"][idx]["title"].stringValue
result.image = json["items"][idx]["owner"]["profile_image"].stringValue
self.searchResults.append(result)
}
}
case .Failure:
print("error")
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
alamofireFunction()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! MainTableViewCell
cell.questionLabel.text = searchResults[indexPath.row].question
cell.nameLabel.text = searchResults[indexPath.row].name
return cell
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return searchResults.count
}`
You must call self.reloadData() when your data source changes. This will cause tableView to call dataSource methods.
This is because you are using a request from Url, this process executes on a thread, so when you fetch your data in this way, you must call tableView.reloadData() to let know to the data source that the process have finished
Related
So, I have method loadData() which download datas from parse.com
And I should present all images show in table view.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ReusableCell", forIndexPath: indexPath) as! LeaguesTableViewCell
loadData { (success) in
if success {
cell.leagueImage.image = UIImage(data: self.leaguesImage[indexPath.row])
cell.leagueNameLabel.text = self.leagues[indexPath.row]["name"] as? String
} else {
cell.leagueNameLabel.text = "Wait"
}
}
return cell
}
Its didn't work. I call my function in viewDidLoad() but its not correct too, table view is empty.
Cuz my array is empty
My
The basic procedure for loading data into a UITableView is:
Load the data
Reload the table view
Return the number of sections in numberOfSectionsInTableView: method: In your case there is only 1 section.
Return the number of rows in tableView:numberOfRowsInSection:: In your case return the number of leagues if the data is loaded. If the data is not loaded then return 1 so that the table view has at least one row to display the "Wait" message.
Create and populate the cells from the data: Use leagues and leaguesImage.
Example:
private var loaded = false
override func viewDidLoad() {
super.viewDidLoad()
loaded = false
loadData() { success in
NSOperationQueue.mainQueue().addOperationWithBlock() {
self.loaded = success
self.tableView.reloadData()
}
}
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection: Int) -> Int {
if loaded {
return leagues.count
}
else {
return 1
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ReusableCell", forIndexPath: indexPath) as! LeaguesTableViewCell
if loaded {
cell.leagueImage.image = UIImage(data: self.leaguesImage[indexPath.row])
cell.leagueNameLabel.text = self.leagues[indexPath.row]["name"] as? String
}
else {
cell.leagueNameLabel.text = "Wait"
}
return cell
}
Try to set delegate and datasource first. If you have separate datasource other than view controller, retain it otherwise you will not get any callback.
I m trying to populate my tableview with the json data that i m getting on url using swiftyjson .The problem i m facing is , i m apprehending the city in the array but when i use it on the table view the data does not show .How can i fix it ?(you could check the data structure of my json by clicking on the url ).
import UIKit
import SwiftyJSON
import Alamofire
class ViewController: UIViewController , UITableViewDelegate ,UITableViewDataSource {
#IBOutlet var tableview: UITableView!
var data = [String]()
var numberofRows = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
Alamofire.request(.GET, "http://android.goidx.com/search")
.responseJSON {( response) -> Void in
if let value = response.result.value {
let json = JSON(value)
for (index,json):(String, JSON) in json {
//Do something you want
self.numberofRows = json["city"].count
let city = json["city"].string! as String
self.data.append(city)
print(json["city"].stringValue)
}
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numberofRows
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell" , forIndexPath: indexPath) as UITableViewCell
if data.count != 0 {
cell.textLabel?.text = data[indexPath.row]
}
return cell
}
}
After you create your array of cities, you need to reload the table view to refresh the contents
tableView.reloadData()
Also change your datasource, numberOfRowsInSection method to return
self.data.count
I noticed that the cities key in the json returned does not map to an array.
I have created a tableview. Then calling an url to get the data and accordingly loading the tableview. But whenever i am clicking a cell the data is disappearing.
I have tried with making userinteractionenabled as false or the selection style as .None. Still it is not working. Any reason for this?
class CheckInTableViewController: UITableViewController {
var flightInfo : [Flight]!
var multipleChoiceQuestion : [MultipleChoiceQuestion]!
var question : [String] = [String]()
var answer : [[String]] = [[String]]()
var correctAnswer: [Int] = [Int]()
override func viewDidLoad() {
super.viewDidLoad()
loadData()
}
func loadData(){
Request.CheckInFlight().execute().validate().responseJSON { (request, _, data, error)
-> Void in
if error != nil {
print("error")
}
else{
self.flightInfo = Response.flightsFromJSON(data)
self.multipleChoiceQuestion = self.flightInfo[0].checkInUpdate.checkInTest.multipleChoiceQuestion
for questionNew in self.multipleChoiceQuestion {
self.question.append(questionNew.question)
self.answer.append(questionNew.answerArray)
self.correctAnswer.append(questionNew.correctAnswerId)
}
self.tableView.reloadData()
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
if flightInfo != nil {
return flightInfo.count + 1
}
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = UITableViewCell()
switch indexPath.row {
case 0: _ = tableView.dequeueReusableCellWithIdentifier("headercell", forIndexPath: indexPath) as! CheckInHeaderTableViewCell
default:
let cell = tableView.dequeueReusableCellWithIdentifier("datacell", forIndexPath: indexPath) as! CheckInTableViewCell
cell.flightNumber.text = flightInfo[indexPath.row - 1].fullFlightId
cell.departureCity.text = flightInfo[indexPath.row - 1].departureInfo!.airport.iataCode
cell.departureDate.text = dateFormatter(flightInfo[indexPath.row - 1].departureInfo!.scheduledDateTime)
cell.departureTime.text = flightInfo[indexPath.row - 1].departureInfo!.scheduledDateTime.flightTimeString()
cell.arrivalCity.text = flightInfo[indexPath.row - 1].arrivalInfo!.airport.iataCode
cell.arrivalDate.text = dateFormatter(flightInfo[indexPath.row - 1].arrivalInfo!.scheduledDateTime)
cell.arrivalTime.text = flightInfo[indexPath.row - 1].arrivalInfo!.scheduledDateTime.flightTimeString()
}
return cell
}
Just to round this up, I'm turning my comment into an answer.
You are returning the cell from the first line. That is a fresh cell.
The dequeue'd cell you are modifying and throwing away w/o return in the switch.
The dequeue in case 0 you are throwing away instantly.
This should give you a warning regarding scope ambiguity on the second let cell =, btw.
If the problem persists, please update your question and let me know:)
He everyone,
Im pulling my hears out for a whole day for the following issue. My back-end is in Parse and i am doing a query on my table "events" in a UITableViewController. The problem is that the query returns the complete data in the ViewDidLoad but not in my tableView method. In my tableView im only getting 3 items returned. Im aware of that parse query doing a Asynchronously call but why its returning 3 items?
I would be gratefull if somebody can help me out here.
Here is my code:
class EventOverViewController: UITableViewController {
var events:Array = [AnyObject]();
var imageContainer : UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.None;
self.retrieveInfoFromParse();
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return self.events.count
}
func queryForTable() -> PFQuery {
let getEvents = PFQuery(className:"Event");
return getEvents;
}
func retrieveInfoFromParse(){
self.queryForTable().findObjectsInBackgroundWithBlock { (objects:[PFObject]?, error:NSError?) -> Void in
if error == nil {
for object in objects! {
self.events.append(object);
}
//RETURNING 6 ITEMS
print(self.events);
self.tableView.reloadData();
}
}
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 230;
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("EventCell", forIndexPath:indexPath) as! EventTableViewCell
let eventData = self.events[indexPath.row];
//ONLY returning 3 ITEMS, WHY?
print(eventData);
return cell
}
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let indexPath: NSIndexPath = self.tableView.indexPathForSelectedRow!
let destinationVC = segue.destinationViewController as! RootMainViewController
var secondEventData : Event!
secondEventData = self.events[indexPath.row] as! Event;
destinationVC.title = secondEventData.eventName;
destinationVC.event = secondEventData;
}
}
I need to know why my AllNews:NSMutableArray is empty when i try to call it inside the Tableviewcell.
class NewsTableViewController: UITableViewController {
var AllNews:NSMutableArray! = NSMutableArray()
var myEditImage = UIImage(named: "create_new-32.png")
func gotoCompose () {
self.performSegueWithIdentifier("gotoCompose", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
//Getting the latest 5 news from the parse.com
var getNews = PFQuery(className: "News")
getNews.orderByDescending("CreatedAt")
getNews.limit = 5
getNews.findObjectsInBackgroundWithBlock {
(objects:[AnyObject]!, error:NSError!)->Void in
if error == nil{
for object in objects {
let news:PFObject = object as PFObject
self.AllNews.addObject(news)
//tableView.reloadData()
//println(object)
}
let array:NSArray = self.AllNews.reverseObjectEnumerator().allObjects
self.AllNews = NSMutableArray(array: array)
self.tableView.reloadData()
}
}
var homeButton: UIBarButtonItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Compose, target: self, action: Selector("gotoCompose"))
self.navigationItem.rightBarButtonItem = homeButton
}
override func viewDidAppear(animated: Bool) {
self.tableView.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete method implementation.
// Return the number of rows in the section.
return 5
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
// #warning Potentially incomplete method implementation.
// Return the number of sections.
return 1
}
//
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("newsCell", forIndexPath: indexPath) as NewsTableViewCell
let herzNews:PFObject = self.AllNews.objectAtIndex(indexPath.row) as PFObject
var user = herzNews.objectForKey("newser") as? String
var content = herzNews.objectForKey("content") as? String
cell.userLabel.text = user!
cell.newsTextView.text = content!
return cell
}
}
The error i get is
[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
*** First throw call stack:
The problem: in the viewDidLoad, you start a download, and when the download is finished, then you add objects to AllNews (which is a bad name, don't start with a capital). But before the download is finished, the cellForRowAtIndexPath is called. And you hardcoded the value 5 as the number of rows, so it expects an array with 5 fields, but when it is called, your array is empty. If you use AllNews.count insted of 5, it will be good.