Simultaneous accesses to 0x1c0a7f0f8, but modification requires exclusive access error on Xcode 9 beta 4

后端 未结 11 1832
孤城傲影
孤城傲影 2020-11-29 05:15

my project uses both Objective-C and Swift code. When a user logs in, it calls a set of apis for user preference, I have a DataCoordinator.swift class which schedules the AP

11条回答
  •  庸人自扰
    2020-11-29 05:45

    The answers by @Mark Bridges and @geek1706 are good answers but I would like to add my 2 cents about this matter and give a general example.

    As stated above this is a feature in Swift 4 SE-176.

    The implementation should still be permitted to detect concurrent conflicting accesses, of course. Some programmers may wish to use an opt-in thread-safe enforcement mechanism instead, at least in some build configurations.

    The exclusive access enforces that every write mutation of vars must be exclusive when accessing that variable. In a multithread environment, multiple threads accessing a shared var and one or more can modify it.

    There's nothing like a good example: If we try to mutate a shared value in a multi-threaded environment using an abstraction (mutation occurs on a protocol type) between 2 objects and the Exclusive Access to Memory is on, our app will crash.

    protocol Abstraction {
      var sharedProperty: String {get set}
    }
    
    class MyClass: Abstraction {
      var sharedProperty: String
    
      init(sharedProperty: String) {
         self.sharedProperty = sharedProperty
      }
    
      func myMutatingFunc() {
         // Invoking this method from a background thread
         sharedProperty = "I've been changed"
      }
    }
    
    
    class MainClass {
       let myClass: Abstraction
    
       init(myClass: Abstraction) {
         self.myClass = myClass
       }
    
       func foobar() {
          DispatchQueue.global(qos: .background).async {
             self.myClass.myMutatingFunc()
          }
       }
    }
    
    let myClass = MyClass(sharedProperty: "Hello")
    let mainClass = MainClass(myClass: myClass)
    // This will crash
    mainClass.foobar()
    

    Since we didn't state that the Abstraction protocol is class bound, during runtime, inside myMutatingFunc, the capture of self will be treated as struct even though we injected an actual class (MyClass).

    Escaping variables generally require dynamic enforcement instead of static enforcement. This is because Swift cannot reason about when an escaping closure will be called and thus when the variable will be accessed.

    The solution is to bound the Abstraction protocol to class:

    protocol Abstraction: class
    

提交回复
热议问题