Passing a variable with dynamic data from UITableViewCell to SwiftUI View - swift

in my app I am storing a variable with different finger measurements. The different finger measurements have values in the UITableViewCell but they come up as nil in the SwiftUI View.
In the UITableViewCell, I made the variable a published variable. I then went to the SwiftUI View and tried #ObservedObject and then tried #StateObject when #ObservedObject didn't work. Again, logs in the UITableViewCell show values but logging in the SwiftUI View come up as nil and default to 0.
Below are snippets of code of the published var as well as the type. Then a snippet of the SwiftUI View where i try to pass the variable.
struct SaveNailImagesResponse: Codable {
var id: Int?
var leftIndexLength: Double?
var leftIndexSize: Int?
var leftIndexWidth: Double?
var leftMiddleLength: Double?
var leftMiddleSize: Int?
var leftMiddleWidth: Double?
var leftPinkyLength: Double?
var leftPinkySize: Int?
var leftPinkyWidth:
}
/// SNIPPET OF UITABLEVIEWCELL
class HandMeasurementsTableViewCell: UITableViewCell, ObservableObject {
#Published var fingerSizeData: SaveNailImagesResponse? {
didSet {
self.tableView.reloadData()
print(self.fingerSizeData?.leftIndexSize as Any)
print(self.fingerSizeData?.leftRingSize as Any)
print(self.fingerSizeData?.leftMiddleSize as Any)
}
}
}
/// HERE IS SNIPPET OF SWIFTUI VIEW: I tried passing it a 2 different ways below but comes up as nil and defaults to 0 every time
struct ResultsThumbnailView1: View {
#Environment(\.presentationMode) var presentationMode
#ObservedObject var data: HandMeasurementsTableViewCell = HandMeasurementsTableViewCell()
var body: some View {
VStack {
Text(String(self.data.fingerSizeData?.leftRingSize ?? 0))
Text("Size \(String(data.fingerSizeData?.leftIndexSize ?? 0))")
.font(.system(size: 19, weight: .bold))
}
}
}
// VIEW CONTROLLER WHERE EVERYTHING CONNECTS
class ResultsSizesViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var resultsData: SaveNailImagesResponse?
private var thumbnailButton: UIButton = {
let button = UIButton(type: .custom)
button.setImage(UIImage(systemName: "camera.circle"), for: .normal)
button.tintColor = .black
button.addTarget(self, action: #selector(presentThumbnailPage), for: .touchUpInside)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
["HandMeasurementsTableViewCell"].forEach( {
tableView.register(UINib.init(nibName: $0, bundle: nil), forCellReuseIdentifier: $0)
})
tableView.delegate = self
tableView.dataSource = self
setNavBar(backButtonAvailable: true, title: "Results")
setUI()
thumbnailButtonConstraints()
}
#objc func presentThumbnailPage() {
let vc = UIHostingController(rootView: ResultsThumbnailTabView())
vc.modalPresentationStyle = .fullScreen
self.navigationController?.present(vc, animated: true)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "HandMeasurementsTableViewCell") as? HandMeasurementsTableViewCell
let data = self.resultsData
cell?.fingerSizeData = data
if indexPath.row == 0 {
cell?.titleLabel.text = "Left Hand"
} else if indexPath.row == 1 {
cell?.titleLabel.text = "Right Hand"
}
return cell!
}
func thumbnailButtonConstraints() {
view.addSubview(thumbnailButton)
thumbnailButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
thumbnailButton.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 20),
thumbnailButton.trailingAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.trailingAnchor, constant: -20),
thumbnailButton.heightAnchor.constraint(equalToConstant: 20),
thumbnailButton.widthAnchor.constraint(equalToConstant: 20),
])
thumbnailButton.addTarget(self, action: #selector(presentThumbnailPage), for: .touchUpInside)
}
}

struct ResultsThumbnailView: View {
let resultsData: SaveNailImagesResponse
let vc = UIHostingController(rootView: ResultsThumbnailView(resultsData: resultsData))

Related

How to save array data locally

Here is my code. I want to learn how to save my dataSource for the like button of each cell. So that when the user leaves the app and returns later, the same cells that were liked remain liked.
This is new code from my last post. Since I don't want to keep making new arrays, I can try and locally save my dataSource variable which stores each cells Status of being liked or not.
ViewController -
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet var tableView: UITableView!
var dataSource: [TableModel] = []
var updatedCell = TableViewCell()
var updatedIndex = Int()
override func viewDidLoad() {
super.viewDidLoad()
overrideUserInterfaceStyle = .light
self.dataSource = Array(repeating: TableModel(isLiked: false), count: 8)
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.showsVerticalScrollIndicator = false
self.tableView.reloadData()
}
#IBAction func buttonSelected(_ sender: Any) {
// Update Cell for which UIButton (Like Button) was tapped.
dataSource[(sender as AnyObject).tag].isLiked = !dataSource[(sender as AnyObject).tag].isLiked
let indexPath = IndexPath(row: (sender as AnyObject).tag, section: 0)
tableView.reloadRows(at: [indexPath], with: .automatic)
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
// Saved updatedCell & updatedIndex variables for delegate pattern. To Update this VC's cells data when edited on secondVC (moreInfoViewController) in a way, made them accessible outside this function
// To Get Specific TableView Cell the user is interacting with.
updatedCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
updatedIndex = indexPath.row
// Go to Second VC and Send cell tapped data to next view
let vc = (storyboard?.instantiateViewController(identifier: "secondVC") as? moreInfoViewController)!
vc.delegate = self
// Get Status of Liked Button in the cell the user tapped and display if the user liked it previously in the SecondVC
let isLiked = dataSource[indexPath.row].isLiked
if isLiked {
// print("Liked")
vc.isLiked = true
} else {
// print("Not Liked")
vc.isLiked = false
}
present(vc, animated: true)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 8
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! TableViewCell
// cell.moreBtn.isUserInteractionEnabled = false
cell.likeBtn.tag = indexPath.row
// cell.likeBtn.addTarget(self, action: #selector(buttonSelected(_:)), for: .touchUpInside)
// Get Each Cell Liked Button Status and display if the user liked or not Liked each cell
let isLiked = dataSource[indexPath.row].isLiked
if isLiked {
// User liked the post
cell.likeBtn.setImage(UIImage(named: "liked"), for: UIControl.State.normal)
} else {
// User Unliked the post
cell.likeBtn.setImage(UIImage(named: "unLiked"), for: UIControl.State.normal)
}
return cell
}
}
// Conform VC to protocol (VC2Delegate) located in "Structs.swift" File
extension ViewController: VC2Delegate {
func likeStatusDidChange(_ vc2: moreInfoViewController, to title: Bool) {
// set the text of the table cell here...
dataSource[updatedIndex].isLiked = !dataSource[updatedIndex].isLiked
let indexPath = IndexPath(row: updatedIndex, section: 0)
tableView.reloadRows(at: [indexPath], with: .automatic)
}
}
moreInfoViewController -
import UIKit
class moreInfoViewController: UIViewController {
#IBOutlet var backBtn: UIButton!
#IBOutlet var titleLabel: UILabel!
#IBOutlet var locationLabel: UILabel!
#IBOutlet var theImage: UIImageView!
#IBOutlet var mainlikeBtn: UIButton!
#IBOutlet var mainTypeLbl: UILabel!
var currentID:String = ""
var isLiked = Bool()
weak var delegate: VC2Delegate?
override func viewDidLoad() {
super.viewDidLoad()
overrideUserInterfaceStyle = .light
self.navigationController?.setNavigationBarHidden(true, animated: true)
styles()
// "isLiked" variable to display whether or user liked this event
if (isLiked == true) {
// is Liked
mainlikeBtn.setImage(UIImage(named: "liked"), for: UIControl.State.normal)
} else {
// Not Liked
mainlikeBtn.setImage(UIImage(named: "unLiked"), for: UIControl.State.normal)
}
}
// Heart/Like Button Action. User can like event in this VC with this button and it will tell the firstVC (ViewController) to update "Like Status" there also
#IBAction func likeBtnAction(_ sender: Any) {
if (isLiked == true) {
// is Liked
isLiked = false
mainlikeBtn.setImage(UIImage(named: "unLiked"), for: UIControl.State.normal)
} else {
isLiked = true
mainlikeBtn.setImage(UIImage(named: "liked"), for: UIControl.State.normal)
}
// When User interacts with like Button, this function gets called that tells the firstVC (ViewController) to update as well.
// likeStatusDidChange function is located at the bottom of the (ViewController) with extension ViewController.
delegate?.likeStatusDidChange(self, to: true)
}
// Go Back To FirstVC (ViewController)
#IBAction func previousVC(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
func styles() {
titleLabel.numberOfLines = 1
titleLabel.adjustsFontSizeToFitWidth = true
locationLabel.numberOfLines = 1
locationLabel.adjustsFontSizeToFitWidth = true
backBtn.transform = CGAffineTransform(rotationAngle: -CGFloat.pi / 2)
theImage.layer.borderColor = UIColor.black.cgColor
theImage.layer.borderWidth = 2
theImage.layer.cornerRadius = 10
}
}
When you get array from userdefaults it gives you Any type array so you need to cast it to Int array and check it nil or not before you use. So you can use this code block.
if let savedDataKey = UserDefaults.standard.array(forKey: "savedDataKey") as? [Int] {
print(savedDataKey)
}

xCode Like-button won't be created in table cell (EXC_BAD_ACCESS (code=2, address=0x7fff86e8d750))

Does anyone know why the code complains when I run the simulator of the application in xCode v12?
I get the error message on the line:
cell.likeControl.isFavored = request.isFavored <== Thread 1: EXC_BAD_ACCESS (code=2, address=0x7fff86e8d750)
The code will run fine when I comment out the line.
SOURCE CODE
RequestTableViewController.swift
import UIKit
class RequestTableViewController: UITableViewController {
//MARK: Properties
var requests = [Request]()
override func viewDidLoad() {
super.viewDidLoad()
loadSampledData()
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem
}
(...)
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Table view cells are reused and should be dequeued using a cell identifier.
let cellIdentifier = "RequestTableViewCell"
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? RequestTableViewCell else {
fatalError("The dequeued cell is not an instance of RequestTableViewCell.")
}
// Fetches the appropriate request for the data source layout.
let request = requests[indexPath.row]
cell.wordLabel.text = request.word
cell.countLabel.text = String(request.count)
cell.likeControl.isFavored = request.isFavored
return cell
}
//MARK: Private methods
private func loadSampledData() {
guard let request1 = Request(word: "Ghetto", count: 5, isFavored: false) else {
fatalError("Unable to instantiate request1")
}
guard let request2 = Request(word: "Skyskraber", count: 0, isFavored: false) else {
fatalError("Unable to instantiate request2")
}
guard let request3 = Request(word: "Hjem", count: 1, isFavored: true) else {
fatalError("Unable to instantiate request3")
}
print(requests)
requests += [request1, request2, request3]
}
}
RequestTableViewCell.swift
import UIKit
class RequestTableViewCell: UITableViewCell {
#IBOutlet weak var wordLabel: UILabel!
#IBOutlet weak var countLabel: UILabel!
#IBOutlet weak var thumbsControl: ThumbsControl!
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
}
}
LikeControl.swift
import UIKit
#IBDesignable class LikeControl: UIStackView {
//MARK: Properties
private var thumbsImage = UIButton()
var isFavored = false
//MARK: Initialization
override init(frame: CGRect) {
super.init(frame: frame)
setupButton()
}
required init(coder: NSCoder) {
super.init(coder: coder)
setupButton()
}
//MARK: Button action
#objc func likeButtonTapped(button: UIButton) {
isFavored.toggle()
print("Button updated")
}
//MARK: Private Methods
private func setupButton() {
let bundle = Bundle(for: type(of: self))
let emptyUp = UIImage(named: "thumbs-up-regular", in: bundle, compatibleWith: self.traitCollection)
let filledUp = UIImage(named: "thumbs-up-solid", in: bundle, compatibleWith: self.traitCollection)
let highlightedUp = emptyUp?.withTintColor(.blue)
let emptyDown = UIImage(named: "thumbs-down-regular", in: bundle, compatibleWith: self.traitCollection)
let button = UIButton()
button.setImage(emptyUp, for: .normal)
button.setImage(filledUp, for: .selected)
button.setImage(highlightedUp, for: .highlighted)
button.setImage(emptyDown, for: [.highlighted, .selected])
// Setup the button action
button.addTarget(self, action: #selector(LikeControl.likeButtonTapped(button:)), for: .touchUpInside)
print("Button created")
}
}
Request.swift
import Foundation
class Request {
//MARK: Properties
var word: String
var count: Int
var isFavored: Bool
//MARK: Initialization
init?(word: String, count: Int, isFavored: Bool) {
guard !word.isEmpty else {
return nil
}
guard count >= 0 else {
return nil
}
guard !isFavored || (isFavored && count > 0) else {
return nil
}
self.word = word
self.count = count
self.isFavored = isFavored
}
}

