How to update the tableview after adding the object - ios

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().

Related

Inserting table view row by pressing the button

I created a UITabBarController with two controllers , as first I have a
ViewController with UIButton on it and the second is UITableViewController, how can I by pressing on btn in ViewController insert new row in tableView?
Should it be done with custom delegation ?
Can someone please show quick example
here is my code
import UIKit
class Home: UIViewController {
var delegate: TableViewDelegate?
lazy var addButton : UIButton = {
let button = UIButton(type: .system)
button.setImage(#imageLiteral(resourceName: "plus_photo"), for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget(self, action: #selector(setupRows), for: .touchUpInside)
return button
}()
#objc func setupRows() {
delegate?.insertingRows()
}
override func viewDidLoad() {
super.viewDidLoad()
delegate = self as? TableViewDelegate
setupRows()
navigationItem.title = "Test"
view.backgroundColor = .white
view.addSubview(addButton)
addButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
addButton.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
addButton.heightAnchor.constraint(equalToConstant: 150).isActive = true
addButton.widthAnchor.constraint(equalToConstant: 150).isActive = true
}
}
import UIKit
protocol TableViewDelegate {
func insertingRows()
}
class TableViewTest: UITableViewController , TableViewDelegate {
var items = ["abc", "abcd", "abcde"]
let cellid = "cellid"
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(CustomCell.self, forCellReuseIdentifier: cellid)
insertingRows()
}
func insertingRows() {
let indexPath = IndexPath(row: items.count + 1, section: 0)
tableView.insertRows(at: [indexPath], with: .left)
self.tableView.reloadData()
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellid, for: indexPath) as! CustomCell
cell.textLabel?.text = items[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
}
class CustomCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews() {
}
}
You can use tabBar(_:didSelect:) delegate method in your Home viewController.
Your Home VC :
class Home: UIViewController, UITabBarControllerDelegate {
private var selectedIndex: Int?
override func viewDidLoad() {
super.viewDidLoad()
self.tabBarController?.delegate = self
}
func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
if tabBarController.selectedIndex == 1 {
if let secondViewController = viewController as? TableViewTest, let index = selectedIndex {
secondViewController.insertingRows(index: index)
}
}
}
#objc func setupRows() {
selectedIndex = 3
}
}
Your TableViewTest TableViewController :
class TableViewTest: UITableViewController {
func insertingRows(index: Int) {
let indexPath = IndexPath(row: index, section: 0)
tableView.beginUpdates()
tableView.insertRows(at: [indexPath], with: .none)
tableView.endUpdates()
}
}

How to display the data from JSON in tableviewcell

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

UITableViewCell multiple select circle (Edit Control) coming randomly

