3

I have a singleton class that tracks my game's score among other things.

final class PublicData {
    static let sharedInstance: PublicData? = PublicData()

    struct Scores {
        var points = [0, 0]
        subscript(index: Int) -> Int {
            get {return points[index]}
            set(newValue) {
                points[index] += newValue
                print("score\(index): \(points[index])")
                NotificationCenter.default.post(name: Notification.Name(rawValue: "updateScore\(index)"), object: nil)
            }
        }
        mutating func reset() {
            points = [0, 0]
            NotificationCenter.default.post(name: Notification.Name(rawValue: "updateScore0"), object: nil)
            NotificationCenter.default.post(name: Notification.Name(rawValue: "updateScore1"), object: nil)
        }
    }


    var scores = Scores()
}

Then in my RootViewController, I update the view to match the current scores.

let data = PublicData.sharedInstance

@objc func updateScore0(_ payload: Notification) {
    let score = data!.scores[0] // line 678
    score0.text = "\(score)"
    // I use matchsticks to show the score
    setMatchScore(score, matchesView: matchesStack0)
}

@objc func updateScore1(_ payload: Notification) {
    let score = data!.scores[1]
    score1.text = "\(score)"
    setMatchScore(score, matchesView: matchesStack1)
}

Now in Swift 4 I get this error on line 678

"Thread 1: Simultaneous accesses to 0x608000186ad8, but modification requires exclusive access

I've tried using let temp = points and using temp instead but it didnt work. Can anyone help shed light on a solution?


This issue has been criticized as already being answered. However the "answer" was simply a link to a video which, though explained the concept and reason for the error, does not explain clearly why I am encountering it.

Most coding principles are documented. Stack Overflow helps those who haven't yet wrapped their heads around them.

Pointing questioners toward the direction of the documentation/video is fruitless. Sometimes someone personally focusing on YOUR issue with you not only solves it more quickly but turns the light on for similar hard to grasp concepts in the future.


Adrian Bartholomew
  • 2,506
  • 6
  • 29
  • 37
  • Possible duplicate of [Simultaneous accesses to 0x1c0a7f0f8, but modification requires exclusive access error on Xcode 9 beta 4](https://stackoverflow.com/questions/45415901/simultaneous-accesses-to-0x1c0a7f0f8-but-modification-requires-exclusive-access) – Tamás Sengel Oct 05 '17 at 13:30
  • I looked at it. It didnt help me. – Adrian Bartholomew Oct 05 '17 at 13:48

1 Answers1

1

I solved my dilemma.

I simply passed the payload data in the Notification to the RootViewController from the struct instead of reading the struct property from the RootViewController.

RootViewController code

@objc func updateScore0(_ payload: Notification) {
    if let score = payload.userInfo?["score"] as? Int {
        score0.text = "\(score)"
        setMatchScore(score, matchesView: matchesStack0)
    }
}

Struct code

struct Scores {
    var points = [0, 0]
    subscript(index: Int) -> Int {
        get {return points[index]}
        set(newValue) {
            points[index] += newValue
            let payload: [String: Int] = ["score": points[index]]
            print("score\(index): \(points[index])")
            NotificationCenter.default.post(name: Notification.Name(rawValue: "updateScore\(index)"), object: nil, userInfo: payload)
        }
    }
    mutating func reset() {
        points = [0, 0]
        let payload0: [String: Int] = ["score": points[0]]
        let payload1: [String: Int] = ["score": points[1]]
        NotificationCenter.default.post(name: Notification.Name(rawValue: "updateScore0"), object: nil, userInfo: payload0)
        NotificationCenter.default.post(name: Notification.Name(rawValue: "updateScore1"), object: nil, userInfo: payload1)
    }
}
Adrian Bartholomew
  • 2,506
  • 6
  • 29
  • 37