我目前正在通過他樹方式IOS Swift當然,我們正在建設一個天氣應用程序。我已經到了一個地步,我一直得到一個錯誤,我的課不符合我的協議,但我不明白爲什麼。類不符合包含默認實現的擴展名的協議
這裏是我的協議聲明:
public protocol APIClient {
var configuration: URLSessionConfiguration { get }
var session: URLSession { get }
func JSONTaskWithRequest(request: URLRequest, completion: JSONTaskCompletion) -> JSONTask
func fetch<T: JSONDecodable>(request: URLRequest, parse: (JSON) -> T?, completion: (APIResult<T>) -> Void)
}
然後,我有一個協議擴展在那裏我有我的協議中聲明瞭兩個方法的默認實現,而方法之一是調用其他方法,如你可以看到下面。
public extension APIClient {
func JSONTaskWithRequest(request: URLRequest, completion: @escaping JSONTaskCompletion) -> JSONTask {
let task = session.dataTask(with: request) { data, response, error in
guard let HTTPResponse = response as? HTTPURLResponse else {
let userInfo = [
NSLocalizedDescriptionKey: NSLocalizedString("Missing HTTP Response", comment: "")
]
let error = NSError(domain: BPSnetworkingErrorDomain, code: MissingHTTPReponseError, userInfo: userInfo)
completion(nil, response as! HTTPURLResponse, error)
return
}
if data == nil {
if let error = error {
completion(nil, response as! HTTPURLResponse, error as NSError?)
}
} else {
switch HTTPResponse.statusCode {
case 200:
do {
let JSON = try JSONSerialization.jsonObject(with: data!, options: []) as? [String: AnyObject]
completion(JSON, HTTPResponse, nil)
} catch let error as NSError {
completion(nil, HTTPResponse, error)
}
default: print("Received HTTP Response \(HTTPResponse.statusCode) - not handled")
}
}
}
return task
}
public func fetch<T>(request: URLRequest, parse: @escaping (JSON) -> T?, completion: @escaping (APIResult<T>) -> Void) {
let task = JSONTaskWithRequest(request: request) { json, response, error in
DispatchQueue.main.async {
guard let json = json else {
if let error = error {
completion(.Failure(error))
} else {
let error = "Something is really wrong. There was no JSON object created, but there was no error either."
completion(.Failure(error as! Error))
}
return
}
if let value = parse(json) {
completion(.Success(value))
} else {
let error = NSError(domain: BPSnetworkingErrorDomain, code: unexpectedResponseError, userInfo: nil)
completion(.Failure(error))
}
}
}
task.resume()
}
}
然後我有我的類聲明,我得到我的不符合性錯誤。
final class ForecastAPIClient: APIClient {
let configuration: URLSessionConfiguration
lazy var session: URLSession = {
return URLSession(configuration: self.configuration)
}()
private let token: String
init(config: URLSessionConfiguration, APIKey: String) {
self.configuration = config
self.token = APIKey
}
convenience init(APIKey: String) {
self.init(config: URLSessionConfiguration.default, APIKey: APIKey)
}
func fetchCurrentWeather(coordinate: Coordinate, completion: @escaping (APIResult<CurrentWeather>) -> Void) {
let request = Forecast.Current(token: self.token, coordinate: coordinate).request
fetch(request: request, parse: { (JSON) -> CurrentWeather? in
if let currentWeatherDictionary = JSON["currently"] as? [String: AnyObject] {
return CurrentWeather(JSON: currentWeatherDictionary)
} else {
return nil
}
}, completion: completion)
}
}
我已經做了大量的閱讀,試圖弄清楚這裏發生了什麼。據我所知,我不需要在我的類中定義這兩種方法,因爲它們在協議擴展中有默認實現。我遇到了公共/內部類型和類似的問題,其他人在StackExchange上使用它們的擴展名(正如你通過我公開標記的東西所看到的那樣),但這似乎沒有幫助在我的情況。我能夠讓錯誤消失的唯一方法是通過在原始協議聲明中註釋這些方法聲明。這似乎向我表明,無論是類,還是協議,或者由於某種原因都沒有看到擴展名,然而,如果我在類聲明中點擊fetch
方法調用,它會帶我到它在擴展中。我一直無法找到解決方案,或者甚至有人在做這種類似的事情,但樹屋中有好幾個人似乎也有同樣的問題。
另外,我下載了教師代碼,並將其轉換爲Swift 3,並且它也得到了相同的錯誤,所以也許這是Xcode的不同版本與他製作視頻時使用的問題有關的問題?
我覺得我有點抓住吸管,但我真的很渴望得到這個想法,所以任何可能的幫助將非常感激。
謝謝!
Xcode中的「報告導航器」具有完整的編譯器日誌,其中應包含有關編譯器認爲您的類不符合該協議的更多詳細信息。 –
謝謝,這幫助我弄清楚發生了什麼事情。顯然,如果你在擴展中將閉包標記爲@escaping,它也必須在協議聲明中標記出來,在思考它之後纔有意義,但我對這個概念還是一個新的東西。 – bshock84