Using Delegates to Transfer Data from One Tableview to Another

Passing data from one custom uitableviewcell to another using Delegates in swift

It doesn't work because in AlbumCell you create another instance of AlbumsPickerTableViewCell and use it for delegation.

Generally speaking, implementing a delegate from one cell to another doesn't feel right. You can quickly find yourself in the situation when you need the value from the first cell in the controller and have no way of obtaining it. Also, a strange behaviour can occur if those cells are going to be reused by table view.

In your case, it worth making UIViewController which contains UITableView a delegate of AlbumsPickerTableViewCell, and when it gets called from the cell, pass data into AlbumCell.

Also, don't forget that references to the delegate should be weak to prevent strong reference cycle.

Passing data from one Custom TableView Cell to another using delegates and protocols

The proper way of updating a tableview/collectionviewcell is to reload the particular cell. And you should always maintain a data represent your table view cells since your cells are not persistent and re-usable. You can use that data to populate the properties of your cell when it is created.

In your case, date is the data needs to be persisted. In this scenario, you could simply have that as a field in your controller.

import UIKit

class DateLabelCell: UITableViewCell {

@IBOutlet var dateLabel: UILabel!

override func awakeFromNib() {
super.awakeFromNib()
}

func setDate(_ text: String) {
dateLabel.text = text
}

override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
class TableViewController: UITableViewController {
var date: String = "Date"

.......

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "DateLabelCell", for: indexPath) as! DateLabelCell
cell.setDate(self.date)
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "DatePickerCell", for: indexPath) as! DatePickerCell
cell.dateDelegate = self
return cell
}
}

}
extension TableViewController: DatePickerDelegate {
func setDate(_ text: String) {
self.date = text
tableView.reloadRows(at: [IndexPath(item: 0, section: 0)], with: .automatic)
}
}

Passing data from Table view cell using button delegate

The problem is you don't update you're global properties when selecting each of you're row,

If you pass data over cell delegate and pass you're cell through delegate, you can pass data from cell like:

    customViewController?.titlemovie = cell.movieTitle.text ?? ""
customViewController?.imagemovie = cell.movieImage.image
customViewController?.overview = cell.movieOverview.text ?? ""

of course it would be better to pass you're data model to you're cell. and then share that through you're delegate not share you're cell, like:

protocol CellSubclassDelegate: AnyObject {
func buttonTapped(cell: MovieModel)
}

Pass data from tableView Cell to another view controller using delegate protocol

Just simply take a variable for value to be passed in your another Viewcontroller, then while pushing just pass the value.

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
let vc = self.storyboard.instantiateViewController(withIdentifier: "AnotherVC") as! AnotherVC
vc.variable = your value
self.navigationController?.pushViewController(vc, animated: true)
}

Why do you need to use protocols?

how to use delegate to pass data to from one View Controller to another?

Update following line in cellForRowAt function:

cartCell.modifyItems = self.modifyItems

to this:

cartCell.modifyItems = itemsToDisplay

Pass data back to previous VC using delegates and update custom cell

Check below corrected code:

MainVC:

import UIKit

class MainVC: UIViewController, UITableViewDelegate, UITableViewDataSource, DataSentDelegate {

@IBOutlet weak var deliveryAddress: UITableView!

//Create array which will return your address data
var addressArr = [DeliveryDestinations]()

override func viewDidLoad() {
super.viewDidLoad()
deliveryAddress.delegate = self
deliveryAddress.dataSource = self
deliveryAddress.reloadData()
}

//add parameter for created address object
func userDidEnterData(addressObj: DeliveryDestinations) {

//append added object into your table array
self.addressArr.append(addressObj)
//Reload your tableview once your new object added.
self.deliveryAddress.reloadData()
}

func numberOfSections(in tableView: UITableView) -> Int {
return 1
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

//change this with array count
return addressArr.count
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "deliveryAddressCell", for: indexPath) as! AddressCell

//get address object from array which you can assign to cell
let addressObj = addressArr[indexPath.row]
//assign data from array
cell.updateUI(addressObj: addressObj)
return cell
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 165
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "addDeliveryAddressVC" {
let addDestination:AddingDestinationVC = segue.destination as! AddingDestinationVC
addDestination.delegate = self
}
}
}

AddingDestinationVC:

import UIKit

