arvinq
arvinq

Reputation: 701

Swift : Simultaneous accesses to 0x10959c600, but modification requires exclusive access on Structs

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

Answers (2)

Enes Karaosman
Enes Karaosman

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

bauerMusic
bauerMusic

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

Related Questions