How to display the data from JSON in tableviewcell - ios

I need to list the data in the tableview.
{"data":[{"id":33,"question":"sqws","options":["option ,A","option ,A"],"button_type":"2","option_count":"2"}]}
This is my api pattern .
My code as follow:-
Model:-
class Model: NSObject {
var question:String?
var options:[String]?
init?(dictionary :JSONDictionary) {
guard
let question = dictionary["question"] as? String
else {
return
}
if let options = dictionary["options"] as? [String]{
print(options)
self.options = options
}
self.question = question
}
}
datasourceModel:-
class DataSourceModel: NSObject {
var dataListArray:Array<Model>? = []
init(array :Array<[String:Any]>?) {
super.init()
var newArray:Array<[String:Any]> = []
if array == nil{
// newArray = self.getJsonDataStored22()
}
else{
newArray = array!
}
var datalist:Array<Model> = []
for dict in newArray{
let model = Model(dictionary: dict)
datalist.append(model!)
}
self.dataListArray = datalist
}
}
viewmodel:-
class ViewModel: NSObject {
var datasourceModel:DataSourceModel
var filteredListArray:Array<DataSourceModel>? = []
init(withdatasource newDatasourceModel:DataSourceModel) {
datasourceModel = newDatasourceModel
print(datasourceModel.dataListArray)
}
func numberOfSections(tableView: UITableView) -> Int{
print((datasourceModel.dataListArray?.count)!)
return (datasourceModel.dataListArray?.count)!
}
func titleForHeaderInSection(atsection section: Int) -> ListModel {
return datasourceModel.dataListArray![section]
}
func numberOfRowsInSection(section:Int) -> Int {
return (datasourceModel.dataListArray?.count)!
}
func datafordisplay(atindex indexPath: IndexPath) -> Model{
//print(datasourceModel.dataListArray![indexPath.row])
return datasourceModel.dataListArray![indexPath.row]
}
func loadData(completion :#escaping (_ isSucess:Bool) -> ()){
loadFromWebserviceData { (newDataSourceModel) in
if(newDataSourceModel != nil)
{
self.datasourceModel = newDataSourceModel!
completion(true)
}
else{
completion(false)
}
}
}
func loadFromWebserviceData(completion :#escaping (DataSourceModel?) -> ()){
Alamofire.request("http://www.example.com").validate(statusCode: 200..<300).validate(contentType: ["application/json"]).responseJSON{ response in
print(response)
switch response.result{
case .success(let data):
print("success",data)
let result = response.result
print(result)
if let wholedata = result.value as? [String:Any]{
print(wholedata)
if let data = wholedata["data"] as? Array<[String:Any]>{
print(data)
print(response)
let newDataSource:DataSourceModel = DataSourceModel(array: data)
completion(newDataSource)
}
}
case .failure(let encodingError ):
print(encodingError)
// if response.response?.statusCode == 404{
print(encodingError.localizedDescription)
completion(nil)
}
}}
}
viewcontroller:-
class ViewController: UIViewController ,UITableViewDelegate,UITableViewDataSource{
private var reviewViewModel :ViewModel!
var nameArray = [String]()
#IBOutlet weak var tableview: UITableView!
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?, withViewModel viewModel:ViewModel) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
reviewViewModel = viewModel
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
nameArray = ["Home","Message","Map","Setting"]
reviewViewModel.loadData { (isSuccess) in
if(isSuccess == true)
{
self.tableview.reloadData()
}
else{
self.viewDidLoad()
}
// self.viewDidLoad()
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return (reviewViewModel.datasourceModel.dataListArray?.count)!
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let identifier = "HeaderCell"
var headercell: =questionheader! = tableView.dequeueReusableCell(withIdentifier: identifier) as? = questionheader
if headercell == nil {
tableView.register(UINib(nibName: "questionheader", bundle: nil), forCellReuseIdentifier: identifier)
headercell = tableView.dequeueReusableCell(withIdentifier: identifier) as? questionheader
}
headercell.setReviewData(reviews:reviewViewModel.titleForHeaderInSection(atsection:section))
headercell.setReviewData(reviews:reviewViewModel.datafordisplay(atindex: section))
return headercell
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// 2
//return 1
return reviewViewModel.numberOfRowsInSection(section: section)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let identifier = "Cell"
var cell: NH_QuestionListCell! = tableView.dequeueReusableCell(withIdentifier: identifier) as? NH_QuestionListCell
if cell == nil {
tableView.register(UINib(nibName: "QuestionListCell", bundle: nil), forCellReuseIdentifier: identifier)
cell = tableView.dequeueReusableCell(withIdentifier: identifier) as? QuestionListCell
}
cell.setReviewData(reviews:reviewViewModel.datafordisplay(atindex: indexPath))
return cell
}
}
questionheader:-
class questionheader: UITableViewCell {
#IBOutlet weak var lblName: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func setReviewData(reviews:QuestionListModel)
{
self.lblName.text = reviews.question
print(self.lblName.text)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
QuestionListCell:-
class QuestionListCell: UITableViewCell {
#IBOutlet weak var question: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
func setReviewData(reviews:QuestionListModel)
{
print(reviews.options)
print(reviews.options?[0])
self.question.text = reviews.options?[0]
print(self.question.text)
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
So,here i got questions at sections .But according to my api i need to list the data contain in key option.
{"data":[{"id":33,"question":"sqws","options":["option ,A","option ,B"],"button_type":"2","option_count":"2"}]}
According to this i got the question in section and i need to display the options in tableviewcell That means option ,A and option ,B should display in the tableviewcell.How to do?
Just like thisJust like this

First thing is:
You should return the option count in this method
func numberOfRowsInSection(section:Int) -> Int {
let objectAtSection: [String: String] = datasourceModel.dataListArray?[section]
return Int(objectAtSection["option_count"])!
}
second, for showing the options in cell, update this method.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let identifier = "Cell"
var cell: NH_QuestionListCell! = tableView.dequeueReusableCell(withIdentifier: identifier) as? NH_QuestionListCell
if cell == nil {
tableView.register(UINib(nibName: "QuestionListCell", bundle: nil), forCellReuseIdentifier: identifier)
cell = tableView.dequeueReusableCell(withIdentifier: identifier) as? QuestionListCell
}
let objectAtSection: [String: String] = datasourceModel.dataListArray?[section]
let optionsAtRow: [String] = objectAtSection["options"]
cell.question.text = optionsAtRow[indexPath.row]
return cell
}
Try and share the results

Related

How to make the deleteTask method work properly?

I am trying to create a ToDoList in swift UI and my deleteTask function is not working properly. I tried a lot of things and none of them worked.
import UIKit
class ViewController: UIViewController {
#IBOutlet var tableView: UITableView!
var toDoTasks = [String]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.title = "SAVED TASKS"
tableView.delegate = self
tableView.dataSource = self
// setup
if !UserDefaults().bool(forKey: "setup")
{
UserDefaults().set(true, forKey: "setup")
UserDefaults().set(0, forKey: "count")
}
updateTasks()
}
func updateTasks()
{
toDoTasks.removeAll()
guard let count = UserDefaults().value(forKey: "count") as? Int else
{
return
}
for x in 0..<count
{
if let task = UserDefaults().value(forKey: "task_\(x+1)") as? String
{
toDoTasks.append(task)
}
}
tableView.reloadData()
}
#IBAction func didTapAdd()
{
let viewController = storyboard?.instantiateViewController(withIdentifier: "entry") as! EntryViewController
viewController.title = "NEW TASK"
viewController.updated =
{
DispatchQueue.main.async {
self.updateTasks()
}
}
navigationController?.pushViewController(viewController, animated: true)
}
}
extension ViewController: UITableViewDelegate
{
// function to select the rows
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
let viewController = storyboard?.instantiateViewController(withIdentifier: "task") as! TasksViewController
viewController.title = "NEW TASK"
viewController.task = toDoTasks[indexPath.row]
navigationController?.pushViewController(viewController, animated: true)
}
}
extension ViewController: UITableViewDataSource
{
// function which returns number of tasks
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return toDoTasks.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = toDoTasks[indexPath.row]
return cell
}
}
import UIKit
class TasksViewController: UIViewController {
#IBOutlet var label : UILabel!
var task : String?
var currentPosition: Int?
override func viewDidLoad() {
super.viewDidLoad()
label.text = task
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Delete", style: .done, target: self, action: #selector(deleteTask))
}
#objc func deleteTask(_ sender: UIBarButtonItem) {
guard let currentPosition = self.currentPosition else {
return
}
let count = UserDefaults.standard.integer(forKey: "count")
UserDefaults.standard.removeObject(forKey: "task_\(currentPosition+1)")
for i in currentPosition+1..<count {
let task = UserDefaults.standard.string(forKey: "task_\(i+1)")
UserDefaults.standard.setValue(task, forKey: "task_\(i)")
}
UserDefaults.standard.setValue(count-1, forKey: "count")
navigationController?.popViewController(animated: true)
}
}
When I press the Delete button, nothing happens. Could you please help me??

How to update the tableview after adding the object

How to update the tableview after adding the object .
I am doing in the mvvm ,
So
in cartviewmodel:-
var datasourceModel: DataSourceModel
var insertedArray: Model?
var finalArray: Array<Model>? = []
func add() {
datasourceModel.dataListArray?.append(insertedArray!)
print(datasourceModel.dataListArray)
self.datasourceModel.dataListArray = datasourceModel.dataListArray
}
In tableview cell i have used a button for adding.
So in viewcontroller i have done the action on the add button
AND thus it will add and display the other viewcontroller.
my hotelviewcontroller as:-
the code for add button action...
cell.cartaddCell = {[weak self] in
if let i = self?.tableView.indexPath(for: $0) {
let cartDataSource:DataSourceModel = DataSourceModel(array: nil)
let cartViewModel:ViewModel = ViewModel(withdatasource: cartDataSource)
let cartmodel:Model = Model(withoffermodel:self!.offerViewModel.datafordisplay(atindex: indexPath))
cartViewModel.insertedArray = cartmodel
print(cartViewModel.insertedArray)
cartViewModel.add()
let cartViewController:ViewController = ViewController(nibName: "ViewController", bundle: nil, withViewModel: cartViewModel)
self?.navigationController?.pushViewController(cartViewController, animated: true)
// self?.present(cartViewController, animated: true, completion: nil)
// print(cartViewModel.insertedArray )
print(cartmodel.offerprice)
print(cartmodel.offerdetailAddName)
print(cartmodel)
print(i)
// self?.chartViewModel.delete(atIndex: i)
}
}
now in my cartviewmodel as:-
class ViewModel: NSObject {
var datasourceModel:DataSourceModel
var insertedArray:Model?
var finalArray:Array<Model>? = []
init(withdatasource newDatasourceModel: DataSourceModel) {
datasourceModel = newDatasourceModel
print(datasourceModel.dataListArray)
}
func datafordisplay(atindex indexPath: IndexPath) -> Model{
return datasourceModel.dataListArray![indexPath.row]
}
func numberOfRowsInSection(section:Int) -> Int {
return datasourceModel.dataListArray!.count
}
func delete(atIndex indexPath: IndexPath) {
datasourceModel.dataListArray!.remove(at: indexPath.row)
}
func add() {
datasourceModel.dataListArray?.append(insertedArray!)
print(datasourceModel.dataListArray)
self.datasourceModel.dataListArray = datasourceModel.dataListArray
}
func insert(){
add()
datasourceModel.dataListArray!.insert(insertedArray?.offerdetailAddName, at: indexPath.row)
}
}
my cartviewcontroller:-
class ViewController: UIViewController ,UITableViewDataSource,UITabBarDelegate{
#IBOutlet private weak var tableView: UITableView!
#IBOutlet weak var orderbutton: UIButton!
#IBOutlet weak var displayresult: UIView!
private var chartViewModel :ViewModel!
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?, withViewModel viewModel:ViewModel) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
chartViewModel = viewModel
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.backgroundColor = UIColor(red: 0.93, green: 0.86, blue: 1, alpha:1.0)
tableView.dataSource = self
displayresult.isHidden = false
self.tableView .reloadData()
self.tableView.tableFooterView = displayresult
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return chartViewModel.numberOfRowsInSection(section: section)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let identifier = "cell"
var cell: ChartCell! = tableView.dequeueReusableCell(withIdentifier: identifier) as? ChartCell
if cell == nil {
tableView.register(UINib(nibName: "ChartCell", bundle: nil), forCellReuseIdentifier: identifier)
cell = tableView.dequeueReusableCell(withIdentifier: identifier) as? ChartCell
}
cell.setEventData(charts: chartViewModel.datafordisplay(atindex: indexPath))
print(chartViewModel.insertedArray)
return cell
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
chartViewModel.delete(atIndex: indexPath)
tableView.deleteRows(at: [indexPath], with: .automatic)
self.tableView.reloadData()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Actually i have 2 screens.
1.hotelscreen
2.cartscreen
So while clicking the hoteltableviewcell a have a button to add cart .
So while adding the hotel model will added in the cart screen.
for that i got the value already.
But my question is:-
when i clicked on the cartscreen the added object is not displayed.
So how to show the updated data.
Seems like all you need is tableView.reloadData().