Creating a JTAppleCalendar inside a xib view

I'm trying to create a calendar using JTAppleCalendar inside a xib view because I want a paging type thing for it. On the first page is some information, and the second page is the calendar. I followed the tutorials for JTAppleCalendar on multiple sites, but my project always crashes, probably because I'm doing something wrong.
I have 3 files, a DetailViewController for setting up and displaying the pages, a dataViewController to connect the xib vars, and a CollectionViewCell for the calendar cells.
DetailViewController
import UIKit
import JTAppleCalendar
class DetailViewController: UIViewController {
var sportName: String = ""
var numClasses: Int = 0
var pages : [dataViewController]{
get {
let page1: dataViewController = Bundle.main.loadNibNamed("dataView", owner: self, options: nil)?.first as! dataViewController
page1.label.text = sportName
page1.classDuration.text = String(numClasses)
let page2: dataViewController = Bundle.main.loadNibNamed("secondDataView", owner: self, options: nil)?.first as! dataViewController
page2.calendar.calendarDataSource = self as? JTACMonthViewDataSource
page2.calendar.calendarDelegate = self as? JTACMonthViewDelegate
page2.calendar.reloadData()
return [page1, page2]
}
}
#IBOutlet weak var detailDescriptionLabel: UILabel!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var pageControl: UIPageControl!
func configureView() {
// Update the user interface for the detail item.
if let detail = detailItem {
if let label = detailDescriptionLabel {
label.text = detail.description
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let back = UIBarButtonItem(title: "Back",style: .plain,target: self,action: #selector(backButton(_:)))
self.navigationItem.leftBarButtonItem = back
configureView()
view.bringSubviewToFront(pageControl)
setupScrollView(pages: pages)
pageControl.numberOfPages = pages.count
pageControl.currentPage = 0
}
var detailItem: String? {
didSet {
// Update the view.
configureView()
}
}
#objc
func backButton (_ sender: Any) {
performSegue(withIdentifier: "detailToList", sender: self)
}
func setupScrollView(pages: [dataViewController]){
scrollView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height)
scrollView.contentSize = CGSize(width: view.frame.width * CGFloat(pages.count), height: view.frame.height)
scrollView.isPagingEnabled = true
for i in 0 ..< pages.count {
pages[i].frame = CGRect(x: view.frame.width * (CGFloat(i)), y: 0, width: view.frame.width, height: view.frame.height)
scrollView.addSubview(pages[i])
}
}
}
extension DetailViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let pageIndex = round(scrollView.contentOffset.x/view.frame.width)
pageControl.currentPage = Int(pageIndex)
}
}
extension dataViewController: JTACMonthViewDataSource, JTACMonthViewDelegate {
func configureCalendar(_ calendar: JTACMonthView) -> ConfigurationParameters {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy MM dd"
formatter.timeZone = Calendar.current.timeZone
formatter.locale = Calendar.current.locale
let startDate = formatter.date(from: "2020 01 01")!
let endDate = Date()
return ConfigurationParameters(startDate: startDate, endDate: endDate)
}
func calendar(_ calendar: JTACMonthView, cellForItemAt date: Date, cellState: CellState, indexPath: IndexPath) -> JTACDayCell {
let cell = calendar.dequeueReusableJTAppleCell(withReuseIdentifier: "dateCell", for: indexPath) as! CollectionViewCell
cell.dateLabel.text = cellState.text
return cell
}
func calendar(_ calendar: JTACMonthView, willDisplay cell: JTACDayCell, forItemAt date: Date, cellState: CellState, indexPath: IndexPath) {
let cell = cell as! CollectionViewCell
cell.dateLabel.text = cellState.text
}
}
dataViewController
import JTAppleCalendar
class dataViewController: UIView {
//Page 1
#IBOutlet weak var label: UILabel!
#IBOutlet weak var classDuration: UILabel!
//Page 2
#IBOutlet weak var calendar: JTACMonthView!
}
CollectionViewCell
import UIKit
import JTAppleCalendar
class CollectionViewCell: JTACDayCell {
#IBOutlet weak var dateLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}
And of course, the xib files. In DetailViewController, I moved the last extension part to dataViewController, but it didn't change anything. I'm also pretty sure I did many things wrong or inefficiently.
Can anyone help successfully implement the JTAppleCalendar inside the xib view, that would be appreciated! Thanks!
In your DetailViewController You are setting delegate and dataSource of calendar to self which is not conforming those protocols.
page2.calendar.calendarDataSource = self as? JTACMonthViewDataSource
page2.calendar.calendarDelegate = self as? JTACMonthViewDelegate
If thoose are needed to be handled in DetailViewController, I suggest you to start with implementing methods in DetailViewController not in dataViewController
extension DetailViewController: JTACMonthViewDataSource, JTACMonthViewDelegate

Best Approach to make Calculation in tableviewcells and sums up in UILabel

My Cart looks like this
What should be the best approach to do calculation of all cells and sums up total Amount label
Cart Working like this :
Increment in cell's item doubles the value of price label but when i dequeue new cell it already has that increment value
When tried to work with custom delegate , Delegate always shows nil
What should I do ? why my delegate is always nil ?
TableViewCell
class ShoppingCartCell: UITableViewCell {
#IBOutlet weak var cellView:UIView!
#IBOutlet weak var productImageView:UIImageView!
#IBOutlet weak var productName:UILabel!
#IBOutlet weak var brandName:UILabel!
#IBOutlet weak var productPrice:UILabel!
#IBOutlet weak var modifier1Lbl:UILabel!
#IBOutlet weak var modifier2Lbl:UILabel!
#IBOutlet var counterBtns:[UIButton]!
#IBOutlet weak var counterLbl:UILabel!
var delegate : cellDelegateFunc?
override func layoutMarginsDidChange() {
super.layoutMarginsDidChange()
contentView.frame = contentView.frame.inset(by: UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10))
productImageView.layer.cornerRadius = productImageView.frame.height / 4
cellView.roundUIViewWithShadow(cornerRadius: 4, shadowColor: .darkGray)
cellView.layer.masksToBounds = false
cellView.layer.shadowColor = UIColor.lightGray.cgColor
cellView.layer.shadowOpacity = 1
cellView.layer.shadowOffset = .zero
}
override func awakeFromNib() {
super.awakeFromNib()
cellView.layer.cornerRadius = cellView.frame.height / 16
productImageView.layer.cornerRadius = productImageView.frame.height / 16
}
#IBAction func counter(_ sender:UIButton){
self.delegate?.countItems(self)
}
}
CartViewController (Particular Portion)
class ShoppingBagVC: UIViewController , cellDelegateFunc {
func countItems(_ cell: ShoppingCartCell) {
print("print")
}
}
Protocol
protocol cellDelegateFunc : class {
func countItems(_ cell:ShoppingCartCell)
}
CellForRow
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if cartAllData[indexPath.row].deal.data != nil {
let cell = cartTableView.dequeueReusableCell(withIdentifier: "cell3", for: indexPath) as! ShoppingCartDealCell
cell.originalPrice = Int(cartAllData[indexPath.row].deal.data!.dealPrice)
cell.productName.text = cartAllData[indexPath.row].deal.data?.dealName
cell.productPrice.text = "Rs.\(String(cell.originalPrice))"
cell.freeItem.text = cartAllData[indexPath.row].deal.data?.freeProduct
cell.productImageView?.sd_setImage(with: URL(string: cartAllData[indexPath.row].deal.data!.imageURL), completed: nil)
return cell
} else {
let cell = cartTableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath) as! ShoppingCartCell
var originalPrice = Int()
var price : Int = 2{
didSet {
cell.productPrice.text = "Rs.\(String(price))"
}
}
var count : Int = 1{
didSet {
cell.counterLbl.text = String(count)
price = originalPrice * count
}
}
if let value = cartAllData[indexPath.row].deal.data?.quantity {
cell.counterLbl.text = String(value)
}
if let value = cartAllData[indexPath.row].product.data?.quantity {
cell.counterLbl.text = String(value)
}
originalPrice = Int(cartAllData[indexPath.row].product.data!.productBasePrice)
cell.productPrice.text = "Rs.\(String(originalPrice))"
cell.productName.text = cartAllData[indexPath.row].product.data?.productName
cell.productImageView?.sd_setImage(with: URL(string: cartAllData[indexPath.row].product.data!.imageURL), completed: nil)
cell.modifier1Lbl.text = cartAllData[indexPath.row].product.data?.modifier1
cell.modifier2Lbl.text = cartAllData[indexPath.row].product.data?.modifier2
return cell
}
}
As #joakim said in comment you are doing calculations in a UI! and it's not a correct way
When a UITableView scrolls every cell will reload because of reusing and every cell will lose its state because it loads again. so you must store state of each cell in a Model and pass it to your cell each time a cell loads.
As you requested The Best approach would be to use a ViewModel or a Presenter to store state of a View (here your cell) and in every load you feed that View (for example in your cellForRow) with the stored States or Properties

