Reputation: 701
I want to understand why using a struct is causing this issue and a class does not. I encountered the issue when appending elements to array and having an observer load a table. Here are the codes:
Order.swift - items ordered
struct Order {
var menuItems: [MenuItem]
init(menuItems: [MenuItem] = []) {
self.menuItems = menuItems
}
}
MenuController.swift - contains the order and a shared instance
struct MenuController {
static var shared: MenuController = MenuController()
static let orderNotification = Notification.Name("MenuController.orderUpdated")
var order = Order() {
didSet {
NotificationCenter.default.post(name: MenuController.orderNotification,
object: nil)
}
}
MenuItemViewController.swift - ordering screen
@IBAction func orderButtonTapped(_ sender: UIButton) {
MenuController.shared.order.menuItems.append(menuItem)
}
OrderTableViewController.swift - items ordered screen
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(tableView,
selector: #selector(UITableView.reloadData),
name: MenuController.orderNotification, object: nil)
}
...
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return MenuController.shared.order.menuItems.count //Simultaneous access error thrown here
}
Now, I made a design mistake where MenuController should be a class instead of a struct because we're gonna be sharing MenuController instance throughout the app hence it should be a reference type. Using a class solved the simultaneous access issue.
What I am confused about is : Why is a value-typed (struct) MenuController causing this simultaneous access issue when observer try to load the tableView.
Hope someone can explain. TIA!
Upvotes: 4
Views: 2365
Reputation: 2067
My case was different than @bauerMusic 's answer.
I put my related code in a DispatchQueue.main.async
block (main thread) & it is solved.
So was a thread issue for my case.
Upvotes: 0
Reputation: 6166
It has to do with 'Exclusive Access to Memory' and is explaind well here:
Simultaneous accesses to 0x1c0a7f0f8, but modification requires exclusive access error on Xcode 9 beta 4
The short version: A var cannot be 'readable' and 'writeable' at the same time. When a set
action starts, the var is 'writeable', if a get
action occur ('readable') while the var is still 'writeable', it will trigger an exception.
On didSet
, var is 'writeable'. If actions in didSet
leads somewhere in the call stack to the var being read, it will trigger the exception.
Even without a didSet
, if you have a mutating function that sets a var and then post a notification, where the observer of the notification will attempt to read it, same exception will be triggered.
Upvotes: 6