viewmodel in app delegate ion mmvm in swift

I am doing in mvvm .
my code as below:-
private var url = URL(string: "http://www.example.com")!
typealias JSONDictionary = [String:Any]
class Webservice{
static func fetchHostels(completion: #escaping ([JSONDictionary]) -> ()) {
URLSession.shared.dataTask(with: url) { data, _, _ in
if let data = data {
let json = try! JSONSerialization.jsonObject(with: data, options: [])
let dictionaries = json as! [JSONDictionary]
completion(dictionaries)
}
}.resume()
}
}
My hostelmodel:-
class hostelmodel: NSObject {
var name: String?
var city: String?
init(_ dictionary: [String: Any]) {
if let name = dictionary["name"] as? String, let location = dictionary["location"] as? [String: Any], let city = location["city"] as? String {
self.name = name
self.city = city
}
}
}
my hostelviewmodel:-
class hostelviewmodel: NSObject {
private var hostels: [hostelmodel] = []
func fetchData(completion: (() -> Void)?) {
Webservice.fetchHostels { [weak self] dictionaries in
self?.hostels = dictionaries.flatMap(hostelmodel.init)
completion?()
}
}
func numberOfSections() -> Int {
//your number of section
return 1
}
func numberOfRows() -> Int {
//your number of rows
return hostels.count
}
func hostel(atIndex index: Int) -> hostelmodel {
return hostels[index]
}
}
my hostellist:-
#IBOutlet private weak var tableView: UITableView!
private var viewModel: hostelviewmodel
init(hostelViewModel: hostelviewmodel) {
self.viewModel = hostelViewModel
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
}
private func fetchData() {
viewModel.fetchData { [weak self] in
DispatchQueue.main.async {
self?.tableView.reloadData()
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return viewModel.numberOfSections()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return viewModel.numberOfRows()
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)as! QM_RestaurtantCell
cell.setRestaurtantData(restaurtant: QM_RestaurtantModel)
return cell
}
}
}
my hosteltablecell:-
#IBOutlet weak var name: UILabel!
#IBOutlet weak var city: UILabel!
func setRestaurtantData(restaurtant:hostelmodel)
{
self.name.text = restaurtant.name
self.city.text = restaurtant.city
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
I am doing without storyboard, so here how to set in the appdelegate. What should I set as root view controller in app delegate class. And also how the name and city value display in the tableview cell for row index in swift.How to deo
For Migrating to App Delegate to your HostelList View Controller :
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Transferring Control to First Controller
window = UIWindow(frame: UIScreen.main.bounds)
let nav1 = UINavigationController()
let vc = HostelList()
nav1.viewControllers = [vc]
window?.rootViewController = vc
window?.makeKeyAndVisible()
return true
}
To set your values in tableview, Use this function :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
}
Ok. Try this refactored code pls:
AppDelegate didFinish:
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
let vm = HostelViewModel()
let vc = HostelViewController(hostelViewModel: vm)
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = vc
window?.makeKeyAndVisible()
return true
}
HostelViewController:
class HostelViewController: UIViewController {
private let tableView = UITableView(frame: .zero, style: .plain)
private var viewModel: HostelViewModel
init(hostelViewModel: HostelViewModel) {
self.viewModel = hostelViewModel
super.init(nibName: nil, bundle: nil)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
createUI()
tableView.dataSource = viewModel
fetchData()
}
func createUI() {
tableView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(tableView)
tableView.register(HostelCell.self, forCellReuseIdentifier: cellIdentifier)
tableView.estimatedRowHeight = 60
tableView.rowHeight = UITableViewAutomaticDimension
let tableViewConstraints: [NSLayoutConstraint] = [
tableView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
tableView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor)
]
NSLayoutConstraint.activate(tableViewConstraints)
}
private func fetchData() {
viewModel.fetchData { [weak self] in
DispatchQueue.main.async {
self?.tableView.reloadData()
}
}
}
}
HostelViewModel:
class HostelViewModel: NSObject, UITableViewDataSource {
private var hostels: [HostelModel] = []
func fetchData(completion: (() -> Void)?) {
Webservice.fetchHostels { [weak self] dictionaries in
self?.hostels = dictionaries.flatMap(HostelModel.init)
completion?()
}
}
func hostel(atIndex index: Int) -> HostelModel {
return hostels[index]
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return hostels.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let hostel = hostels[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! HostelCell
cell.setRestaurtantData(restaurtant: hostel)
return cell
}
}
HostelCell file:
let cellIdentifier = "HostelTableCell"
class HostelCell: UITableViewCell {
private var name: UILabel = UILabel()
private var city: UILabel = UILabel()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
createUI()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setRestaurtantData(restaurtant: HostelModel)
{
self.name.text = restaurtant.name
self.city.text = restaurtant.city
}
func createUI() {
[city, name].forEach {
contentView.addSubview($0)
$0.translatesAutoresizingMaskIntoConstraints = true
}
city.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8).isActive = true
city.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
name.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -8).isActive = true
name.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
HostelModel:
class HostelModel {
var name: String?
var city: String?
init(_ dictionary: [String: Any]) {
if let name = dictionary["name"] as? String, let location = dictionary["location"] as? [String: Any], let city = location["city"] as? String {
self.name = name
self.city = city
}
}
}

can we pass data from table cell to table view where both are xib files?

I want to pass table cell data (xib file) to table view (also a xib file). I have tried passing the data using the following piece of code but did not get an appropriate result.
PropertyCell.swift
import UIKit
class PropertyCell: UITableViewCell {
#IBOutlet weak var propertyCodeLbl: UILabel!
#IBOutlet weak var addressLbl: UILabel!
}
I have attached the screenshot for PropertyCell below -
PropertyCell.xib
PropertyCell.xib file
PropertyTableVC.swift
import UIKit
import Alamofire
class PropertyTableVC: UITableViewController {
#IBOutlet var propertyTabel: UITableView!
let URL_Landlord_Property_List = "http://127.0.0.1/source/api/LandlordPropertyList.php"
var count: Int = 0
var landlordPropertyArray: [PropertyList]? = []
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
propertyTabel.dataSource = self
propertyTabel.delegate = self
let nibName = UINib(nibName: "PropertyCell", bundle:nil)
self.propertyTabel.register(nibName, forCellReuseIdentifier: "Cell")
}
func fetchData(){
let urlRequest = URLRequest(url: URL(string: URL_Landlord_Property_List)!)
let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if error != nil{
print(error!)
return
}
print(data!)
self.landlordPropertyArray = [PropertyList]()
self.count = (self.landlordPropertyArray?.count)!
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]
if let datafromjson = json["landlords_property_list"] as? [[String: AnyObject]] {
print(datafromjson)
for data in datafromjson{
var property = PropertyList()
if let id = data["ID"] as? Int,let code = data["Code"] as? String, let address1 = data["Address"] as? String
{
property.id = id
property.code = code
property.address1 = address1
}
self.landlordPropertyArray?.append(property)
}
print(self.landlordPropertyArray)
}
DispatchQueue.main.async {
self.propertyTabel.reloadData()
}
}catch let error {
print(error)
}
}
task.resume()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (landlordPropertyArray?.count)!
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Configure the cell...
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! PropertyCell
cell.propertyCodeLbl.text = self.landlordPropertyArray?[indexPath.item].code
cell.addressLbl.text = self.landlordPropertyArray?[indexPath.item].address1
return cell
}
}
Attached the screenshot for Property Table below -
PropertyTableVC.xib
PropertyTableVC.xib file
Your TableViewCell :
import UIKit
protocol yourProtocolName { //add protocol here
func getDataFromTableViewCellToViewController (sender : self) //* as you need to pass the table view cell, so pass it as self
}
class PropertyCell: UITableViewCell {
#IBOutlet weak var propertyCodeLbl: UILabel!
#IBOutlet weak var addressLbl: UILabel!
var delegate : yourProtocolName? //set a delegate
override func awakeFromNib() {
super.awakeFromNib()
if delegate != nil {
delegate.getDataFromTableViewCellToViewController(sender :self) *
}
}
}
And your ViewController :
import UIKit
import Alamofire
class PropertyTableVC: UITableViewController,yourProtocolName { //conform to the protocol you created in tableViewCell
#IBOutlet var propertyTabel: UITableView!
let URL_Landlord_Property_List = "http://127.0.0.1/source/api/LandlordPropertyList.php"
var count: Int = 0
var landlordPropertyArray: [PropertyList]? = []
override func viewDidLoad() {
super.viewDidLoad()
fetchData()
propertyTabel.dataSource = self
propertyTabel.delegate = self
let nibName = UINib(nibName: "PropertyCell", bundle:nil)
self.propertyTabel.register(nibName, forCellReuseIdentifier: "Cell")
}
func fetchData(){
let urlRequest = URLRequest(url: URL(string: URL_Landlord_Property_List)!)
let task = URLSession.shared.dataTask(with: urlRequest) { (data, response, error) in
if error != nil{
print(error!)
return
}
print(data!)
self.landlordPropertyArray = [PropertyList]()
self.count = (self.landlordPropertyArray?.count)!
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as! [String: AnyObject]
if let datafromjson = json["landlords_property_list"] as? [[String: AnyObject]] {
print(datafromjson)
for data in datafromjson{
var property = PropertyList()
if let id = data["ID"] as? Int,let code = data["Code"] as? String, let address1 = data["Address"] as? String
{
property.id = id
property.code = code
property.address1 = address1
}
self.landlordPropertyArray?.append(property)
}
print(self.landlordPropertyArray)
}
DispatchQueue.main.async {
self.propertyTabel.reloadData()
}
}catch let error {
print(error)
}
}
task.resume()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (landlordPropertyArray?.count)!
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Configure the cell...
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! PropertyCell
cell.propertyCodeLbl.text = self.landlordPropertyArray?[indexPath.item].code
cell.addressLbl.text = self.landlordPropertyArray?[indexPath.item].address1
return cell
}
func getDataFromTableViewCellToViewController(sender :UITableViewCell) {
//make a callback here
}
}
(*) Marked fields are updated code
Call fetchData() function after tableview delegate and datasource assigning
propertyTabel.dataSource = self
propertyTabel.delegate = self
Updated answer is
Create Cell Class like this
import UIKit
class YourTableViewCell: UITableViewCell {
#IBOutlet weak var profileImageView: UIImageView!
#IBOutlet weak var userNameLabel: UILabel!
#IBOutlet weak var timeDateLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
self.backgroundColor = UIColor.tableViewBackgroundColor()
self.selectionStyle = .none
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
class func cellForTableView(tableView: UITableView, atIndexPath indexPath: IndexPath) -> YourTableViewCell {
let kYourTableViewCell = "YourTableViewCellIdentifier"
tableView.register(UINib(nibName:"RRLoadQuestionsTableViewCell", bundle: Bundle.main), forCellReuseIdentifier: kYourTableViewCell)
let cell = tableView.dequeueReusableCell(withIdentifier: kYourTableViewCell, for: indexPath) as! YourTableViewCell
return cell
}
}
Then create UIViewController Class and place UITableView on it and link with outlet
class YourViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UITextViewDelegate {
#IBOutlet weak var tableView: UITableView!
var dataSource = [LoadYourData]()
// MARK: - Init & Deinit
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
super.init(nibName: "YourViewController", bundle: Bundle.main)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
NotificationCenter.default.removeObserver(self)
}
override func viewDidLoad() {
super.viewDidLoad()
setupViewControllerUI()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
}
// MARK: - UIViewController Helper Methods
func setupViewControllerUI() {
tableView.estimatedRowHeight = 44.0
tableView.rowHeight = UITableViewAutomaticDimension
tableView.delegate = self
tableView.dataSource = self
loadData()
}
func loadData() {
// Write here your API and reload tableview once you get response
}
// MARK: - UITableView Data Source
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return dataSource.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = YourTableViewCell.cellForTableView(tableView: tableView, atIndexPath: indexPath)
// assign here cell.name etc from dataSource
return cell
}

