let task = session.dataTask(with: url){(data, response, error)iniflet error = error {// 통신 중 에러가 발생한 경우 에러 처리return}guardlet httpResponse = response as?HTTPURLResponseelse{// HTTPURLResponse로 변환할 수 없는 경우 에러 처리return}guard(200...299).contains(httpResponse.statusCode)else{// 상태코드가 성공이 아닐 경우 에러 처리return}guardlet data = data else{// 데이터가 nil일 경우 에러 처리return}do{let decoder =JSONDecoder()// 디코딩 및 데이터 활용 처리 }catch{// 디코딩이 성공적으로 수행되지 않았을 경우 에러처리}}
URL을 전달하여 Task를 생성합니다.
URL이 아닌 URLRequest를 전달할 수도 있는데, 이는 Task 별로 네트워크 설정(캐시 정책 등)을 변경하고 싶을 때 사용합니다.
completion handler는 URL을 통해 네트워크 작업이 완료되면 호출됩니다. 이를 통해 data, response, error값을 전달받을 수 있습니다.
data : 서버에서 전달된 Binary Data
response : 서버 응답에 대한 정보
error : 에러 발생시 에러 정보
이들을 활용해 data를 decoding하고 이를 활용합니다.
아직은 task가 suspended 상태입니다.
task.resume()
task를 실행합니다. (끝)
Session Configuration
Session Configuration을 통해 네트워크 연결과 관련된 속성을 설정할 수 있습니다.
셀룰러 연결 금지, 캐시 저장위치 설정, 쿠기 설정 변경, 타임아웃 값 설정 등을 수행할 수 있습니다.
URLSession을 생성하기 전에 미리 구성을 완료한 뒤, URLSession 생성자로 전달해 사용할 수 있습니다.
URLSession이 생성된 후에는 Session Configuration을 수정할 수 없습니다. (Read Only)
기본적으로 제공하는 Session Configuration은 총 4가지입니다.
Shared : shared session에서 사용되는 Configuration으로, 일반적으로 직접 사용하는 경우는 없습니다.
Default : 기본 Configuration 설정을 기반으로 구성되어 있습니다. delegate를 통한 이벤트 처리 제공하며 disk 캐싱으로 서버 전달 데이터를 전달합니다.
Ephemeral : Default와 유사하지만 메모리에만 캐싱을 처리한다는 특징이 있습니다.
Background : Download 및 Upload Task에서 활용합니다. 앱 실행상태와 관계없이 데이터를 전송할 수 있도록 합니다.
Delegate를 사용하기 위해서는 처음 Session을 생성할 때 URLSession(configuration:, delegate:, delegateQueue:) 메서드를 사용해야합니다.
delegate를 self로 지정했습니다.
task 처리에는 completion handler가 없는 dataTask 메서드를 사용합니다.
classViewController: UIViewController{var buffer: Data?...}extensionViewController: URLSessionDataDelegate{// 서버로부터 최초로 응답을 받았을 때 호출funcurlSession(_session: URLSession, dataTask: URLSessionDataTask, didReceiveresponse: URLResponse, completionHandler: @escaping(URLSession.ResponseDisposition) -> Void){guardlet response = response as?HTTPURLResponse,(200...299).contains(response.statusCode)else{// 아닐 경우 cancel 처리completionHandler(.cancel)return}// 맞을 경우 allow 처리completionHandler(.allow)}// 전체 데이터가 아니기 때문에 이들을 누적하다가 완료되면 파싱처리funcurlSession(_session: URLSession, dataTask: URLSessionDataTask, didReceivedata: Data){buffer?.append(data)}// 데이터 전송이 완료되면 호출funcurlSession(_session: URLSession, task: URLSessionTask, didCompleteWithErrorerror: Error?){iflet error = error {// 에러 처리}// buffer data를 이용해 파싱처리}}
delegate를 self로 지정했기 때문에 이를 구현해주어야합니다.
각각 최초로 응답을 받았을 때, 각 데이터가 전송될 때 마다, 데이터 전송이 완료되면 호출되는 메서드입니다.
각각 최초로 응답을 받았을 때 : 조건에 따라 작업을 계속할지 말지를 결정해 completionHandler에 전달합니다.
overridefuncviewWillDisappear(_animated: Bool){super.viewWillDisappear(animated)session.finishTasksAndInvalidate()// Task가 모두 종료될 때까지 기다렸다가 리소스 정리session.invalidateAndCancel()// 모든 Task를 취소하고 바로 리소스 정리}
delegate를 사용하면서 ViewController와 URLSession이 서로 순환참조를 일으킬 수 있습니다.
따라서 ViewWillDisapear에서 이를 메모리에서 해제해주는 작업이 필요합니다.
finishTasksAndInvalidate 혹은 invalidateAndCancel를 사용합니다.