I have 2 arrays, one that is containing the sections and another one that is containing the elements for populate the cells of my TableView.
The question is: is it possible to create multiple sections with title after 7 cells?
For example, the array contains 14 elements and sections array 2 elements. I wish that at the beginning will appear "Section 1" then first 7 elements, then "Section 2" then the rest of the elements.
Thank you!
import UIKit
class ChallengesViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
var titleArray = [""]
var weekSection = ["1","2"]
override func viewDidLoad() {
super.viewDidLoad()
> let url = URL(string:"https://website.com/file.txt")!
> URLCache.shared.removeAllCachedResponses()
> let task = URLSession.shared.dataTask(with:url) { (data, response, error) in
> if error != nil {
> print(error!)
> }
> else {
> if let textFile = String(data: data!, encoding: .utf8) {
> DispatchQueue.main.async {
> self.titleArray = textFile.components(separatedBy: "\n")
> self.tableView.reloadData()
> print(self.titleArray)
> }
> }
> }
> }
> task.resume()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return titleArray.count
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return weekSection.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "challengeCell", for: indexPath) as! ChallengeTableViewCell
cell.labelTitle.text = titleArray[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
switch (section) {
case 0:
return "Case 0"
case 1:
return "Case 1"
default:
return "Default"
}
}
Update numberOfRowsInSection and cellForRowAt methods like this
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return "Case \(section)"
}
func numberOfSections(in tableView: UITableView) -> Int {
let lastSection = titleArray.count % 7 == 0 ? 0 : 1
return (titleArray.count/7) + lastSection
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let count = titleArray.count - (7*section)
return min(7,count)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "challengeCell", for: indexPath) as! ChallengeTableViewCell
let rowIndex = (indexPath.section*7)+indexPath.row
cell.labelTitle.text = titleArray[rowIndex]
return cell
}
after the edit of the question, this is one of the best answers I think
extension Array {
func chunked(into size: Int) -> [[Element]] {
return stride(from: 0, to: count, by: size).map {
Array(self[$0 ..< Swift.min($0 + size, count)])
}
}
}
usage:
#IBOutlet weak var tableView: UITableView!
var titleArray: [[String]] = [[]]
var sectionsCount: Int = 0
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string:"https://website.com/file.txt")!
URLCache.shared.removeAllCachedResponses()
let task = URLSession.shared.dataTask(with:url) { (data, response, error) in
if error != nil {
print(error!)
}
else {
if let textFile = String(data: data!, encoding: .utf8) {
DispatchQueue.main.async {
let myArray = textFile.components(separatedBy: "\n")
self.sectionsCount = myArray.chunked(into: 7).count
self.tableView.reloadData()
print(self.titleArray)
}
}
}
}
task.resume()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return sectionsCount
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return titleArray[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "challengeCell", for: indexPath) as! ChallengeTableViewCell
let sectionArray = titleArray[indexPath.section]
cell.labelTitle.text = sectionArray[indexPath.row]
return cell
}
Related
Essentially I have tableview with JSON data and a search controller for the user to quickly find values from the response. While the tableview data loads initially when attempting to search I get the error index out of range. The error occurs inside the cellForRowAt function. The following is what I am currently doing:
var sections = [customerListSection]()
var structure = [customerList]()
var searchsections = [customerListSection]()
var searchstruct = [customerList]()
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let section = sections[section]
let searchsection = searchsections[section]
if isFiltering() {
return searchsection.count
}
return section.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let item = sections[indexPath.section].items[indexPath.row]
let customerList: customerList
if isFiltering() {
customerList = searchstruct[indexPath.row]
} else {
customerList = item
}
return cell
}
struct customerListSection {
let customerType : String
var items : [customerList]
}
struct customerList: Decodable {
let customerid: Int
let customer: String
let type: String
}
From your code, it seems that there are multiple sections, so you need to implement numberOfSections(in:)method.
If you do not implement this method, the table configures the table with one section.)
https://developer.apple.com/documentation/uikit/uitableviewdatasource/1614860-numberofsections
And since the number of rows is the number of items, not the number of sections, the tableView(_:numberOfRowsInSection:) method should return items.count.
The following is the modified code:
override func numberOfSections(in tableView: UITableView) -> Int {
if isFiltering() {
return searchsections.count
}
return sections.count
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isFiltering() {
return searchsections[section].items.count
}
return sections[section].items.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
let customerList: customerList
if isFiltering() {
customerList = searchsections[indexPath.section].items[indexPath.row]
} else {
customerList = sections[indexPath.section].items[indexPath.row]
}
cell.textLabel?.textAlignment = .left
cell.selectionStyle = .none
cell.textLabel?.font = .boldSystemFont(ofSize: 20)
cell.textLabel?.numberOfLines = 0
cell.textLabel?.lineBreakMode = .byWordWrapping
cell.textLabel!.text = customerList.customer
return cell
}
I'm pulling data from the database, I'm having no problems with data, but I'm having trouble transferring this data to the text in the Cell. I think I'm having a problem with the numberOfRowsInSection count. I want to add as much data as the sum of the two data, but I'm having trouble this way.
class ChatRoomViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var bilgiCevap = [String]()
var bilgiKullanıcı = [String]()
override func viewDidLoad() {
super.viewDidLoad()
FCevap()
chatTableView.delegate = self
chatTableView.dataSource = self
func FCevap(){
let client = SQLClient.sharedInstance()!
client.connect("...", username: "...", password: "...", database: "...") { success in
client.execute("SELECT ... FROM ... WHERE . LIKE '\(self.form_no)' AND ... LIKE '0'", completion: { (_ results: ([Any]?)) in
for table in results as! [[[String:AnyObject]]] {
for row in table {
for (_, value) in row {
if let intVal = value as? String {
self.bilgiKullanıcı.append(String(intVal))
}} }}
DispatchQueue.main.async {
self.Kullanici()
self.chatTableView.reloadData()}
client.disconnect() }) }
}
func Kullanıcı(){
let client = SQLClient.sharedInstance()!
client.connect("...", username: "...", password: "...", database: "...") { success in
client.execute("SELECT ... FROM ... WHERE ... LIKE '\(self.form_no)' AND ... LIKE '1'", completion: { (_ results: ([Any]?)) in
for table in results as! [[[String:AnyObject]]] {
for row in table {
for (_, value) in row {
if let intVal = value as? String {
self.bilgiCevap.append(String(intVal))
}} }}
DispatchQueue.main.async {self.chatTableView.reloadData()}
client.disconnect() }) }
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = chatTableView.dequeueReusableCell(withIdentifier: "chatCell") as! ChatCell
let messageGıden = self.bilgiKullanıcı[indexPath.row]
cell.chatTextView.text = messageGıden
cell.usernameLabel.text = "..."
cell.setBubbleType(type: .incoming)
let messageGelen = self.bilgiCevap[indexPath.row]
cell.chatTextView2.text = messageGelen
cell.userNameLabel2.text = "Kullanıcı"
cell.setBubbleType2(type: .outgoing)
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return bilgiCevap.count + bilgiKullanici.count
}
}
if you have data sources you need to take two Sections in number of section delegate.
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
And in numberOfRows section
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return dataSource1.count
} else {
return dataSource2.count
}
}
and then inside cellFor rowAt delegate
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let data = dataSource1[indexPath.row]
} else {
let data = dataSource2[indexPath.row]
}
}
I have a UIViewController with a UITableView. I have separate class for UITableViewDataSource and UITableViewDelegate. How can I navigate to another view controller when a cell is selected?
class ViewController: UIViewController {
let tableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = TableViewDataSource()
}
}
class TableViewDataSource: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//How to push SecondVC from Viewcontroller?
}
}
class TableViewDataSource: UITableViewDataSource, UITableViewDelegate {
var parentViewController : UIViewController?
func init(parentController : UIViewController){
self.parentViewController = parentController
}
// rest of your code
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//How to push SecondVC from Viewcontroller?
let storyboard = UIStoryboard(name: "Stroybaordname", bundle: nil)
let secondVC = storyboard.instantiateViewController(withIdentifier: "ViewControllerName")
parentViewController.present(secondVC, animated: true, completion: nil)
}
}
Try this way
If I had to do this I would do it using a separate delegate method. If I am missing the context pardon me.
class ViewController: UIViewController, TableViewDataSourceDelegate {
let tableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
let customTableDataSource = TableViewDataSource()
customTableDataSource.delegate = self
// Setting the custom delegate
tableView.delegate = customTableDataSource
}
func cellSelected(at: IndexPath) {
// Navigate from here.
}
}
/// Protocol helps to communicate with the TableViewDataSource to the user of it.
protocol TableViewDataSourceDelegate {
func cellSelected(at: IndexPath)
}
class TableViewDataSource: UITableViewDataSource, UITableViewDelegate {
var delegate: TableViewDataSourceDelegate?
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return UITableViewCell()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
delegate?.cellSelected(at: indexPath)
}
}
You can create a blocks to access it in your ViewController class.
//MARK:- MODULES
import UIKit
//MARK:- TYPEALIAS
typealias ListCellConfigureBlock = (_ cell : AnyObject? , _ item : AnyObject? , _ indexpath: IndexPath?) -> ()
typealias DidSelectedRow = (_ indexPath : IndexPath) -> ()
typealias ScrollViewDidScroll = (_ scrollView : UIScrollView) -> ()
typealias ViewForHeaderInSection = (_ section : Int) -> UIView?
typealias DidDeselectedRow = (_ indexPath : IndexPath) -> ()
typealias CanEditRowAt = (_ indexPath : IndexPath) -> Bool
typealias CommitEditingStyle = (_ commiteditingStyle: UITableViewCellEditingStyle, _ indexPath : IndexPath) -> ()
typealias HeightForRowAt = (_ indexPath : IndexPath) -> CGFloat
//MARK:- CLASS
class TableViewDataSource: NSObject {
//MARK:- PROPERTIES
var _section: [String]?
var sectionCount: Array<AnyObject>?
var rowCount : Array<AnyObject>?
var cellIdentifier : String?
var tableView : UITableView?
var configureCellBlock : ListCellConfigureBlock?
var aRowSelectedListener : DidSelectedRow?
var ScrollViewListener : ScrollViewDidScroll?
var viewforHeaderInSection : ViewForHeaderInSection?
var headerHeight : CGFloat?
var aRowDeselectedListener : DidDeselectedRow?
var aRowEditListener : CanEditRowAt?
var aRowCommitListener : CommitEditingStyle?
var aRowHeightListener : HeightForRowAt?
init (tableView : UITableView?, cellIdentifier : String?, sectionCount: Array<AnyObject>?, rowCount : Array<AnyObject>? , height : HeightForRowAt? , configureCellBlock : ListCellConfigureBlock? , aRowSelectedListener : #escaping DidSelectedRow,aRowDeselectedListener: #escaping DidDeselectedRow ,aRowCommitListener: #escaping CommitEditingStyle, DidScrollListener : ScrollViewDidScroll?) {
self.tableView = tableView
self.sectionCount = sectionCount
self.rowCount = rowCount
self.cellIdentifier = cellIdentifier
self.aRowHeightListener = height
self.configureCellBlock = configureCellBlock
self.aRowSelectedListener = aRowSelectedListener
self.aRowDeselectedListener = aRowDeselectedListener
self.aRowCommitListener = aRowCommitListener
self.ScrollViewListener = DidScrollListener
}
override init() {
super.init()
}
}
//MARK:- DELEGATE, DATASOURCE
extension TableViewDataSource : UITableViewDelegate , UITableViewDataSource{
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let identifier = cellIdentifier else { fatalError("Cell identifier not provided") }
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: identifier , for: indexPath) as UITableViewCell
cell.selectionStyle = UITableViewCellSelectionStyle.none
if let block = self.configureCellBlock , let item: AnyObject = self.rowCount?[(indexPath as NSIndexPath).row]{
block(cell , item , indexPath as IndexPath?)
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if let block = self.aRowSelectedListener{
block(indexPath)
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.rowCount?.count ?? 0
}
func numberOfSections(in tableView: UITableView) -> Int {
return self.sectionCount?.count ?? 0
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
guard let block = self.aRowHeightListener else { return 0.0 }
return block(indexPath)
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
guard let block = viewforHeaderInSection else { return nil }
return block(section)
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self._section?[section]
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return headerHeight ?? 0.0
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if let block = self.ScrollViewListener{
block(scrollView)
}
}
func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
if let block = self.aRowDeselectedListener {
block(indexPath)
}
}
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
guard let block = self.aRowEditListener else { return false }
return block(indexPath)
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if let block = self.aRowCommitListener{
block(editingStyle, indexPath)
}
}
}
You can use it like:
//Create a variable:
var dataSource = TableViewDataSource()
fileprivate func setUpDataSource() throws {
DispatchQueue.main.async { [weak self] in
dataSource = TableViewDataSource.init(tableView: tblView, cellIdentifier: CellId.chatUserTVCell.rV, sectionCount: arrSection as Array<AnyObject>, rowCount: arrSearchChatListing , height: { (indexPath) -> CGFloat in
return 80.0
}, configureCellBlock: { (cell, item, indexPath) in
guard let _cell = cell as? ChatUserTableCell, let _item = item as? ChatListing, let row = indexPath?.row else { return }
_cell.chatListing = _item
try? self?.shouldRequestPaging(row: row)
}, aRowSelectedListener: { (indexPath) in
let vc = StoryboardScene.Home.instantiateChatTextController()
try? self?.pushVC(vc)
}, aRowDeselectedListener: { (indexPath) in
debugPrint("Deselected")
}, aRowCommitListener: { (editingStyle, indexPath) in
debugPrint("aRowCommitListener")
}, DidScrollListener: { (scrollView) in
debugPrint("DidScrollListener")
})
tblView.delegate = dataSource
tblView.dataSource = dataSource
tblView.reloadData()
}
}
Hope it helps :)
I am trying to separate these data into two different sections :
–one section with movies of runtime more than 120 mins, another for the rest.
The problem is I am pulling data from the same array. How can I apply conditional statement/logic and insert into each section depending on the value? I am able to pull data from the different arrays and insert into the different sections however. Please guide me. Thank you
import UIKit
class ViewController: UIViewController,
UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section:
Int) -> Int {
return movieList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : MovieCell = tableView.dequeueReusableCell(withIdentifier: "MovieCell", for: indexPath) as! MovieCell
let p = movieList[indexPath.row]
cell.nameLabel.text = p.movieName
cell.runTimeLabel.text = "\(p.runtime) mins"
cell.movieImageView.image = UIImage(named: p.imageName)
return cell
}
var movieList : [Movie] = []
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
movieList.append(Movie(movieName:"Oklahoma Crude",
movieDesc:"",
runtime:115,
imageName:"movie_oklahoma"))
movieList.append(Movie(movieName:"Bootleggers",
movieDesc:"",
runtime:140,
imageName:"movie_bootleggers"))
movieList.append(Movie(movieName:"Superdad",
movieDesc:"",
runtime:112,
imageName:"movie_superdad"))
// Do any additional setup after loading the view, typically from a nib.
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete{
movieList.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .automatic)
}
}
#IBAction func editButton(_ sender: Any) {
if !self.tableView.isEditing
{
(sender as AnyObject).setTitle("Done", for: .normal)
tableView.setEditing(true, animated: true)
}
else
{
(sender as AnyObject).setTitle("Edit", for: .normal)
tableView.setEditing(false, animated: true)
} }
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let m = movieList[sourceIndexPath.row]
movieList.remove(at:sourceIndexPath.row)
movieList.insert(m, at:destinationIndexPath.row)
}
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
let headerTitles = ["More than 120 minutes", "Others"]
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section < headerTitles.count {
return headerTitles[section]
}
return nil
}
}
Suppose with 120 will be section = 0
func tableView(_ tableView: UITableView, numberOfRowsInSection section:
Int) -> Int {
let arr120 = movieList.filter { $0.runtime >= 120 }
let arrLess120 = movieList.filter { $0.runtime < 120 }
return section == 0 ? arr120.count : arrLess120.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let arr120 = movieList.filter { $0.runtime >= 120 }
///..
}
else {
let arrLess120 = movieList.filter { $0.runtime < 120 }
////....
}
Howver this not the perfest solution , you can organize your data source to
struct AllMovies {
let title:String // ex. above 120
let arr:[Movie]
}
It is better to have 2 arrays - one containing the movies shorter than 120mins and one containing the movies longer than 120mins. You should create those two arrays from the movieList array:
var lessThan120: [Movie]!
var moreThan120: [Movie]!
override func viewDidLoad() {
super.viewDidLoad()
movieList.append(Movie(movieName:"Oklahoma Crude",
movieDesc:"",
runtime:115,
imageName:"movie_oklahoma"))
movieList.append(Movie(movieName:"Bootleggers",
movieDesc:"",
runtime:140,
imageName:"movie_bootleggers"))
movieList.append(Movie(movieName:"Superdad",
movieDesc:"",
runtime:112,
imageName:"movie_superdad"))
let count = movieList.partition(by: {$0.runtime > 120})
lessThan120 = Array(movieList[0..<count])
moreThan120 = Array(movieList[count...])
}
Then implementing the data source methods would be very simple:
func tableView(_ tableView: UITableView, numberOfRowsInSection section:
Int) -> Int {
if section == 0 {
return moreThan120.count
} else if section == 1 {
return lessThan120.count
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : MovieCell = tableView.dequeueReusableCell(withIdentifier: "MovieCell", for: indexPath) as! MovieCell
let p = indexPath.section == 0 ? moreThan120[indexPath.row] : lessThan120[indexPath.row]
cell.nameLabel.text = p.movieName
cell.runTimeLabel.text = "\(p.runtime) mins"
cell.movieImageView.image = UIImage(named: p.imageName)
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
var movieList = [String]()
var movieListGreaterThen120 = [String]()
var movieListSmallerThen120 = [String]()
for item in movieList {
if item.runtime > 120 {
movieListGreaterThen120.append(item)
}else {
movieListSmallerThen120.append(item)
}
}
//MARK: - tableView DataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section:
Int) -> Int {
if section == 0 {
return movieListGreaterThen120.count
}else {
return movieListSmallerThen120.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : MovieCell = tableView.dequeueReusableCell(withIdentifier: "MovieCell", for: indexPath) as! MovieCell
if indexPath.section == 0 {
//Load your movieListGreaterThen120 Data
}else {
//Load your movieListSmallerThen120 Data
}
return cell
}
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
"movieList" array can be filtered out depending on the runtime value.
if indexPath.section == 0 {
movieList.filter { $0.runtime >= 120 }
}
else {
movieList.filter { $0.runtime < 120 }
}
I have an issue, numberOfRowsInSection and cellForRowAt functions don't return values. I need to return name and price from coincap.io/front API into tableView. I tried to change return values to integer and it works fine, but anyway I can't return another values.
Here is code:
import UIKit
import Alamofire
import SwiftyJSON
class Currency : NSObject {
var name : String!
var price : Double!
init(name : String, price : Double) {
self.name = name
self.price = price
}
}
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
let DATA_URL : String = "http://coincap.io/front"
var currencies = [Currency]()
var counter = 0
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
getData(url: DATA_URL)
}
func getData(url: String) {
Alamofire.request(url, method: .get).responseJSON { response in
if response.result.isSuccess {
print("Success! Got the data")
let dataJSON : JSON = JSON(response.result.value!)
// print(dataJSON)
self.updateData(json: dataJSON)
} else {
print("Error \(String(describing: response.result.error))")
}
}
}
func updateData(json: JSON) {
for (_, current) in json{
currencies.append(Currency(name: current["long"].stringValue, price: current["price"].doubleValue))
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return NSInteger(counter)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "currencyCell", for: indexPath)
let current = currencies[indexPath.row]
cell.textLabel?.text = current.name
cell.detailTextLabel?.text = "\(current.price!)"
return cell
}
}
You have to call reload
func getData(url: String) {
Alamofire.request(url, method: .get).responseJSON { response in
if response.result.isSuccess {
print("Success! Got the data")
let dataJSON : JSON = JSON(response.result.value!)
// print(dataJSON)
self.updateData(json: dataJSON)
DispatchQueue.main.async {self.tableView.reloadData()}
} else {
print("Error \(String(describing: response.result.error))")
}
}
}
Also replace
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return NSInteger(counter)
}
with
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return currencies.count
}