简体   繁体   中英

append data into an array in different view controller in swift

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.

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.

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)
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM