wiftクリーンアップ-URLSessession+Combine
出典:Processing URL Session Data Task Results with Combine - Apple Developer
非同期演算子を使用してURLからのデータを処理する方法について説明します.
ネットワーク操作は本質的に非同期操作であり,これらの非同期操作を処理する方法には多くの種類がある.
Combineも非同期を処理するフレームワークであり、ネットワーク操作を簡素化することができます.
task成功時
dataと taskが失敗した場合
error 既存の
また、完了ハンドラを使用するコードは、完了ハンドラモジュールを使用してすべての関連タスクを処理する必要があります.ただし、publisherを使用する場合は、多くのモジュールタスクをCombine演算子で置き換えることができます.
ネットワーク操作が完了すると、
Combineは、
前述したように、タスクが成功すると、
(
Combineの
次に、URLから受信したjsonデータを
ネットワーク・アクティビティは、多くのエラーが予想されるアクティビティです.そのため、私たちのアプリケーションはエラーをうまく処理する必要があります.
場合によっては、失敗したタスクを再試行する必要がある場合があります.
完了ハンドラを使用する場合は、再試行のためにハンドラを再作成する必要があります.
Combineは
エラーが発生した場合は、指定した回数で上流パブリケーションサーバへのサブスクリプションを再作成します.
ただし、ネットワーク・アクティビティのコストが高いため、再試行を過度に要求するべきではありません.また、すべてのリクエストが有効であることを確認する必要があります.
エラーを別のパブリケーションサーバに変換します.
fallback URLからデータをロードするのと同様に、他の
エラーを開発者が提供した内容に変更します.
エラーを他の内容に変更して、成功したときと同じ処理を実行することもできます.
この構文を実行することは、
DispatchQueueとRunLoopは、いずれもCombineの
ネットワークアクティビティのコストが高い.したがって、アプリケーションの複数の部分から1つの
Combineの
2つのサブスクリプション・サーバを
最初の
他のサブスクリプションサーバに接続する時間が必要な場合は、
すべてのサブスクリプション・サーバが準備ができている場合は、
非同期演算子を使用してURLからのデータを処理する方法について説明します.
ネットワーク操作は本質的に非同期操作であり,これらの非同期操作を処理する方法には多くの種類がある.
Combineも非同期を処理するフレームワークであり、ネットワーク操作を簡素化することができます.
dataTaskPublisher(for:)
URLSession
は、URL
またはURLRequest
から受信したデータを発行するためのURLSession.DataTaskPublisher
という組合せのパブリッシャーを提供する.dataTaskPublisher(for:)
メソッドでpublisherを作成できます.これにより、次の2つのコンテンツを解放できます.dataと
URLResponse
からなるtupleerror
dataTask(with:completionHandler:)
とは異なり、publisherはこのオプションを無効にします.また、完了ハンドラを使用するコードは、完了ハンドラモジュールを使用してすべての関連タスクを処理する必要があります.ただし、publisherを使用する場合は、多くのモジュールタスクをCombine演算子で置き換えることができます.
Raw Data -> Custom Type
ネットワーク操作が完了すると、
Data
タイプの値が受信されます.Combineは、
Data
からCustom Type
に変換する操作をサポートする演算子を提供する.前述したように、タスクが成功すると、
Data
およびURLResponse
が送信され、タイプをmap(_:)
またはtryMap(_:)
に変更できます.Data
をCustom Type
に変更します.(
Custom Type
仮定Decodable
.)Combineの
decode(type:decoder:)
を使用します.次に、URLから受信したjsonデータを
User
タイプに変換する手順を示します.struct User: Codable {
let name: String
let userID: String
}
let url = URL(string: "https://example.com/endpoint")!
cancellable = urlSession
.dataTaskPublisher(for: url)
.tryMap() { element -> Data in
guard let httpResponse = element.response as? HTTPURLResponse,
httpResponse.statusCode == 200 else {
throw URLError(.badServerResponse)
}
return element.data
}
.decode(type: User.self, decoder: JSONDecoder())
.sink(receiveCompletion: { print ("Received completion: \($0).") },
receiveValue: { user in print ("Received user: \(user).")})
dataTaskPublisher(for: url)
を使用してネットワーク操作を開始します.tryMap() { element -> Data in }
を使用して、元のdataTaskPublisher
リリースされた継ぎ手(Data
,Response
)を確認し、所望の形状に加工します.decode(type: User.self, decoder: JSONDecoder())
からtryMap()
へのデータをユーザタイプに変換します.Retry + Error Handling
ネットワーク・アクティビティは、多くのエラーが予想されるアクティビティです.そのため、私たちのアプリケーションはエラーをうまく処理する必要があります.
場合によっては、失敗したタスクを再試行する必要がある場合があります.
完了ハンドラを使用する場合は、再試行のためにハンドラを再作成する必要があります.
retry(_:)
Combineは
retry(_:)
行であってもよい.エラーが発生した場合は、指定した回数で上流パブリケーションサーバへのサブスクリプションを再作成します.
ただし、ネットワーク・アクティビティのコストが高いため、再試行を過度に要求するべきではありません.また、すべてのリクエストが有効であることを確認する必要があります.
catch(_:)
エラーを別のパブリケーションサーバに変換します.
fallback URLからデータをロードするのと同様に、他の
URLSession.DataTaskPublisher
とともに使用できます.replaceError(with:)
エラーを開発者が提供した内容に変更します.
エラーを他の内容に変更して、成功したときと同じ処理を実行することもできます.
let pub = urlSession
.dataTaskPublisher(for: url)
.retry(1)
.catch() { _ in
self.fallbackUrlSession.dataTaskPublisher(for: fallbackURL)
}
cancellable = pub
.sink(receiveCompletion: { print("Received completion: \($0).") },
receiveValue: { print("Received data: \($0.data).") })
retry(1)
エラーが発生した場合は、上流パブリケーションサーバのサブスクリプションが再び作成されます.catch()
エラーが発生した場合はfallBackUrlSession
を呼び出すことができます.この構文を実行することは、
retry(1)
が1回後に実行されることを意味するので、2回目error
と呼ぶことができる.Dispatch Queue + Scheduling Operators
URLSession
を完了ハンドラとして扱う場合は、ハンドラ内部のDispatch Queueなどを直接使用して特定のキューにタスクを移動する必要があります.receive(on:options:)
メソッドを使用すると、サブスクリプション・サーバとオペレータのメソッド後のワークキューを指定できます.DispatchQueueとRunLoopは、いずれもCombineの
Scheduler
プロトコルを実現しているので、すぐに使用できます.cancellable = urlSession
.dataTaskPublisher(for: url)
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { print ("Received completion: \($0).") },
receiveValue: { print ("Received data: \($0.data).")})
receive(on: DispatchQueue.main)
,sink
のログがDispatch Queueのmainから出力されます.Share Data Task Publisher
ネットワークアクティビティのコストが高い.したがって、アプリケーションの複数の部分から1つの
DataTaskPublisher
を1つのリクエストで購読できます.Combineの
share()
演算子を使用すると、複数の演算子とサブスクリプションサーバを接続できますが、上流のパブリッシャは1つの下流しか表示できません.これは、URLSession.DataTaskPublisher
がこのネットワーク操作を一度だけ実行することを意味する.let sharedPublisher = urlSession
.dataTaskPublisher(for: url)
.share()
cancellable1 = sharedPublisher
.tryMap() {
guard $0.data.count > 0 else { throw URLError(.zeroByteResource) }
return $0.data
}
.decode(type: User.self, decoder: JSONDecoder())
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { print ("Received completion 1: \($0).") },
receiveValue: { print ("Received id: \($0.userID).")})
cancellable2 = sharedPublisher
.map() {
$0.response
}
.sink(receiveCompletion: { print ("Received completion 2: \($0).") },
receiveValue: { response in
if let httpResponse = response as? HTTPURLResponse {
print ("Received HTTP status: \(httpResponse.statusCode).")
} else {
print ("Response was not an HTTPURLResponse.")
}
}
)
share()
複数のサブスクライバが許可されているが、ネットワーク操作は1回のみ可能である.2つのサブスクリプション・サーバを
sharedPublisher
に接続します.sharedPublisher
が一度だけ要求されていることを確認するには、.print(_:to:)
を.share()
演算子の上に配置してデバッグします.sink
がダウンストリームサブスクリプションサーバに接続されていない場合、URLセッションはデータをロードします.他のサブスクリプションサーバに接続する時間が必要な場合は、
makeConnectable()
を使用してPublisher.Share
publisherをConnectablePublisher
に変換します.すべてのサブスクリプション・サーバが準備ができている場合は、
connect()
メソッドを使用してデータのロードを開始できます.Reference
この問題について(wiftクリーンアップ-URLSessession+Combine), 我々は、より多くの情報をここで見つけました https://velog.io/@yy0867/Swift-정리-URLSession-Combineテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol