Hi I am a little new to Swift and tableviews I am working on a final project at school and I am using Alamofire to make my request and SwiftyJSON to parse through my JSON. I want to store some data that is in a [[String:String]] into my tableview cell. I keep on getting this error and can't not figure out, If anyone can point me in the right direction I would appreciate it.
var items = [[String: String]]()
var regions = ["NA", "EUW", "EUNE", "BR", "KR", "LAN", "LAS", "OCE", "RU","TR"]
override func viewDidLoad() {
super.viewDidLoad()
let pickerView = UIPickerView()
pickerView.delegate = self
pickerView.selectRow(0, inComponent: 0, animated: true)
regionPicker.inputView = pickerView
regionPicker.text = regions[0];
search.backgroundColor = UIColor.blackColor();
self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
loadData("maj0r Lee Hung")
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
cell.textLabel?.text = items[indexPath.row]
return cell
}
func loadData(name: String){
let escapedName = name.stringByAddingPercentEncodingWithAllowedCharacters(.URLHostAllowedCharacterSet())
let url = "https://na.api.pvp.net/api/lol/na/v1.4/summoner/by-name/\(escapedName!)"
Alamofire.request(.GET, url , parameters: [ "api_key":"BLAHBLAHBLAH" ])
.responseJSON { response in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
print(json)
for (key: _, subJson: json) in json {
let id = json["id"].stringValue
let name = json["name"].stringValue
let iconID = json["profileIconId"].stringValue
let obj = ["id": id, "name": name, "iconID": iconID]
self.items.append(obj)
self.tableView.reloadData()
}
}
case .Failure(let error):
print(error)
}
}
}
In your code
cell.textLabel?.text = items[indexPath.row]
The text is expecting a string, but you are passing a dictionary. You need to take the items[indexPath.row] and extract an individual string from it.
Related
I am trying to retrieve data from my site, I am using Alamofire, how can I put that data into an array that I can use to populate my table view?
override func viewDidLoad() {
super.viewDidLoad()
Alamofire.request("http://lytestech.ga/api/lytes/get_movies/").responseJSON { response in
if let json = response.result.value {
print("JSON: \(json)") // serialized json response
let res = json as! NSDictionary
let movies = res["movies"] as! NSArray
// movieTitles = movies["movie_desc"]
let movieTitles: [String] = movies["movietitile"] as! String
print (movies)
print (movieTitles)
}
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
print("Data: \(utf8Text)") // original server data as UTF8 string
}
}
}
json data
JSON: {
movies = (
{
id = 66;
"movie_desc" = "spiders bite";
movietitile = spiderman;
},
{
id = 64;
"movie_desc" = horror;
movietitile = mummy;
}
);
status = ok;
}
(
{
id = 66;
"movie_desc" = "spiders bite";
movietitile = spiderman;
},
{
id = 64;
"movie_desc" = horror;
movietitile = mummy;
}
)
Store movies in movies NSArray
var movies = NSArray()
After that in cellForRowAt method you can display data like this.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "Identifier") as! YouCustomCell
let movieDetail = movies[indexPath.row] as! NSDictionary
cell.lblMovieName.text = movieDetail.value(forKey: "movietitile") as? String
return cell
}
Note: - This is just code skeleton, you can use as per your custom cell and Outlets
var movies:[Dictionary<String,AnyObject>] = [] // Makes movies array global
movies = res["movies"] // and tableview reload
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let identifier = "cell"
let cell = tableView.dequeueReusableCell(withIdentifier: identifier) ??
UITableViewCell(style: .default, reuseIdentifier: identifier)
cell.textLabel!.text = movies[indexPath.row]["movietitile"] as? String
return cell
}
func demo()
{
let str : String = "http://lytestech.ga/api/lytes/get_movies/"
let url = NSURL(string:str)
let request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
Alamofire.request(request)
.responseString { response in
switch (response.result) {
case .Success(let JSON):
let data = JSON.dataUsingEncoding(NSUTF8StringEncoding)!
do {
let responseString = try NSJSONSerialization.JSONObjectWithData(data, options: []) as? [String:AnyObject]
// print(responseString!)
self.movieName = []
self.desc = []
let arr = responseString!["movies"] as! NSArray
for j in 0..<arr.count{
let dic = arr[j] as! NSMutableDictionary
self.movieName.addObject(dic.valueForKey("movietitile")!)
self.desc.addObject(dic.valueForKey("movie_desc")!)
}
self.removeIndicator()
self.contactTable.reloadData()
} catch _ as NSError {
//print(error)
}
break
case .Failure:
print("FAILURE")
self.removeIndicator()
break
}
}
}
Convert your response Data into Dictionary
let dictionary: Dictionary? = NSKeyedUnarchiver.unarchiveObject(with: response.data) as! [String : Any]
Extract your Array from Dictionary , there is key name movies
if let arryMovies1 = dictionary["movies"] as? [[String:Any]] {
print (arryMovies1);
// Now your have your Array
// You can Populate into UItableView
// when your array is modified than you have to reload the tableData
self.arryMovies=arryMovies1
self.tableView.reloadData()
}
In your cellForRowAtIndexPath for populating in list view
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "you_cell_identifre") as! UITableCell
let dicMovie = self.arryMovies[indexPath.row] as! NSDictionary
cell.lableTitle.text = dicMovie.value(forKey: "movietitile") as? String
return cell
}
I hope this will help you
I am using Alamofire and trying to fetch data on my tableview, however I am not able to get the data. When I use the cmd Print, its showing me the data but not able to fetch the data. How can I fetch the data on my tableview?
Please find the code below:-
import UIKit
import Alamofire
import SwiftyJSON
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, NSURLConnectionDelegate {
//let myarray = ["item1", "item2", "item3"]
var tableData = Array<Group>()
var arrRes = [[String:AnyObject]]() //Array of dictionary
var group = [Group]()
#IBOutlet weak var tableview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
loadGroups()
}
func loadGroups(){
let testhappyhour:Group = Group(tempName: "TEST", tempID: "TESST", icons: "TEST", tempgbcount: "TEST")
self.group.append(testhappyhour)
//let groupQuery:String = "http://jsonplaceholder.typicode.com/users"
Alamofire.request("http://jsonplaceholder.typicode.com/users").responseJSON
{ response in switch response.result {
case .success(let JSON):
let response = JSON as! NSArray
for item in response { // loop through data items
let obj = item as! NSDictionary
let happyhour = Group(tempName:obj["NAME"] as! String, tempID:obj["id"] as! String, icons:obj["icon"] as! String, tempgbcount:obj["TOTAL"] as! String)
self.group.append(happyhour)
}
self.tableview.reloadData()
case .failure(let error):
print("Request failed with error: \(error)")
}
}
}
func convertToArray(text: String) -> [Any]? {
if let data = text.data(using: .utf8) {
do {
return try JSONSerialization.jsonObject(with: data, options: []) as? [Any]
} catch {
print(error.localizedDescription)
}
}
return nil
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
tableview.reloadData()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//return myarray.count
return arrRes.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//let cell = tableView.dequeueReusableCell(withIdentifier: "groupCell", for: indexPath) as! UITableViewCell
// cell.textLabel?.text = myarray[indexPath.item]
let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "groupCell")!
var dict = arrRes[indexPath.row]
cell.textLabel?.text = dict["NAME"] as? String
cell.detailTextLabel?.text = dict["TOTAL"] as? String
return cell
}
}
Thank you!!
Need to change loadGroups function like this
func loadGroups(){
let testhappyhour:Group = Group(tempName: "TEST", tempID: "TESST", icons: "TEST", tempgbcount: "TEST")
self.group.append(testhappyhour)
Alamofire.request("http://jsonplaceholder.typicode.com/users").responseJSON
{ response in switch response.result {
case .success(let JSON):
let response = JSON as! NSArray
for item in response { // loop through data items
let obj = item as! NSDictionary
let happyhour = Group(tempName:obj["NAME"] as! String, tempID:obj["id"] as! String, icons:obj["icon"] as! String, tempgbcount:obj["TOTAL"] as! String)
self.group.append(happyhour)
self.arrRes.append(obj) // ADD THIS LINE
}
self.tableview.reloadData()
case .failure(let error):
print("Request failed with error: \(error)")
}
}
}
Array 'group' is appended with the Alamofire responses, but Array 'arrRes' is used as the table view data source. If you use self.group instead of arrRes in the data source methods, the table should update with the new groups received in the Alamofire response.
So I'm trying to parse some JSON data retrieved from a server and display it nicely in a table, ive followed the suggestions here: UITableView example for Swift and managed to get the example working.
However with the data im parsing the table remains blank.
Can anyone see where im going wrong?
import UIKit
import SwiftyJSON
class LogsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
let animals: [String] = ["Horse", "Cow", "Camel", "Sheep", "Goat"]
var arrayCount:Int = 0
struct Item {
let name : String
let lockTime : String
let type : String
}
// cell reuse id (cells that scroll out of view can be reused)
let cellReuseIdentifier = "cell"
var items = [Item]()
#IBOutlet weak var textUodate: UIStackView!
override func viewDidLoad() {
super.viewDidLoad()
// Register the table view cell class and its reuse id
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellReuseIdentifier)
tableView.delegate = self
tableView.dataSource = self
// Do any additional setup after loading the view.
let lockid = UserDefaults.standard.value(forKey: "LockID")!
// let email = UserDefaults.standard.value(forKey: "email")!
//get the data from the server for that specific lock id
let u = UserDefaults.standard.value(forKey: "userIP")!
var request = URLRequest(url: URL(string: "http://\(u):3000/logs")!)
request.httpMethod = "POST"
let postString = "LockID=\(lockid)"
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) { data, response, error in
guard let data = data, error == nil else { print("error=\(error)")
return
}
if let httpStatus = response as? HTTPURLResponse, httpStatus.statusCode != 200 { // check for http errors
print("statusCode should be 200, but is \(httpStatus.statusCode)")
print("response = \(response)")
print(response ?? " ")
}
let responseString = String(data: data, encoding: .utf8)
if let data = responseString?.data(using: String.Encoding.utf8) {
let resString = JSON(data: data)
if resString["success"].stringValue == "true"
{
self.arrayCount = (resString["message"].count)
print(self.arrayCount)
let returnedArray = resString["message"].arrayValue
for item in returnedArray {
let name = String(describing: item["name"])
let lockTime = String(describing: item["lockTime"])
let type = String(describing: item["type"])
self.items.append(Item(name:name, lockTime:lockTime, type:type))
}
}
else if resString["success"].stringValue == "false"
{
print(resString["success"].stringValue)
}
}
}
task.resume()
DispatchQueue.main.async{
self.tableView.reloadData()
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayCount
}
// create a cell for each table view row
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:UITableViewCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as UITableViewCell!
let item = items[indexPath.row]
let cellText = "\(item.name) \(item.type) At: \(item.lockTime) "
cell.textLabel?.text = cellText
print(cellText)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("You tapped cell number \(indexPath.row).")
}
Data is not displaying because you didn't reload the table view after you append the items array. Please reload the table view at the end of task closure
let task = URLSession.shared.dataTask(with: request) { data, response, error in
// ......
// ......
self.tableView.reloadData()
}
I have the following code.
import UIKit
import Alamofire
class CheHappyTableViewController: UITableViewController, NSURLConnectionDelegate {
var happyHours = [HappyHour]()
override func viewDidLoad() {
super.viewDidLoad()
//Load the cell elements
loadHappyHourElements()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loadHappyHourElements(){
let testhappyhour:HappyHour = HappyHour(title: "TEST", image: "TESST", description: "TEST", postedDate: "TEST")
self.happyHours.append(testhappyhour)
let url:String = "https://gist.githubusercontent.com/arianitp/036133ebb5af317a595c/raw/f134ec241ec3126bedd6debe5de371e3e01d225b/happyhours.json"
Alamofire.request(.GET, url, encoding:.JSON).responseJSON
{ response in switch response.result {
case .Success(let JSON):
let response = JSON as! NSArray
for item in response { // loop through data items
let obj = item as! NSDictionary
let happyhour = HappyHour(title:obj["title"] as! String, image:obj["image"] as! String, description:obj["description"] as! String, postedDate:obj["date"] as! String)
self.happyHours.append(happyhour)
}
case .Failure(let error):
print("Request failed with error: \(error)")
}
}
self.tableView.reloadData()
}
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 {
return happyHours.count
}
//Displays the cells in the table
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
self.tableView.rowHeight = UIScreen.mainScreen().bounds.size.width
let cellIdentifier = "CheHappyTableViewCellController"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! CheHappyTableViewCellController
let happyHour = happyHours[indexPath.row]
cell.lblTitle.text = happyHour.title
//cell.cheHappyImage = happyHour.photo
// Configure the cell...
return cell
}
}
The table cells don't get updated even though I included the self.tableView.reloadData() in the Alamofire request complete function. I have defined also one Sample Object with Title and all Properties set to "TEST", this does get loaded, however the JSON file doesn't populate the table. I can see the file is being downloaded correctly and read, but I think the elements are either not being added to the Property Variable happyHours or somehow the elements are not being reloaded.
I tried many solutions from here but without success. What am I doing wrong?
Your self.tableView.reloadData() line is outside the callback, meaning that it gets called straight away, before the data has been loaded. Try this:
func loadHappyHourElements(){
let testhappyhour:HappyHour = HappyHour(title: "TEST", image: "TESST", description: "TEST", postedDate: "TEST")
self.happyHours.append(testhappyhour)
let url:String = "https://gist.githubusercontent.com/arianitp/036133ebb5af317a595c/raw/f134ec241ec3126bedd6debe5de371e3e01d225b/happyhours.json"
Alamofire.request(.GET, url, encoding:.JSON).responseJSON
{ response in switch response.result {
case .Success(let JSON):
let response = JSON as! NSArray
for item in response { // loop through data items
let obj = item as! NSDictionary
let happyhour = HappyHour(title:obj["title"] as! String, image:obj["image"] as! String, description:obj["description"] as! String, postedDate:obj["date"] as! String)
self.happyHours.append(happyhour)
}
self.tableView.reloadData()
case .Failure(let error):
print("Request failed with error: \(error)")
}
}
}
Is it possible to assign two values to a cell in a UITableView?
I have a json file that is structured like this:
{
"band": [
"Name": "The Kooks",
"id": "1258"
]
}
I can get the label to display in the cell and pass it to a new view controller, but how do I also assign the id so that I can pass that too?
I am new to swift so please dont eat me.
Edit 1:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
cell.textLabel?.text = self.items[indexPath.row]
return cell
}
items is empty, so I get it like so:
Alamofire.request(.GET, testurl, parameters: ["bandName": bandName])
.responseJSON { response in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
for (_,bands) in json {
for (_,bname) in bands {
let bandName = bname["Name"].stringValue
print(bandName)
self.items.append(bandName)
self.tableView.reloadData()
}
}
}
case .Failure(let error):
print(error)
}
}
you should not add every value in bname Dictionary to self.items.
Try add bname to self.items,code:
Alamofire.request(.GET, testurl, parameters: ["bandName": bandName])
.responseJSON { response in
switch response.result {
case .Success:
if let value = response.result.value {
let json = JSON(value)
for (_,bands) in json {
for (_,bname) in bands {
self.items.append(bname)
self.tableView.reloadData()
}
}
}
case .Failure(let error):
print(error)
}
}
and in cellForRowAtIndexPath use it:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
if let dic = self.items[indexPath.row] as? NSDictionary{
if let id = dic["id"] as? String{
cell.idLabel.text = id
}
if let name = dic["Name"] as? String{
cell.nameLabel.text = name
}
}
return cell
}
Create class or model with these properties and assign values in objects keep object in NSarray that works as datasource get object from datasource using selected indexpath and pass object to your new viewcontroller using prepareForSegue.