MikeG
MikeG

Reputation: 4044

Cannot use mutating member on immutable value: 'self' is immutable

I don't understand why I'm getting this error. SomeController is a class, not a struct, and it is not immutable. Is there a work around to this?

class SomeController: APIFetchable {

    let baseUrl = "https://jsonplaceholder.typicode.com"
    let defaultSession =  URLSession(configuration: .default)
    var dataTask: URLSessionTask?

    func fetchDataFromAPI(atPath path: String, _ callback: ()-> Void){
        fetchDataAtPath(path) { data, error in  /*Error on this line -> "Cannot use mutating member on immutable value: 'self' is immutable"*/

        }
    }

}


protocol APIFetchable {
    var baseUrl: String {get}
    var defaultSession: URLSession {get}
    var dataTask: URLSessionTask? {get set}

    mutating func fetchDataAtPath(_ path: String,  _ callback: @escaping (Data?, Error?)-> Void)
}

extension APIFetchable {

    mutating func fetchDataAtPath(_ path: String,  _ callback: @escaping (Data?, Error?)-> Void){
        dataTask?.cancel()

        if var urlComponents = URLComponents(string: baseUrl) {
            urlComponents.path = path

            guard let url = urlComponents.url else {return}

            dataTask = defaultSession.dataTask(with: url) { data, response, error in
                defer {self.dataTask =  nil}

                if let error = error {
                    print("data task error \(error.localizedDescription)")
                    callback(nil, error)
                } else if let data = data, let response = response as? HTTPURLResponse, response.statusCode == 200 {
                    callback(data, nil)
                }
            }
            dataTask?.resume()
        }
    }


}

Upvotes: 3

Views: 5746

Answers (2)

Wizard of Kneup
Wizard of Kneup

Reputation: 2183

I got this response from Apple:

Since the method is mutating, it must be applied to a mutable self value.

Try:

var myself = self myself.fetchDataAtPath(...)

This is necessary because the implementation of a mutating method is allowed to reassign self. If the protocol is intended to be used primarily with classes, you may want to make it class-constrained rather than have mutating method requirements.

Upvotes: 0

Charlie Fish
Charlie Fish

Reputation: 20526

It looks like there are 2 options you have in order to fix this (according to this page).

  1. Implement a non-mutating version of fetchDataAtPath() on SomeController.
  2. Mark the APIFetchable protocol as class only: protocol APIFetchable: class { ... }, and remove the use of mutating (as @rmaddy mentioned in the comments on the OP)

Upvotes: 6

Related Questions