How do I access stored properties from another UIViewController programmatically?

How can I add append addedItem in SecondViewController to items array in FirstViewController programmatically?

class FirstViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

     var items: [String] = []
}
class SecondViewController: UIViewController {

     let textField: UITextField = UITextField()
     let saveButton: UIButton = UIButton()

     @objc func saveButtonTapped() {
          let addedItem = textField.text
     }
}
Answered by AncientCoder in 708174022

I haven't used UIKit since SwiftUI arrived, but the below code should work.

Create a DataModel class for use as a singleton and put your items array into it:

import Foundation
class DataModel {
    static let shared = DataModel()
    var items: [String] = []
}

In your FirstViewController add a reference to the DataModel singleton, then use the items array as needed, e.g. in your UITableView

let dataModel = DataModel.shared 

Use dataModel.items in the UITableView

In the SecondViewController also add a reference to the DataModel singleton, then use this to append to items:

class SecondViewController: UIViewController {
     let dataModel = DataModel.shared
     let textField: UITextField = UITextField()
     let saveButton: UIButton = UIButton()
     @objc func saveButtonTapped() {
          dataModel.items.append(textField.text)
     }
}

However, using this method you then, presumably, need to force a reload of the FirstViewController's tableview. This can be done via delegation (which could also be used to send the new item for appending in the FirstViewController) or via Combine. If using Combine, the DataModel becomes:

import Foundation
import Combine

class DataModel {
    static let shared = DataModel()
    let itemAdded = PassthroughSubject<(String), Never>()
    
    var items: [String] = [] {
        didSet {
            itemAdded.send("ItemAdded")
        }
    }
}

and the FirstViewController needs to include Combine and to have

var itemSink : AnyCancellable? = nil
itemSink = dataModel.itemAdded.sink(receiveValue: { message in
            // you don't need to use message, but can be useful if you want to know about additions, deletions etc by sending different messages
            tableView.reloadData()
        })

at an appropriate place in your code, i.e. to force the Table Reload.

I haven't tested this with a real UIKit app and tableview, but it should work.

Regards, Michaela

Accepted Answer

I haven't used UIKit since SwiftUI arrived, but the below code should work.

Create a DataModel class for use as a singleton and put your items array into it:

import Foundation
class DataModel {
    static let shared = DataModel()
    var items: [String] = []
}

In your FirstViewController add a reference to the DataModel singleton, then use the items array as needed, e.g. in your UITableView

let dataModel = DataModel.shared 

Use dataModel.items in the UITableView

In the SecondViewController also add a reference to the DataModel singleton, then use this to append to items:

class SecondViewController: UIViewController {
     let dataModel = DataModel.shared
     let textField: UITextField = UITextField()
     let saveButton: UIButton = UIButton()
     @objc func saveButtonTapped() {
          dataModel.items.append(textField.text)
     }
}

However, using this method you then, presumably, need to force a reload of the FirstViewController's tableview. This can be done via delegation (which could also be used to send the new item for appending in the FirstViewController) or via Combine. If using Combine, the DataModel becomes:

import Foundation
import Combine

class DataModel {
    static let shared = DataModel()
    let itemAdded = PassthroughSubject<(String), Never>()
    
    var items: [String] = [] {
        didSet {
            itemAdded.send("ItemAdded")
        }
    }
}

and the FirstViewController needs to include Combine and to have

var itemSink : AnyCancellable? = nil
itemSink = dataModel.itemAdded.sink(receiveValue: { message in
            // you don't need to use message, but can be useful if you want to know about additions, deletions etc by sending different messages
            tableView.reloadData()
        })

at an appropriate place in your code, i.e. to force the Table Reload.

I haven't tested this with a real UIKit app and tableview, but it should work.

Regards, Michaela

How do I access stored properties from another UIViewController programmatically?
 
 
Q