Swift:同时访问0x10959c600,但修改需要对Structs的独占访问

时间:2018-11-09 04:55:39

标签: ios swift tableview observers

我想了解为什么使用结构会导致此问题,而类却没有。将元素追加到数组并让观察者加载表时遇到了问题。这是代码:

Order.swift-订购商品

struct Order {
    var menuItems: [MenuItem]
    init(menuItems: [MenuItem] = []) {
        self.menuItems = menuItems
    }
}

MenuController.swift-包含订单和共享实例

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-订购屏幕

@IBAction func orderButtonTapped(_ sender: UIButton) {
     MenuController.shared.order.menuItems.append(menuItem)
 }

OrderTableViewController.swift-物品订购屏幕

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
}

现在,我犯了一个设计错误,即MenuController应该是而不是结构,因为我们要在整个应用程序中共享MenuController实例,因此它应该是引用类型。使用类解决了同时访问问题。

我很困惑的是: 为什么当观察者尝试加载tableView时,值类型(结构)的MenuController会导致此同时访问问题。

希望有人可以解释。 TIA!

2 个答案:

答案 0 :(得分:2)

它与“对内存的独占访问权”有关,并在此处进行了很好的解释:
Simultaneous accesses to 0x1c0a7f0f8, but modification requires exclusive access error on Xcode 9 beta 4

简短版本:var不能同时“可读”和“可写”。当set操作开始时,变量是“可写的”,如果在变量var仍然是“可写”的情况下发生get操作(“可读”),则会触发异常。

didSet上,var是“可写的”。如果didSet中的操作导致调用堆栈中的某处导致正在读取的var,它将触发异常。

即使没有didSet,如果您具有设置var并随后发布通知的变异函数,该通知的观察者将尝试读取该通知,则将触发相同的异常。

答案 1 :(得分:0)

我的情况与@bauerMusic的回答不同。

我将相关代码放在DispatchQueue.main.async块(主线程)中,此问题已解决。

我的情况也是一个线程问题。