protocol DataSentDelegate {
//Replace parameter with DeliveryDestinations
func userDidEnterData(addressObj: DeliveryDestinations)
}

class AddingDestinationVC: UIViewController {

@IBOutlet weak var firstLineAddressTextField: UITextField!
@IBOutlet weak var secondLineAddressTextField: UITextField!
@IBOutlet weak var cityLineAddressTextField: UITextField!
@IBOutlet weak var postcodeLineAddressTextField: UITextField!

var delegate: DataSentDelegate?

override func viewDidLoad() {
super.viewDidLoad()

// Do any additional setup after loading the view.
}

@IBAction func addBtnWasPressed(_ sender: Any) {
if delegate != nil {
if firstLineAddressTextField.text != nil {

//Create Model object DeliveryDestinations
let addressObj = DeliveryDestinations(FirstLineAddress: firstLineAddressTextField.text, SecondLineAddress: secondLineAddressTextField.text, CityLineAddress: cityLineAddressTextField.text, PostCodeLineAddress: postcodeLineAddressTextField.text)
//add that object to previous view with delegate
delegate?.userDidEnterData(addressObj: addressObj)
navigationController?.popViewController(animated: true)
}
}
}
}

AddressCell:

class AddressCell: UITableViewCell {

@IBOutlet weak var firstLineAddressLbl: UILabel!
@IBOutlet weak var secondLineAddressLbl: UILabel!
@IBOutlet weak var cityLineAddressLbl: UILabel!
@IBOutlet weak var postcodeLineAddressLbl: UILabel!
@IBOutlet weak var numberLbl: UILabel!
@IBOutlet weak var startBtn: UIButton!
@IBOutlet weak var distanceLbl: UILabel!
@IBOutlet weak var metricLbl: UILabel!

func updateUI(addressObj: DeliveryDestinations) {

//Drow your cell with values from addressObj
firstLineAddressLbl.text = addressObj.FirstLineAddress
secondLineAddressLbl.text = addressObj.SecondLineAddress
cityLineAddressLbl.text = addressObj.CityLineAddress
postcodeLineAddressLbl.text = addressObj.PostcodeLineAddress
}
}

And your result will be:

Sample Image

And here is your updated code.

How to pass using delegates in a tableview through the footer cell?

Using delegates is probably a good idea. I just wrote some code (not tested!) to give you an idea how it could work:

Extend the delegate class:

protocol CalculationDelegate: class {
func onTouchInfoButton(from cell: CalorieFooter)
func getAdditionalCalories() -> Int
func getCalculations() -> Int // or whatever type this object should be
}

Make sure your view controller follows the protocol:

extension CalorieViewController: CalculationDelegate { 
func onTouchInfoButton(from cell: CalorieFooter) { ... }
func getAdditionalCalories() -> Int {
return self.calories
}
func getCalculations() -> Int {
return self.calculations
}
}

Add local variables to CalorieViewController that stores the current state (amount of calories/calculations)

class CalorieViewController: UIViewController {
private var calories: Int = 0
private var calculations: Int = 0

... other code that is already in the UIViewController
}

Make sure to initialize these variables somewhere! Something like:

func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
... same as before...

self.calories = subtotal // I guess?
self.calculations = calculations // put this somewhere where calculations is initialized
}

Now, the data should be available inCalorieFooter. I added the default values 0 for when the calculationDelegate is nil:

let calories = calculationDelegate?.getAdditionalCalories() ?? 0
let calculations = calculationDelegate?.getCalculations() ?? 0

Good luck!

passing data delegates and protocols swift

According to your code, your delegate field is not set. ! will force the unwrap of the optional delegate field. Your have to set your delegate before call it.

Simply assign a value to it, or use optional chaining.

For example, you could:

  • set a value to delegate in the viewDidLoad() method, for example
override func viewDidLoad() {
super.viewDidLoad()
// HERE
self.delegate = ArtistViewController()
getItunesData()

tableView.dataSource = self
tableView.delegate = self
tableView.register(UINib(nibName: "artistCell", bundle: nil), forCellReuseIdentifier: "artistCell")
}
  • call the delegate only if it's set with delegate?.loadArtistViewModel(_:).

You may replace var delegate: artistViewModelDelegate! by var delegate: artistViewModelDelegate? to prevent this type of errors.



Related Topics



Leave a reply



Submit