私は現在、彼がTreehouse 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)
}
}
ここで何が起こっているのか把握しようと、何時間も読んだことがあります。私が理解しているところでは、プロトコル拡張でデフォルトの実装があるので、私のクラスでこれら2つのメソッドを定義する必要はありません。私は公共/内部型の問題に遭遇しました。他の誰かがStackExchangeでエクステンションを持っていたのです(あなたが私のものを公開しているのと同じではないと思いますが)私の場合。エラーを取り除くための唯一の方法は、元のプロトコル宣言のメソッド宣言をコメントアウトすることです。どのクラスやプロトコル、何かが何らかの理由で拡張機能を見ていないことを私に示しているようですが、私がクラス宣言のfetch
メソッド呼び出しをクリックすると、それは拡張の中にある。私は解決策、あるいはこのようなことをしている人さえ見つけられませんでしたが、同じ問題を抱えているようなTreehouseにはいくつかの人がいます。
また、教師コードをダウンロードしてSwift 3に変換したところ、同じエラーが発生していたため、ビデオを作成したときのXcodeのバージョン?
私はストローでちょっと握っているような気がしますが、実際にはこれを理解してもらいたいと思っています。
ありがとうございました!
Xcodeの「レポートナビゲータ」には完全なコンパイラログがあり、コンパイラがクラスがプロトコルに準拠していないと考える理由についての詳細情報が含まれているはずです。 –
ありがとう、これは何が起こっていたか把握するのを助けた。どうやら、クロージャーをエクステンションの@エスケープとしてマークすると、プロトコル宣言の中でそのようにマークされなければなりません。それを考えた上で意味がありますが、私はまだその概念を初めて習得しています。 – bshock84