Different cells in tableview swift 3

example [1]: https://i.stack.imgur.com/8cORc.png
how to make the following table correctly
I do not want crutches
All cells one by one, except for a block of X.count, there will be a different number (from two or more)
how to find out the first and last cells from Block X later to show or hide the strip between the cells (between the points, I make their three thin ones, and want to hide or show the cell depending on the cell)
import UIKit
import CoreLocation
import Alamofire
import SwiftyJSON
class TableVC: UIViewController,UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var loadingView: UIView!
var number: String! = "number"
var detail_data: DetailListData?
var token: String?
var json = "Invalid"
override func viewDidLoad() {
super.viewDidLoad()
loadingView.isHidden = false
print("===============================",number!)
tableView.register(UINib(nibName: "HeaderTVC", bundle: Bundle.main), forCellReuseIdentifier: "HeaderTVC")
tableView.register(UINib(nibName: "DistanceTVC", bundle: Bundle.main), forCellReuseIdentifier: "DistanceTVC")
tableView.register(UINib(nibName: "MapTVC", bundle: Bundle.main), forCellReuseIdentifier: "MapTVC")
tableView.register(UINib(nibName: "InfoTVC", bundle: Bundle.main), forCellReuseIdentifier: "InfoTVC")
tableView.register(UINib(nibName: "BottomTVC", bundle: Bundle.main), forCellReuseIdentifier: "BottomTVC")
tableView.delegate = self
token = UserDefaults.standard.value(forKey: "token")! as? String
getData()
}
func getData () {
let httpHeaders = ["Authorization": token!,
"Accept": "application/json"]
Alamofire.request(REST_API.MAIN_URL_DEV + REST_API.SHIPMENTS + "/" + number! ,encoding: JSONEncoding.default, headers: httpHeaders)
.responseString { response in
if let JSON = response.result.value {
self.json = JSON
// print(JSON)
if let jsonObj = self.json.parseJSONString {
if let data = jsonObj as? NSDictionary {
if let obj = DetailListJson4Swift_Base(dictionary: data) {
if obj.status?.code == 200 {
self.detail_data = obj.data
print("////==================== DATA", obj.data!, self.detail_data!)
self.loadingView.isHidden = true
self.tableView.reloadData()
} else {
print("Status: Error code")
MyAlertController.doAlert("Error", alertMessage: "something wrong, try again late")
}
} else {
MyAlertController.doAlert("Error", alertMessage: "Unable to construct movie object")
print("Unable to construct movie object")
}
} else {
MyAlertController.doAlert("Error", alertMessage: "Unable to interpret parsed object as dictionary")
print("Unable to interpret parsed object as dictionary")
print(jsonObj)
}
}
}
}
}
#IBAction func accept(_ sender: Any) {
}
}
extension TableVC {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if detail_data != nil {
if section == 0 {
return 3
} else if section == 1 {
return (detail_data?.waypoints?.count)!
} else if section == 2 {
return 1
}
}
return 0
}
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let headerTVC = tableView.dequeueReusableCell(withIdentifier: "HeaderTVC", for: indexPath) as! HeaderTVC
headerTVC.code.text = detail_data?.id!
headerTVC.price.text = detail_data?.price?.total!
headerTVC.distamce.text = detail_data?.distance!
return headerTVC
}
if indexPath.row == 1 {
let distanceTVC = tableView.dequeueReusableCell(withIdentifier: "DistanceTVC", for: indexPath) as! DistanceTVC
return distanceTVC
}
if indexPath.row == 2 {
let mapTVC = tableView.dequeueReusableCell(withIdentifier: "MapTVC", for: indexPath) as! MapTVC
return mapTVC
}
if indexPath.row == 4 {
let bottomTVC = tableView.dequeueReusableCell(withIdentifier: "BottomTVC", for: indexPath) as! BottomTVC
return bottomTVC
}
// the other cells should contains title and subtitle:
let infoTVC = tableView.dequeueReusableCell(withIdentifier: "InfoTVC", for: indexPath) as! InfoTVC
return infoTVC
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}

Resources