不能对不可变值使用可变成员:'self' 是不可变的
Cannot use mutating member on immutable value: 'self' is immutable
我不明白为什么会出现此错误。 SomeController
是一个 class,不是结构,而且它不是不可变的。有解决办法吗?
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()
}
}
}
看起来您有 2 个选项可以解决此问题(根据 this page)。
- 在
SomeController
上实现 fetchDataAtPath()
的非变异版本。
- 仅将
APIFetchable
协议标记为 class:protocol APIFetchable: class { ... }
,并删除变异的使用(如 OP 评论中提到的@rmaddy)
我不明白为什么会出现此错误。 SomeController
是一个 class,不是结构,而且它不是不可变的。有解决办法吗?
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()
}
}
}
看起来您有 2 个选项可以解决此问题(根据 this page)。
- 在
SomeController
上实现fetchDataAtPath()
的非变异版本。 - 仅将
APIFetchable
协议标记为 class:protocol APIFetchable: class { ... }
,并删除变异的使用(如 OP 评论中提到的@rmaddy)