How to prevent cells from mirroring button pressed action in another cell? Part #2

This would be part # 2 of my question How to prevent cells from mirroring button pressed action in another cell?
What im trying to do is have my buttons have a button pressed turn red while a previously selected button deselects to back to blue, and also preventing it from mirroring the pressed button action in another cell, I have achieved that in a previous question I posted
what Im trying to do is integrate this with classes that pass data from Firebase Firestore. since I don't know where to go to convert this prevent the cells from mirroring the same button select action in another and changes the button selected to red and automatically deselects previous button back to blue
I have been stuck trying to make this work and just not getting the right luck to make it happen, I have been getting error codes in 3 different areas in ViewController preventing my code from compiling and making it work so that it works with my cells that pass data to labels from my cloud Firestore
any help would be appreciated and thank you for your time
import Foundation
import UIKit
class Labels {
var id: String
var lbl1: String
var lbl2: String
var lbl3: String
init(id: String,
lbl1: String,
lbl2: String,
lbl3: String) {
self.id = id
self. lbl1 = lbl1
self. lbl2 = lbl2
self. lbl3 = lbl3
}
convenience init(dictionary: [String : Any]) {
let id = dictionary["id"] as? String ?? ""
let lbl1 = dictionary["lbl1"] as? String ?? ""
let lbl2 = dictionary["lbl2"] as? String ?? ""
let lbl3 = dictionary["lbl3"] as? String ?? ""
self.init(id: id,
lbl1: lbl1,
lbl2: lbl2,
lbl3: lbl3)
}
}
enum ButtonSelectionIdentity {
case first
case second
case third
}
struct CellModel {
let buttonSelectionIdentity: ButtonSelectionIdentity
let labels: Labels
}
import UIKit
import SDWebImage
import Firebase
protocol OptionSelectDelegate: class {
func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity)
}
class Cell: UITableViewCell {
weak var labels: Labels!
private var elements: [ButtonSelectionIdentity] = []
weak var optionSelectDelegate: OptionSelectDelegate?
#IBOutlet weak var lbl1: UILabel!
#IBOutlet weak var lbl2: UILabel!
#IBOutlet weak var lbl3: UILabel!
#IBOutlet weak var btnOne: RoundButton!
#IBOutlet weak var btnTwo: RoundButton!
#IBOutlet weak var btnThree: RoundButton!
func configure(withLabels labels: Labels) {
lbl1.text = labels.lbl1
lbl2.text = labels.lbl2
lbl3.text = labels.lbl3
}
override func layoutSubviews() {
super.layoutSubviews()
}
func update(with model: ButtonSelectionIdentity) {
btnOne.backgroundColor = UIColor.blue
btnTwo.backgroundColor = UIColor.blue
btnThree.backgroundColor = UIColor.blue
switch model {
case .first:
btnOne.backgroundColor = UIColor.red
case .second:
btnTwo.backgroundColor = UIColor.red
case .third:
btnThree.backgroundColor = UIColor.red
}
}
#IBAction func optionSelectOne(_ sender: RoundButton!) {
optionSelectDelegate?.onCellModelChange(cell: self, model: .first)
}
#IBAction func optionSelectTwo(_ sender: RoundButton!) {
optionSelectDelegate?.onCellModelChange(cell: self, model: .second)
}
#IBAction func optionSelectThree(_ sender: RoundButton!) {
optionSelectDelegate?.onCellModelChange(cell: self, model: .third)
}
}
import UIKit
import Firebase
import FirebaseFirestore
class ViewController: UIViewController {
private var elements: [CellModel] = []
#IBOutlet weak var tableView: UITableView!
var labelSetup: [Labels] = []
override func viewDidLoad() {
super.viewDidLoad()
//▼ Cannot convert value of type 'ButtonSelectionIdentity' to expected argument type 'CellModel'
elements.append(ButtonSelectionIdentity.first) // error one
tableView.dataSource = self
tableView.delegate = self
fetchLabels { (labels) in
self.labelSetup = labels.sorted(by:
self.tableView.reloadData()
}
}
func fetchLabels(_ completion: #escaping ([Labels]) -> Void) {
let ref = Firestore.firestore().collection("labels")
ref.addSnapshotListener { (snapshot, error) in
guard error == nil, let snapshot = snapshot, !snapshot.isEmpty else {
return
}
completion(snapshot.documents.compactMap( {Labels(dictionary: $0.data())} ))
}
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return labelSetup.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as? Cell else { return UITableViewCell() }
cell.configure(withLabels: labelSetup[indexPath.row])
cell.optionSelectDelegate = self
let model = elements[indexPath.row]
//▼ Cannot convert value of type 'CellModel' to expected argument type 'ButtonSelectionIdentity'
cell.update (with: CellModel) //error 2
return cell
}
}
extension ViewController: OptionSelectDelegate {
func onCellModelChange(cell: Cell, model: ButtonSelectionIdentity) {
guard let indexPath = productListTableView.indexPath(for: cell) else {
return
}
let index = indexPath.row
elements[index] = model
//▼ Cannot assign value of type 'ButtonSelectionIdentity' to type 'CellModel'
cell.update(with: model) //error 3
}
}