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

arv*_*inq 4 observers tableview ios swift

我想了解为什么使用结构会导致此问题,而类则不会。我在将元素附加到数组并让观察者加载表时遇到了问题。以下是代码:

Order.swift - 订购的商品

struct Order {
    var menuItems: [MenuItem]
    init(menuItems: [MenuItem] = []) {
        self.menuItems = menuItems
    }
}
Run Code Online (Sandbox Code Playgroud)

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

MenuItemViewController.swift - 订购屏幕

@IBAction func orderButtonTapped(_ sender: UIButton) {
     MenuController.shared.order.menuItems.append(menuItem)
 }
Run Code Online (Sandbox Code Playgroud)

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
}
Run Code Online (Sandbox Code Playgroud)

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

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

希望有人能解释一下。蒂亚!

bau*_*sic 6

它与“对内存的独占访问”有关,并在此处得到了很好的解释:
Simultaneous accesses to 0x1c0a7f0f8, but revisions require Exclusive access error on Xcode 9 beta 4

简而言之:var 不能同时“可读”和“可写”。当一个set动作开始时,变量是“可写”的,如果一个get动作发生(“可读”)而变量仍然是“可写”的,它将触发异常。

在 上didSet,var 是“可写的”。如果 in 中的操作didSet导致调用堆栈中的某个位置指向正在读取的 var,则会触发异常。

即使没有didSet,如果您有一个设置 var 的变异函数,然后发布通知,通知的观察者将尝试读取它,也会触发相同的异常。