skip to Main Content

I’m working on a Swift 6 project and need to manage a static variable that stores network responses. The current implementation isn’t concurrency-safe because multiple threads can access and modify the shared state, leading to race conditions. Previously this code worked on Swift 4.

extension NetworkRequestHandler {
// Basic static variable with concurrency issues
static private var cachedResponses: [NetworkResponse] = []

// Adding a response
static func addResponse(_ response: NetworkResponse) {
    cachedResponses.append(response)
}

// Removing all responses
static func clearResponses() {
    cachedResponses.removeAll()
}
}


private extension NetworkRequestHandler {
    // Helper function to retrieve the response for a specific request
    static func response(for request: URLRequest) -> NetworkResponse? {
        return cachedResponses.first { $0.url == request.url }
    }
}

So basically the problem is in this part of code static private var cachedResponses: [NetworkResponse] = [] with error – Static property ‘cachedResponses’ is not concurrency-safe because it is nonisolated global shared mutable state

2

Answers


  1. You could use an actor instead of that static property and add the actor as a property in your network type

    actor ResponseCache {
        private var cachedResponses: [NetworkResponse] = []
    
        func addResponse(_ response: NetworkResponse) {
            cachedResponses.append(response)
        }
    
        func clearResponses() {
            cachedResponses.removeAll()
        }
    
        func get(_ url: URL) -> NetworkResponse? {
            cachedResponses.first { $0.url == url }
        }
    }
    
    private extension NetworkRequestHandler {
        func response(for request: URLRequest) async -> NetworkResponse? {
            guard let url = request.url else { return nil }
    
            return await cachedResponses.get(url)
        }
    }
    
    Login or Signup to reply.
  2. Just make your files as an actor like below I do:

    actor SingletonWithStatic {
      private init() { }
      private var output = ""
      static let shared = SingletonWithStatic()
    
      func prepare(outputLine line: String) {
        output += line
        output += "n"
      }
    
      func flushOutput() {
        print(output)
        output = ""
      }
    }
    

    Or you can silent your warning by making your static variable unsafe, but make sure you use that static variable in thread safe manner.

    class SingletonWithStatic {
      private init() { }
      private var output = ""
      nonisolated(unsafe) static let shared = SingletonWithStatic()
    
      func prepare(outputLine line: String) {
        output += line
        output += "n"
      }
    
      func flushOutput() {
        print(output)
        output = ""
      }
    }
    

    Or mark your class or struct as @MainActor

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search