I have trouble in loading the table view when parsing json files in swift.
Parsing the data is doing well. But no data are displayed in the table view.
This is the code :
import UIKit
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet weak var redditListTableView: UITableView!
var tableData = []
#IBAction func cancel(sender: AnyObject) {
self.dismissViewControllerAnimated(false, completion: nil)
println("cancel")
}
#IBAction func done(sender: AnyObject) {
println("done")
}
override func viewDidLoad() {
super.viewDidLoad()
searchJsonFile("blabla.json")
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
println(tableData.count)
return tableData.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: "MyTestCell")
let rowData: NSString = self.tableData[indexPath.row] as NSString
cell.textLabel.text = rowData as String
return cell
}
func searchJsonFile(searchFile: String) {
let urlPath = "http://data.../\(searchFile)"
let url = NSURL(string: urlPath)
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url!, completionHandler: {data, response, error -> Void in
println("Task completed")
if(error != nil) {
// If there is an error in the web request, print it to the console
println(error.localizedDescription)
}
var err: NSError?
var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err) as NSDictionary
if(err != nil) {
println("JSON Error \(err!.localizedDescription)")
}
var results = [String]()
if let results1 = jsonResult["data"] as? NSDictionary{
for (key, value) in results1 {
if let eng = value["eng"] as? NSDictionary {
if let name = eng["name"] as? NSString{
results.append(name)
}
}
}
}
//println(results) OK!!!!
dispatch_async(dispatch_get_main_queue(), {
self.tableData = results
self.redditListTableView.reloadData()
})
})
task.resume()
}
}
You are returning 0 from numberOfSectionsInTableView - so you get no data displayed. You want 1 section -
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
If you are not having sections then just remove this function or comment
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 0
}
or else return 1
Related
i have one table view with two labels. I need to display the data which are coming from json. But now its not showing any data in table view:
import UIKit
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate
{
let yourJsonFormat: String = "JSONFile" // set text JSONFile : json data from file
// set text JSONUrl : json data from web url
var arrDict :NSMutableArray=[]
#IBOutlet weak var tvJSON: UITableView!
override func viewDidLoad()
{
super.viewDidLoad()
if yourJsonFormat == "JSONFile" {
jsonParsingFromFile()
} else {
jsonParsingFromURL()
}
}
func jsonParsingFromURL () {
let url = NSURL(string: "url")
let request = NSURLRequest(URL: url!)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {(response, data, error) in
}
}
func jsonParsingFromFile()
{
let path: NSString = NSBundle.mainBundle().pathForResource("days", ofType: "json")!
let data : NSData = try! NSData(contentsOfFile: path as String, options: NSDataReadingOptions.DataReadingMapped)
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return arrDict.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell : TableViewCell! = tableView.dequeueReusableCellWithIdentifier("Cell") as! TableViewCell
let strTitle : NSString=arrDict[indexPath.row] .valueForKey("name") as! NSString
let strDescription : NSString=arrDict[indexPath.row] .valueForKey("rating") as! NSString
cell.lblTitle.text=strTitle as String
cell.lbDetails.text=strDescription as String
return cell as TableViewCell
}
}
Any thing i missed,please help me out.
I am not able to see any data in my table view...
your code is partially correct, I followed your question
Step-1
Right click on the info.plist file, select open as, Source code. Add the lines of code that allow the http connection to this server.
do like
Step-2
For Server request
sendAsynchronousRequest is deprecated in this place use
func jsonParsingFromURL () {
let url = NSURL(string: "url")
let session = NSURLSession.sharedSession()
let request = NSURLRequest(URL: url!)
let dataTask = session.dataTaskWithRequest(request) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
print("done, error: \(error)")
let dict: NSDictionary!=(try! NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers)) as! NSDictionary
arrDict.addObject((dict.valueForKey("xxxx")
tvJSON .reloadData()
}
dataTask.resume()
}
For local Request
func jsonParsingFromFile()
{
let path: NSString = NSBundle.mainBundle().pathForResource("days", ofType: "json")!
let data : NSData = try! NSData(contentsOfFile: path as String, options: NSDataReadingOptions.DataReadingMapped)
let dict: NSDictionary!=(try! NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers)) as! NSDictionary
arrDict.addObject((dict.valueForKey("xxxx")
tvJSON .reloadData()
}
Update and Edit
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet var showtable: UITableView!
var arrDict :NSMutableArray=[]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.jsonParsingFromURL()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func jsonParsingFromURL () {
let url = NSURL(string: "http://kirisoft.limitscale.com/GetVendor.php?category_id=1")
let session = NSURLSession.sharedSession()
let request = NSURLRequest(URL: url!)
let dataTask = session.dataTaskWithRequest(request) { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
print("done, error: \(error)")
if error == nil
{
self.arrDict=(try! NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)) as! NSMutableArray
print(self.arrDict)
if (self.arrDict.count>0)
{
self.showtable.reloadData()
}
// arrDict.addObject((dict.valueForKey("xxxx")
}
}
dataTask.resume()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int
{
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return arrDict.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let CellIdentifier: String = "cell"
var cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier) as UITableViewCell!
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Subtitle, reuseIdentifier: CellIdentifier)
}
cell?.textLabel!.text=arrDict[indexPath.row] .valueForKey("name") as? String
cell?.detailTextLabel!.text=arrDict[indexPath.row] .valueForKey("rating") as? String
return cell!
}
}
you can get the output like
For sample Project
I am trying to use youtube api in ios swift, and following this tutorial http://www.appcoda.com/youtube-api-ios-tutorial/, but some how my didSelectRowAtIndexPath method is never being called.
Any suggestions will be helpful. Thanks
import UIKit
class SearchVideosViewController: UIViewController, UITableViewDataSource,UITableViewDelegate , UITextFieldDelegate{
#IBOutlet weak var wait: UIView!
#IBOutlet weak var tblShowVideoList: UITableView!
#IBOutlet weak var searchVideoText: UITextField!
var selectedVideoIndex:Int!
var videosArray: Array<Dictionary<NSObject,AnyObject>> = []
var apiKey = "my_api_key"
override func viewDidLoad() {
super.viewDidLoad()
searchVideoText.delegate = self
tblShowVideoList.delegate = self
tblShowVideoList.dataSource = self
wait.hidden = true
// Do any additional setup after loading the view.
}
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 videosArray.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell!
cell = tableView.dequeueReusableCellWithIdentifier("videolistcell", forIndexPath: indexPath)
let videoTitle = cell.viewWithTag(10) as! UILabel
let videoThumbnail = cell.viewWithTag(11) as! UIImageView
let videoDetails = videosArray[indexPath.row]
videoTitle.text = videoDetails["title"] as? String
videoThumbnail.image = UIImage(data: NSData(contentsOfURL: NSURL(string: (videoDetails["thumbnail"] as? String)!)!)!)
return cell
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 140.0
}
// MARK: UITextFieldDelegate method implementation
func textFieldShouldReturn(textField: UITextField) -> Bool {
textField.resignFirstResponder()
wait.hidden = false
let type = "video"
// Form the request URL string.
var urlString = "https://www.googleapis.com/youtube/v3/search?part=snippet&q=\(textField.text)&type=\(type)&key=\(apiKey)"
urlString = urlString.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())!
// Create a NSURL object based on the above string.
let targetURL = NSURL(string: urlString)
// Get the results.
performGetRequest(targetURL, completion: { (data, HTTPStatusCode, error) -> Void in
if HTTPStatusCode == 200 && error == nil {
// Convert the JSON data to a dictionary object.
do {
let resultsDict = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as! Dictionary<NSObject, AnyObject>
// Get all search result items ("items" array).
let items: Array<Dictionary<NSObject, AnyObject>> = resultsDict["items"] as! Array<Dictionary<NSObject, AnyObject>>
// Loop through all search results and keep just the necessary data.
for var i=0; i<items.count; ++i {
let snippetDict = items[i]["snippet"] as! Dictionary<NSObject, AnyObject>
// Gather the proper data depending on whether we're searching for channels or for videos.
// Create a new dictionary to store the video details.
var videoDetailsDict = Dictionary<NSObject, AnyObject>()
videoDetailsDict["title"] = snippetDict["title"]
videoDetailsDict["thumbnail"] = ((snippetDict["thumbnails"] as! Dictionary<NSObject, AnyObject>)["default"] as! Dictionary<NSObject, AnyObject>)["url"]
videoDetailsDict["videoID"] = (items[i]["id"] as! Dictionary<NSObject, AnyObject>)["videoId"]
// Append the desiredPlaylistItemDataDict dictionary to the videos array.
self.videosArray.append(videoDetailsDict)
// Reload the tableview.
self.tblShowVideoList.reloadData()
}
} catch {
print(error)
}
}
else {
print("HTTP Status Code = \(HTTPStatusCode)")
print("Error while loading channel videos: \(error)")
}
// Hide the activity indicator.
self.wait.hidden = true
})
return true
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("Selected row index \(indexPath.row)")
selectedVideoIndex = indexPath.row
performSegueWithIdentifier("playVideo", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "playVideo" {
let videosPlayerViewController = segue.destinationViewController as! VideosPlayerViewController
videosPlayerViewController.videoID = videosArray[selectedVideoIndex]["videoId"] as! String
}
}
// MARK: Custom method implementation
func performGetRequest(targetURL: NSURL!, completion: (data: NSData?, HTTPStatusCode: Int, error: NSError?) -> Void) {
let request = NSMutableURLRequest(URL: targetURL)
request.HTTPMethod = "GET"
let sessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: sessionConfiguration)
let task = session.dataTaskWithRequest(request, completionHandler: { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in
dispatch_async(dispatch_get_main_queue(), { () -> Void in
completion(data: data, HTTPStatusCode: (response as! NSHTTPURLResponse).statusCode, error: error)
})
})
task.resume()
}
}
Try comments on:
searchVideoText.delegate = self
I have async request to HTTP, i want to read JSON and fill my viewtable.
I get data with request, i make NSArray, but i can pass it inside my functions, tableView numberOfRowsInSection return only 1, please help.
import Foundation
import UIKit
class ThirdView : UITableViewController {
var jsonz:NSArray = ["Ray Wenderlich"];
let url = NSURL(string: "http://iweddings.ru/xmlrestaurant.json");
override func viewDidLoad() {
super.viewDidLoad()
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
let json = NSJSONSerialization.JSONObjectWithData(data!, options: nil, error: nil) as! NSArray
println(json)
// here i see in xCode output
// price = 4500;
// rating = 45;
// slogan = "\U041d\U0435\U043b\U0435\U0433\U0430\U043b\U044c\U043d\U043e";
// status = 1;
// type = 1;
// etc....
self.jsonz = json;
}
task.resume()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1;
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
println(self.jsonz.count);
return self.jsonz.count;
// here i see always "1" ???? why?
}
NSArray jsonz does not change.
Sorry for my english.
You need to call reloadData() method after json data is downloaded:
class ThirdView: UITableViewController {
var jsonz: NSArray = ["Ray Wenderlich"]
let url = NSURL(string: "http://iweddings.ru/xmlrestaurant.json")
override func viewDidLoad() {
super.viewDidLoad()
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {(data, response, error) in
let json = NSJSONSerialization.JSONObjectWithData(data!, options: nil, error: nil) as! NSArray
println(json)
self.jsonz = json;
self.tableView.reloadData()
}
task.resume()
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1;
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
println(self.jsonz.count);
return self.jsonz.count;
}
}
I'm creating an app for iOS that get data from my server with json and store it on a tableview; with this no problems, my data are simple notes, some notes are linked together forming projects (simple dependency_id on my database sql), my question is: How can i group my notes by project, like a contact list? (ex. http://img.wonderhowto.com/img/13/66/63535060544981/0/siri-exploit-you-could-bypass-iphones-lock-screen-call-message-any-contact-ios-7-1-1.w654.jpg)
This is the source that populate the table with all notes:
//
// TableController.swift
// uitableview_load_data_from_json
import UIKit
class TableController: UITableViewController {
var TableData:Array< String > = Array < String >()
var userid = NSUserDefaults.standardUserDefaults().stringForKey("userid")!
override func viewDidLoad() {
super.viewDidLoad()
get_data_from_url("http:/localhost/index.php/iOS_getNomenTasks?n=" + userid)
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return TableData.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = TableData[indexPath.row]
return cell
}
func get_data_from_url(url:String)
{
let httpMethod = "GET"
let timeout = 15
let url = NSURL(string: url)
let urlRequest = NSMutableURLRequest(URL: url!,
cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData,
timeoutInterval: 15.0)
let queue = NSOperationQueue()
NSURLConnection.sendAsynchronousRequest(
urlRequest,
queue: queue,
completionHandler: {(response: NSURLResponse!,
data: NSData!,
error: NSError!) in
if data.length > 0 && error == nil{
let json = NSString(data: data, encoding: NSASCIIStringEncoding)
self.extract_json(json!)
}else if data.length == 0 && error == nil{
println("Nothing was downloaded")
} else if error != nil{
println("Error happened = \(error)")
}
}
)
}
func extract_json(data:NSString)
{
var parseError: NSError?
let jsonData:NSData = data.dataUsingEncoding(NSASCIIStringEncoding)!
let json: AnyObject? = NSJSONSerialization.JSONObjectWithData(jsonData, options: nil, error: &parseError)
if (parseError == nil)
{
if let task_list = json as? NSArray
{
for (var i = 0; i < task_list.count ; i++ )
{
if let tasj_obj = task_list[i] as? NSDictionary
{
if let task_id = tasj_obj["id"] as? String
{
if let task_name = tasj_obj["tk_title"] as? String
{
if let task_type = tasj_obj["tk_type"] as? String
{
TableData.append(task_name)
}
}
}
}
}
}
}
do_table_refresh();
}
func do_table_refresh()
{
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
return
})
}
}
ok..
task_id is the note id,
task_name is the note name,
task_type is the value that identify if note is a project or not, if task_type is 0, the note is a simple note, if task_type is 1 the note is a project.
If you create an UITableViewController, you have the function :
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
With it, you have 3 sections who contains 2 lines :
var tab: [String] = ["section 1", "section 2", "section 3"]
var tabData: [AnyObject] = [["item1", "item2"],["item1", "item2"],["item1", "item2"]]
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return tab.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.dataTab[section].count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell: UITableViewCell = UITableViewCell()
return cell
}
Below is my ViewController code. The println in GetRequest prints the correct data that it receives from the HTTP GET request. At this point, tableData has 10 key-value pairs. However, if I put a break point after the call to GetRequest() in viewDidLoad(), tableData is empty and nothing is displayed in the tableView. Why is this? Where am I going wrong?
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
{
#IBOutlet var tableView: UITableView!
var tableData: [String:String] = [:]
let textCellIdentifier = "TextCell"
func GetRequest(urlPath: String)
{
var LatestWaitTimes: [String:String] = [:]
let url: NSURL = NSURL(string: urlPath)!
let session = NSURLSession.sharedSession()
let task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
if error != nil {
// If there is an error in the web request, print it to the console
println(error.localizedDescription)
}
var err: NSError?
var jsonResult: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers, error: &err)
if err != nil {
// If there is an error parsing JSON, print it to the console
println("JSON Error \(err!.localizedDescription)")
}
let json = JSON(jsonResult!)
let count: Int? = json.array?.count
if let ct = count {
for index in 0...ct-1 {
let name = json[index]["CrossingName"].string
var wait = json[index]["WaitTime"].stringValue
if (wait == "-1")
{
wait = "No Info"
}
else
{
wait += " min"
}
println(name!+": "+wait)
LatestWaitTimes[json[index]["CrossingName"].stringValue] = wait as String?
}
}
self.tableData = LatestWaitTimes
})
task.resume()
}
override func viewDidLoad() {
super.viewDidLoad()
var apiInfo = GetWaitTimes()
GetRequest(apiInfo.BorderCrossingApi+"?AccessCode="+apiInfo.AccessCode)
self.tableView.delegate = self
self.tableView.dataSource = self
tableView.reloadData()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1;
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier(self.textCellIdentifier) as! UITableViewCell
let thisEntry = self.tableData.values.array[indexPath.row]
cell.textLabel?.text = thisEntry+": "+tableData[thisEntry]!
return cell
}
func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
}
The problem is that GetRequest runs asynchronously. So you have to reloadData inside the completionHandler of dataTaskWithURL:
let task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
// do all of your existing stuff here
dispatch_async(dispatch_get_main_queue()) {
self.tableData = LatestWaitTimes
self.tableView.reloadData()
}
})
task.resume()
You can remove the reloadData from within viewDidLoad.
Rearrange the orders of the method calls:
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
var apiInfo = GetWaitTimes()
GetRequest(apiInfo.BorderCrossingApi+"?AccessCode="+apiInfo.AccessCode)
tableView.reloadData()
}
Explanation: you set the delegate and dataSource before you GetRequest() so the dataSource won't be nil.
Try this it may help you
you can add a callback (for reload tablview) in GetRequest function and run the callback after parser json in completionHandler
Maybe When you set the delegate with tableview, tableData still be nil (waitting for http response)
this is my code .you can refer to
demand.loadDataFromServer(self.view, done: { () -> Void in
self.demands = demand.getDemandDataList()
dispatch_async(dispatch_get_main_queue(), { () -> Void in
self.tableView.reloadData()
})
})
func loadDataFromServer(view:UIView,done:(() -> Void)!){
var request:HttpRequest = HttpRequest(view:view)
request.GET(getDemandListURL, parameters: nil, success: { (dict) -> Void in
self.demandLists = dict["data"] as NSMutableArray
done()
}, failed: { (dict) -> Void in
}) { (error) -> Void in
}
}