URL Loading System
- 표준 Internet 프로토콜(ex HTTP)을 사용하여 URL과 상호 작용하고 서버와 통신
- URL Loading System은 비동기이기 때문에, 앱이 응답을 하면서 데이터나 오류를 별도 처리 가능
- URL Session 인스턴스로 하나 이상의 URLSession Task 인스턴스를 생성
- → 이것으로 데이터를 앱에 반영, 파일을 다운로드, 데이터와 파일을 원격 위치에 업로드를 함
- private browsing의 경우 Ephemeral Configuration을 사용해야함
- 각 Session은 주기적 업데이트를 위해 Delegate와 연결되어있음
- → Custom Delegate를 사용하면 사용자가 지정한 Completion handler를 호출 X
- → 만약 Default Delegate를 사용하면 사용자가 지정한 Completion handler를 호출
Fetching Website Data into Memory
웹사이트 데이터를 메모리로 가져오기
- Session에서 Data Task를 생성하여 데이터를 메모리로 직접 수신
- 원격 서버와 상호작용 하는 경우, URLSessionDataTask을 사용하여 데이터를 메모리로 수신해라
- web Service의 endpoint와 같은 곳에서 사용하는 것이 이상적임
- Endpoint : API가 서버에서 리소스에 접근할 수 있도록 가능하게 하는 URL, 커뮤니케이션 채널의 한 쪽 끝
- → 서로 역할이 중첩되는 경우가 생길 수 있음
- API : 두 시스템(어플리케이션)이 상호작용할 수 있게 하는 프로토콜의 총집합. 프로그램들이 서로 상호작용하는 것을 도와주는 매개체
- Session은 필요한만큼만 생성하라. 비슷한 구성의 Session은 퉁쳐라
Receive Results with a Completion Handler
Completion Handler로 결과 받기
- 데이터를 가져오는 가장 간단한 방법
- Completion Handler를 사용하여 Data task를 만드는 방식으로 서버의 응답, 데이터 및 오류를 전달
func startLoad() {
let url = URL(string: "<https://www.example.com/>")!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
self.handleClientError(error)
return
}
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
self.handleServerError(response)
return
}
if let mimeType = httpResponse.mimeType, mimeType == "text/html",
let data = data,
let string = String(data: data, encoding: .utf8) {
// UI를 업데이트는 main에서 해야하니까~
DispatchQueue.main.async {
self.webView.loadHTMLString(string, baseURL: url)
}
}
}
task.resume()
}
Receive Transfer Details and Results with a Delegate
- 진행중인 작업에 대한 높은 수준의 접근을 제공하기 위해 completion handler 대신 delegate를 설정할 수 있음
- → delegate는 작업 중간에 끼어들 수 있기 때문
- delegate는 전송 과정이 진행되는 동안에도 다른 종류의 이벤트를 수신할 수 있음
- → delegate를 사용할 땐 sharedSession은 delegate를 사용할 수 없기 때문에, customizable Session을 만들어서 사용해야함
- init(configuration:delegate:delegateQueue:)
- → 만약 waitsForConnectivity를 true로 하면, 필요한 연결을 사용할 수 없는 경우 즉시 실패하지 않고 세션이 적절한 연결을 기다림
- → 사용자가 Session을 인스턴스화 할 때 customize가 가능
private lazy var session: URLSession = {
let configuration = URLSessionConfiguration.default
configuration.waitsForConnectivity = true
return URLSession(configuration: configuration,
delegate: self, delegateQueue: nil)
}()
Delegate callback 함수
urlSession(_:dataTask:didReceive:completionHandler:)
- 응답에 성공적인 HTTP 상태 코드가 있고 MIME 유형이 text/html 또는 text/plain인지 확인합니다. 둘 중 하나라도 해당되지 않으면 작업이 취소됩니다. 그렇지 않으면 계속 진행할 수 있습니다.
urlSession(_:dataTask:didReceive:)
- 태스크에서 수신한 각 Data 인스턴스를 받아서 receivedData라는 버퍼(임시저장소. 큐와 유사. 변기..의..뒤에 물탱크..가..버퍼)에 추가
urlSession(_:task:didCompleteWithError:)
- 먼저 전송 수준 오류가 발생했는지 확인합니다. 오류가 없으면 receivedData 버퍼를 문자열로 변환하고 webView의 내용으로 설정하려고 시도합니다.
// 버퍼
var receivedData: Data?
func startLoad() {
loadButton.isEnabled = false
let url = URL(string: "<https://www.example.com/>")!
receivedData = Data()
let task = session.dataTask(with: url)
task.resume()
}
// delegate methods
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse,
completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
guard let response = response as? HTTPURLResponse,
(200...299).contains(response.statusCode),
let mimeType = response.mimeType,
mimeType == "text/html" else {
completionHandler(.cancel)
return
}
completionHandler(.allow)
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
self.receivedData?.append(data)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
DispatchQueue.main.async {
self.loadButton.isEnabled = true
if let error = error {
handleClientError(error)
} else if let receivedData = self.receivedData,
let string = String(data: receivedData, encoding: .utf8) {
self.webView.loadHTMLString(string, baseURL: task.currentRequest?.url)
}
}
}
URL Loading System | Apple Developer Documentation
Fetching Website Data into Memory | Apple Developer Documentation
728x90
'학습활동' 카테고리의 다른 글
Swift Performance (2) (0) | 2023.12.11 |
---|---|
Swift Performance (1) (0) | 2023.12.11 |
동시성 프로그래밍 (0) | 2023.11.08 |
Swift Concurrency II (0) | 2023.09.28 |
Swift Concurrency I (0) | 2023.09.28 |