본문 바로가기

iOS

[iOS] Fetching Website Data into Memory

Fetching Website Data into Memory

  • URL Session에 데이터 작업을 생성해 데이터를 직접(데이터 -> 메모리) 수신합니다.

URLSessionDataTask(데이터작업)는 어떤기능을 하는가 ?

  • 데이터작업은 하나 이상의 NSData(bytes) 객체로 앱(메모리)에 직접 반환을 시키는 기능이다.

[특징]

  • URLSessionTask의 하위클래스이다. (메서드들에대한 설명은 URLSessionTask에 설명되어있음)
  • 데이터를 업로드하는 동안 Session은 주기적으로 StatusCode와 함께 delegate메서드를 호출합니다. urlSession(_:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:)
  • 응답을 수신한 후 Session Delegate의 urlSession(_:dataTask:didReceive:completionHandler:) 메서드를 호출해 StatusCode와 Header를 검사하고 선택적으로 데이터작업을 다운로드로 convert할 수 있도록 해줍니다.
  • 전송하는 동안 Session Delegate의 urlSession(_:dataTask:didReceive:) 메서드를 호출해 앱이 도착하는 대로 content를 제공합니다.
  • 완료되면 Session은 Delegate의 urlSession(_:dataTask:willCacheResponse:completionHandler:) 메서드를 호출해 응답을 Cache해야하는지 여부를 결정할 수 있습니다.

데이터 업로드 중 Session의 작업 과정

  1. StatusCode와 delegate메서드를 호출 urlSession(_:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:)
  2. 응답을 수신한 후 Session Delegate의 urlSession(_:dataTask:didReceive:completionHandler:) 메서드를 호출해 StatusCode와 Header를 검사하고 선택적으로 데이터작업을 다은로드로 convert할 수 있도록 해줌
  1. 전송하는동안 Session Delegate의 urlSession(_:dataTask:didReceive:) 메서드를 호출해 앱이 도착하는대로(메모리에 데이터가 로드되는대로) content를 제공함
  1. 완료후 Session Delegate의 urlSession(_:dataTask:willCacheResponse:completionHandler:) 호출해 응답을 Cache해야하는지 여부를 결정한다.

다시 Fetching Website Data into Memory OverView로 돌아와서 읽어보자…

  • 요구사항이 간단하면 URLSession의 shared를 사용하면 된다
  • delegate callback을 통해 전송과 상호작용하려면 공유 instance를 사용하지않고 Session을 만들어야한다.
  • Session을 생성할 때 URLSessionConfiguration 인스턴스를 사용하고 URLSessionDelegate 또는 하위 프로토콜 중 하나를 구현하는 class도 전달한다.
  • 세션을 재사용해 여러 작업을 생성할 수 있으므로 필요한 각각의 고유한 구서에대한 세션을 생성하고 프로퍼티로 저장한다.

[NOTE]
Session을 사용할때 주의해야하는 앱안에서 여러 유사한 Session을 구성해 사용할 경우엔 하나의 Session을 생성하여 공유하세요.

  • Session이 있으면 dataTask()메서드 중 하나를 사용해 데이터 작업을 합니다. dataTask는 일시중단 상태이며 resume으로 시작시킬 수 있다.

Receive Result With a Completion Handler(완료 핸들로로 결과받기)

데이터를 가져오는 가장 간단한 방법은 completionHandler로 작업을 만드는것이다.
서버가 데이터를 전달할때 data, response, error를 전달합니다.

completionHandler가 가져야할 3가지작업

  1. error매개변수가 nil인지 확인하세요. 그렇지 않은 경우는 오류가 발생했다는 뜻입니다. 고로 오류처리를 하고 종료하면됩니다.
  2. response 매개변수로 StatusCode가 success를 나타내고 MIME유형이 예상 값인지 확인하세요 그렇지 않은 경우 서버오류를 처리하고 종료합니다.

[MIME 타입 유형]

사진참조글 - https://dololak.tistory.com/130
  1. 오류 검증이 끝났으니 필요에 따라 data를 사용하면 됩니다.
  func startLoad() {
    let url = URL(string: "http/example...")!
    let task = URLSession.shared.dataTask(with: url) { data, response, error in
      if let error = error { print("\(error) 에러 발생..") }
      
      guard let httpResponse = response as? HTTPURLResponse else { return }
      
      if let mimeType = httpResponse.mimeType, mimeType == "text/html",
         let data = data,
         let string = String(data: data, encoding: .utf8) {
        DispatchQueue.main.async {
//          self.view.loadHTMLString(string, baseURL: url)
        }
      }
    }
    task.resume()
  }
 
  • completionhandler는 작업을 생성할 것과 다른 GCD 대기열에서 호출됩니다. 따라서 webView업데이트와 같이 UI를 업데이트하기위해 data나 error를 사용하는 모든작업은 여기에 명시된것처럼 main에 배치되어야합니다.

Receive Transfer Details and Results with a Delegate(대리자와 함께 전송 정보 및 결과를 수신?)

  • 작업이 진행됨에 따라 작업활동에 대한 더 높은 수준의 접근을 위해 dataTask를 생성할때 Session에 Delegate를 설정할 수 있다.

delegate는 전송이 완료되거나 오류가 날때까지 다른종류의 이벤드토 수신합니다. URLSession클래스의 간단한 공유 인스턴스를 사용하는 대신 delegate 접근 방식을 사용할때 고유한 Session인스턴스를 생성해야합니다. 왜?

새 세션을 생성하면 Listing2와 같이 자신의 클래스를 Session대리자로 설정할 수 있습니다.

클래스가 Delegate 프로토콜(URLSessionDelegate, URLSessionTaskDelegate, URLSessionDataDelegate 및 URLSessionDownloadDelegate) 중 하나 이상을 구현한다고 선언합니다.

-> 이후에 init(configuration:delegate:delegateQueue:).메서드를 사용해 URLSession인스턴스를 만들어 커스텀할수 있다. 아래 예시코드로 확인해보자

    lazy var customSession: URLSession = {
      let configuration = URLSessionConfiguration.default
      configuration.timeoutIntervalForResource = 60
      configuration.waitsForConnectivity = true
      return URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
    }()
 
  • waitForConnectivity프로퍼티에 true로 설정해주게되면 urlSession을 통해 data를 가져올 수 있을때까지 기다린다는 뜻이다. 사용자가 인터넷이연결이 되어있지않은 경우에서 dataTask작업을 시도하면 error를 보고할것이다. 이때 시도하지않고 확인해주는 작업이라고 볼 수 있다.
    추가로 timeoutIntervalForResource 프로퍼티가 있는데 이는 기다리는 시간을 제한두는기능이다. 60초로 설정하면 60초만 기다리겠따는 뜻이다.

추가로 configuration을 구성하는 session객체가 3종류가 있다.

  1. default, 2. ephemeral, 3. background

default는 쿠키와 캐시를 저장할때 사용된다.
ephemeral는 쿠키와 캐시를 저장하지 않을때 사용한다.
background는 이미지나 파일을 업로드하면서 작업을

Reference