I created a ViewController with a UITableView as a subView.
import UIKit
class ViewController: UIViewController {
private var tableDataSource = [
"Lorem Ipsum is simply du.",
"It is a long established .",
"Lorem Ipsum come",
"All the Lorem .",
"The standard ch.",
"The generated.",
"Various versions."
]
private var isReorderingEnabled = false
private var isDeleteEnabled = false
#IBOutlet private var reorderCellsBarButton: UIBarButtonItem!
#IBOutlet private var selectCellsBarButton: UIBarButtonItem! {
didSet {
selectCellsBarButton.tag = ButtonTags.Select
}
}
#IBOutlet private var deleteCellsBarButton: UIBarButtonItem! {
didSet {
deleteCellsBarButton.tag = ButtonTags.Delete
}
}
#IBOutlet weak private var tableView: UITableView! {
didSet {
tableView.dataSource = self
tableView.delegate = self
tableView.allowsMultipleSelectionDuringEditing = false
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 300
}
}
}
extension ViewController {
private struct ButtonTags {
static let Delete = 2
static let Select = 1
}
private struct LocalizedStrings {
static let EnableReorderingText = "Reorder"
static let DisableReorderingText = "Done"
static let EnableSelectionText = "Select"
static let ConfirmDeletionText = "Delete"
static let DisableDeletionText = "Cancel"
}
}
extension ViewController {
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
setDeleteBarButton(hidden: true, animated: false)
}
}
// IBActions
extension ViewController {
#IBAction private func reorderCells(_ sender: UIBarButtonItem) {
isReorderingEnabled = !tableView.isEditing
setSelectBarButton(hidden: isReorderingEnabled)
sender.title = isReorderingEnabled ? LocalizedStrings.DisableReorderingText : LocalizedStrings.EnableReorderingText
tableView.setEditing(isReorderingEnabled, animated: true)
tableView.reloadData()
}
#IBAction private func deleteCells(_ sender: UIBarButtonItem) {
isDeleteEnabled = !tableView.isEditing
setDeleteBarButton(hidden: !isDeleteEnabled)
selectCellsBarButton.title = isDeleteEnabled ? LocalizedStrings.DisableDeletionText : LocalizedStrings.EnableSelectionText
if sender.tag == ButtonTags.Delete {
deleteSelectedRows()
}
tableView.allowsMultipleSelectionDuringEditing = isDeleteEnabled
tableView.setEditing(isDeleteEnabled, animated: true)
tableView.reloadData()
}
}
// Custom Helper methods
extension ViewController {
private func setDeleteBarButton(hidden: Bool, animated: Bool = true) {
navigationItem.setRightBarButtonItems([(hidden ? reorderCellsBarButton : deleteCellsBarButton)], animated: animated)
}
private func setSelectBarButton(hidden: Bool, animated: Bool = true) {
self.navigationItem.setLeftBarButton((hidden ? nil : selectCellsBarButton), animated: animated)
}
private func deleteSelectedRows() {
guard let selectedRows = tableView.indexPathsForSelectedRows else { return }
let indexes = selectedRows.map { $0.row }
tableDataSource.remove(indexes: indexes)
tableView.deleteRows(at: selectedRows, with: .fade)
}
}
extension ViewController: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableDataSource.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let customCell = tableView.dequeueReusableCell(withIdentifier: CustomTableViewCell.identifier, for: indexPath) as! CustomTableViewCell
customCell.setup(content: tableDataSource[indexPath.row], for : indexPath.row)
return customCell
}
}
// pragma - To Select/Edit/Move TableView Cells
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
tableDataSource.move(from: sourceIndexPath.row, to: destinationIndexPath.row)
let reloadingIndexPaths = IndexPath.createForNumbers(from: sourceIndexPath.row, to: destinationIndexPath.row)
DispatchQueue.main.async {
tableView.reloadRows(at: reloadingIndexPaths, with: .none)
}
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
tableDataSource.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .none)
}
}
}
// pragma - Settings for Edit/Move TableViewCell
extension ViewController {
func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
print("Edit- \(tableView.isEditing)")
return tableView.isEditing
}
func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
print("Move- \(isReorderingEnabled)")
return isReorderingEnabled
}
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCellEditingStyle {
print("Style- None")
return .none
}
func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
print("indent- \(isDeleteEnabled)")
return isDeleteEnabled
}
}
In this, I have made three bar buttons,one for Reordering , and other two for Deletion and Cancellation.
So, for delete I have provided ability to select multiple rows.
But the problem is, when Reordering selected, the checkbox is still appearing(Not clickable though). And sometimes when Deletion selected, checkbox doesn't appear.
Cannot understand the absurd behaviour. Is this a bug of XCode ? Please help.
Added Content:
CustomTableViewCell class :
import UIKit
class CustomTableViewCell: UITableViewCell {
static let identifier = "customCellIdentifier"
#IBOutlet weak private var titleLabel: UILabel!
#IBOutlet weak private var backgroundImageView: UIImageView!
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
let selectionView = UIView()
selectionView.backgroundColor = UIColor.clear
selectedBackgroundView = selectionView
}
}
extension CustomTableViewCell {
func setup(content: String, for rowNumber: Int) {
titleLabel.text = content
let backgroundImageName = rowNumber % 2 == 0 ? ImageAssetNames.BlueMatte : ImageAssetNames.GreenThreads
backgroundView = UIImageView(image: UIImage(named: backgroundImageName))
}
}

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
}

UICollection View inside Table Cell does not show images in Swift 3

I put UICollectionView inside table cell in Home page. Each category row has their contents image. But, my problem is that when I run the app, the images under second row/second category do not show whenever I run the app.
The images will show after I click more button and it will goes to details UI. Then, I click on Back button and reach the Home page. At this time, the images shows properly. I tried many codes but I don't know where it is wrong.
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
tableView.reloadData()
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
}
override func viewDidAppear(_ animated: Bool) {
tableView.reloadData()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//getSearchWords()
DispatchQueue.main.async {
self.tableView.reloadData()
}
self.tableView.reloadData()
self.tableView.layoutIfNeeded()
}
override func viewDidLoad() {
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// debugPrint("HOme Table View Cell")
let cell = tableView.dequeueReusableCell(withIdentifier: "homecell") as! HomeCategoryRowCell
let list = sections[(indexPath as NSIndexPath).row]
cell.setCollectionViewDataSourceDelegate(self, forRow: indexPath.row)
cell.collectionViewOffset = self.storedOffsets[indexPath.row] ?? 0
DispatchQueue.main.async {
cell.categoryTitle.text = list.package_name
cell.mainAssociatedURL.text = list.package_url
}
cell.categoryTitle.font = UIFont.boldSystemFont(ofSize: 17.0)
cell.collectionView.tag = indexPath.row
cell.parentVC = self
cell.collectionView.reloadData()
return cell
}
extension Home : UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return sections[collectionView.tag].packageTable.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "videoCell", for: indexPath) as! HomeVideoCell
let list = sections[collectionView.tag].packageTable[indexPath.row]
if(list.poster_image_url != StringResource().posterURL){
let url = NSURL(string: list.poster_image_url)
do{
if let url = url {
_ = try Data(contentsOf:url as URL)
poster_url = list.poster_image_url
}
}catch let error {
//debugPrint("ERRor ::\(error)")
poster_url = StringResource().posterURL
}
}else{
poster_url = StringResource().posterURL
}
AsyncImageLoader.sharedLoader.imageForUrl(urlString: poster_url) { (image, url) -> () in
DispatchQueue.main.async(){
cell.movieTitle.text = list.name
if(url == StringResource().posterURL){
cell.imageView.image = UIImage(named: "sample_cover")
}else{
cell.imageView.image = image
}
}
}
// cell.layer.shouldRasterize = true
// cell.layer.rasterizationScale = UIScreen.main.scale
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Home Collection view at row \(collectionView.tag) selected index path \(indexPath)")
let list = sections[collectionView.tag].packageTable[indexPath.row]
self.prefs.set(list.poster_image_url, forKey: "poster_image_url")
self.prefs.set(list.name, forKey: "name")
self.prefs.set(list.assets_id, forKey: "VEDIO_ID")
debugPrint(list.name)
debugPrint(list.assets_id)
}
}
These above codes are written in Home.swift.
In HomeCell.swift,
class HomeCell : UITableViewCell {
var parentVC: UIViewController?
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var categoryTitle: UILabel!
#IBOutlet weak var SeeAll: UIButton!
#IBOutlet weak var mainAssociatedURL: UILabel!
let prefs:UserDefaults = UserDefaults.standard
var catId: String! = ""
var associated_url: String!
override func awakeFromNib() {
super.awakeFromNib()
SeeAll.setTitle(NSLocalizedString("See All >", comment: ""), for: .normal)
SeeAll.titleLabel!.font = UIFont (name: "Tharlon", size: 14)
}
#IBAction func btnSeeAll(_ sender: Any) {
catId = categoryTitle.text!
associated_url = mainAssociatedURL.text!
self.prefs.setValue(1, forKey: "PROVIDER_ID")
self.prefs.set(catId, forKey: "PROVIDER_NAME")
self.prefs.set(associated_url, forKey: "associated_url")
}
override func layoutSubviews() {
super.layoutSubviews()
collectionView.collectionViewLayout.invalidateLayout()
}
}
extension HomeCategoryRowCell {
func setCollectionViewDataSourceDelegate<D: UICollectionViewDataSource & UICollectionViewDelegate>(_ dataSourceDelegate: D, forRow row: Int) {
self.collectionView.delegate = dataSourceDelegate
self.collectionView.dataSource = dataSourceDelegate
self.collectionView.tag = row
self.collectionView.setContentOffset(self.collectionView.contentOffset, animated:false) // Stops collection view if it was scrolling.
self.collectionView.reloadData()
}
var collectionViewOffset: CGFloat {
get { return collectionView.contentOffset.x }
set { collectionView.contentOffset.x = newValue }
}
}
Can anyone help me please?
Edit controller like below, you are calling too many reloadData.
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
self.tableView.layoutIfNeeded()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
//getSearchWords()
DispatchQueue.main.async {
self.tableView.reloadData()
}
self.tableView.layoutIfNeeded()
}
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
}
and add:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView .deselectRow(at: indexPath, animated: false)
}

Resources