skip to Main Content

I’m stuck with a problem now and I need some help.
Currently, I have two different view controllers in my project, VC1 and VC2. In the project, I have both a navigation bar and a tab bar.

In the VC1, I have a UIViewController class and it contains a UITableView and the tablaViewCell. Also, I add an array of liveEvents like below.

 public var liveEvents: [LiveEvent] = [
    LiveEvent(title: "aaaa"),
    LiveEvent(title: "bbbbbb"),
    LiveEvent(title: "ccccccc")
]

Then, from the cell, I added the segue to the VC2. In the VC2, I added the IBaction to barbutton item like below.

@IBOutlet weak var eventTitle: UITextField!

@IBAction func saveNewLiveEvent(_ sender: Any) {
    
    if let eventTitle = eventTitle.text {
        let vc = VC1()
        vc.liveEvents.append(LiveEvent(title: eventTitle))
        print("liveEvent: (vc.liveEvents)")
        navigationController?.popViewController(animated: true)
    }
}

and I tried to append an event in the liveEvent array in the VC1.

In the console, I can see the new event is appended in VC2, however, when I add the print statement in the VC1, I don’t see the new added value is appended (also, the new value is not reflected on the table view.) when I back from VC2 to VC1.

I was wondering how to append the value to an array which is in the different swift file.

If you know what I’m doing wrong, please let me know.

2

Answers


  1. You created a new instance of VC1 in VC2, it’s not the same instance you pushed from. So, that’s the reason your table isn’t updating.

    You can use delegation approach to achieve your result. I have created a demo code for this, please check below.

    TestController1 (or VC1)-

    import UIKit
    
    class LiveEvent{
        var title:String
        
        init(title:String) {
            self.title = title
        }
    }
    
    class TestController: UIViewController {
        
        @IBOutlet weak var testTableView: UITableView!
        
        public var liveEvents: [LiveEvent] = [
            LiveEvent(title: "aaaa"),
            LiveEvent(title: "bbbbbb"),
            LiveEvent(title: "ccccccc")
        ]
        
        override func viewDidLoad() {
            super.viewDidLoad()
        }
        
    }
    
    extension TestController:UITableViewDelegate,UITableViewDataSource{
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            liveEvents.count
        }
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TestTableCell
            cell.eventLabel.text = liveEvents[indexPath.row].title
            return cell
        }
        
        override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            let destinationVC = segue.destination as? TestControllerTwo
            destinationVC?.delegate = self
        }
        
    }
    
    
    extension TestController:AddEventsInVC1{
        func addNewEvent(event: LiveEvent) {
            liveEvents.append(event)
            testTableView.reloadData()
        }
    }
    

    TestController2 (or VC2)-

    import UIKit
    
    protocol AddEventsInVC1:AnyObject {
        func addNewEvent(event:LiveEvent)
    }
    
    class TestControllerTwo: UIViewController {
        
        weak var delegate:AddEventsInVC1?
        
        override func viewDidLoad() {
            super.viewDidLoad()
        }
        
        
        @IBAction func addEventAndPop(_ sender: Any) {
            
            delegate?.addNewEvent(event: LiveEvent(title: "I am New"))
            navigationController?.popViewController(animated: true)
        }
        
    }
    

    CustomCellClass-:

    import UIKit
    
    class TestTableCell: UITableViewCell {
    
        @IBOutlet weak var eventLabel: UILabel!
        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
        }
    
    }
    

    The Storyboard design is simple, I just have TableView with single cell, having a label in it.

    I have connected segue in storyboard itself from cell to VC2 for demo purpose.

    Login or Signup to reply.
  2. Here is a solution for you. In short, you cannot create new instance of VC1 as you did in VC2. You need existing instance which can be achieve using protocol approach. Check the code. This will fix you issue.

    // 1) Protocol to connect two controllers VC1 and VC2
    // You can add protocol code in your VC1 class or you can create new .swift file and add there as well.
    protocol LiveEventProtocol: AnyObject {
        func addEvent(_ liveEvent: LiveEvent)
    }
    
    class VC1: UIViewController, LiveEventProtocol {
        
        public var liveEvents: [LiveEvent] = [
            LiveEvent(title: "aaaa"),
            LiveEvent(title: "bbbbbb"),
            LiveEvent(title: "ccccccc")
        ]
        
        // 2) go to vc2 but don’t forget to set vc2.delegate = self
        // ⭐️ That is the key here.
        // `vc2.delegate = self` connects VC1 and VC2
        func gotoVC2() {
            let vc2 = VC2()
            vc2.delegate = self
            self.navigationController?.pushViewController(VC2(), animated: true)
        }
        
        // 3) Implementing protocol method.
        // This is a method where VC2 will delegate work to VC1 to append liveEvent.
        func addEvent(_ liveEvent: LiveEvent) {
            self.liveEvents.append(liveEvent)
            // now do your reload stuff.
        }
    }
    
    class VC2: ViewController {
        weak var delegate: LiveEventProtocol?
        var eventTitle = UITextField(frame: .zero)
        
        func saveNewLiveEvent() {
            if let eventTitle = eventTitle.text {
                // ❌ this is wrong.
                // Reason,
                //  -> you are creating new instance of VC1
                //  -> Instead we need the existing instance of VC1.
                //  -> This can be achieve using protocol approach.
                // let vc = VC1()
                // vc.liveEvents.append(LiveEvent(title: eventTitle))
                
                // ✅ this is correct way to do it.
                // Here, we are justing passing LiveEvent value through delegate approach which is connected with VC1.
                delegate?.addEvent(LiveEvent(title: eventTitle))
                
                navigationController?.popViewController(animated: true)
            }
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search