ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Raywenderlich - iOS] NSURLSession 사용 가이드
    앱등이에게 살충제를 뿌린다./iOS 2016. 4. 11. 00:59





    앱이 서버로부터 앱 관련 데이터를 받거나, 소셜 미디어의 상태를 업데이트하거나, 리모트 서버의 파일을 로컬에 다운로드 받거나,, 어떤 경우던지 HTTP 요청은 모바일 앱의 핵심이라고 할 수 있습니다. 수 많은 네트워크 요청을 하고자 하는 여러분을 위해 Apple에서는 NSURLSession을 제공하고 있습니다. 이 놈은 HTTP를 통해 컨텐트를 업로드하거나 다운로드를 하는 네트워킹 API를 완벽하게 아우르는 놈입니다.


    NSURLSession 튜토리얼에서는 NSURLSession을 사용하여 Half Tunes라는 앱을 만들어볼 것입니다. 이 앱은 iTunes Search API에 커리를 보내 특정 음악의 30초 미리듣기를 다운로드 하는 앱입니다. 최종적으로 완성한 앱에서는 백그라운드 전송과 사용자들이 다운로드를 중지, 재개, 취소를 하는 기능도 제공될 것입니다.



    Getting Started

    starter project를 다운로드 받으세요. 이 프로젝트에는 이미 곡을 찾고 검색 결과를 보여주는 UI가 구현되어 있습니다. JSON을 파싱하고 음악을 재생하기 위한 Helper 메소드도 구현되어 있습니다. 오로지 네트워킹 구현에 집중할 수 있도록 셋팅되어 있습니다.


    앱을 빌드하고 실행시켜보시면 아래와 같이 검색바와 빈 테이블뷰가 나타날 것입니다.


    검색바에 검색어를 입력하고 검색을 눌러보세요. 테이블뷰가 여전히 비어있죠? 걱정마세요. NSURLSession 구현으로 이 테이블뷰를 채워봅시다.





    Overview of NSURLSession

    시작하기에 앞서, NSURLSession과 관련 클래스들에 대한 간단한 설명을 하도록 하죠. 

    NSURLSession은 프로그래밍 관점에서 볼 때 하나의 클래스이자 동시에 HTTP/HTTPS 기반의 요청을 컨트롤하는 클래스의 집단이라고 볼 수 있습니다.


    NSURLSession은 HTTP요청을 보내고 받는 작업에 가장 중요한 핵심 객체입니다. 이 객체는 3가지 종류의 NSURLSessionConfiguration중 하나와 생성하게 됩니다.

    • defaultSessionConfiguration: 디폴트 configuration 객체를 생성합니다. 사용자들은 disk-persisted global chache, credential, cookie storage objects를 사용하게 됩니다.
    • ephemeralSessionConfiguration: 디폴트 configuration과 유사합니다. 유일한 차이점은 세션관련 데이터가 메모리에 올라가있다는 것입니다. private 세션이라고 생각하시면 되겠습니다.
    • backgroundSessionConfiguration: 세션이 백그라운드에서 다운로드 작업과 업로드 작업을 수행할 수 있도록 합니다. 이 데이터 전송작업은 앱이 Suspended나 Not running일 때에도 수행됩니다.
    NSURLSessionConfiguration은 위에서 설명한 내용 외에도 타임아웃, 캐시 정책 또는 추가적인 HTTP 헤더와 같은 여러 프로퍼티를 설정할 수 있게 해줍니다. 자세한 내용은 documentation을 참조해주세요.

    NSURLSessionTask는 세션의 작업 하나를 나타내는 추상클래스입니다. 세션은 데이터를 다운로드하거나 업로드하는 작업(Task)을 생성합니다.
    이 작업(Task)에는 3가지 종류가 존재합니다.
    • NSURLSessionDataTask: HTTP GET요청으로 서버로부터 데이터를 가져오는 작업을 수행합니다.
    • NSURLSessionUploadTask: 디스크로부터 웹서버로 파일을 업로드하는 작업을 수행합니다. 주로 HTTP POST, PUT 메소드를 이용합니다.
    • NSURLSessionDownloadTask: 리모트 서버로부터 파일을 다운로드하는 작업을 수행합니다. 






    Querying for Tracks

    검색을 누르면 iTunes Search API에 검색커리를 날리는 코드를 작성하면서 시작해보겠습니다.
    SearchViewController.swift에서 클래스 최상단에 아래와 같은 코드를 작성해주세요.


    코드 설명

    1. NSURLSession을 만드는데 이 때 디폴트 configuration으로 생성을 합니다. (위에서 configuration에 대한 설명을 간단히 했습니다.)
    2. NSURLSessionDataTask타입 변수를 선언했습니다. 이 변수는 사용자가 검색을 누를 때 iTunes Search 웹 서버에 HTTP GET 요청을 보내게 됩니다. 사용자가 검색을 할 때마다 이 변수는 새롭게 초기화되어 새로운 커리가 전송되게 됩니다.


    이제 searchBarSearchButtonClicked(_:)를 아래와 같이 대체해주세요.


    func searchBarSearchButtonClicked(searchBar: UISearchBar) {
      dismissKeyboard()
     
      if !searchBar.text!.isEmpty {
        // 1
        if dataTask != nil {
          dataTask?.cancel()
        }
        // 2
        UIApplication.sharedApplication().networkActivityIndicatorVisible = true
        // 3
        let expectedCharSet = NSCharacterSet.URLQueryAllowedCharacterSet()
        let searchTerm = searchBar.text!.stringByAddingPercentEncodingWithAllowedCharacters(expectedCharSet)!
        // 4
        let url = NSURL(string: "https://itunes.apple.com/search?media=music&entity=song&term=\(searchTerm)")
        // 5
        dataTask = defaultSession.dataTaskWithURL(url!) {
          data, response, error in
          // 6
          dispatch_async(dispatch_get_main_queue()) {
            UIApplication.sharedApplication().networkActivityIndicatorVisible = false
          }
          // 7
          if let error = error {
            print(error.localizedDescription)
          } else if let httpResponse = response as? NSHTTPURLResponse {
            if httpResponse.statusCode == 200 {
              self.updateSearchResults(data)
            }
          }
        }
        // 8
        dataTask?.resume()
      }
    }
    코드 설명
    1. 사용자가 커리전송을 할 때, data task가 이미 초기화 되어있는지를 확인합니다. 만약 되어 있다면 이 data task의 작업을 중지시키고 재사용하게 됩니다.(새로운 커리를 날리고자 하는데이전에 날리던 커리를 계속 보낼 필요가 없겠죠?)
    2. 아이폰의 상태바에 네트워크 작업이 진행중이라는 표시를 해줍니다. (데이터 쓰면 빙글빙글 돌아가는 아이콘)
    3. URL커리에 사용자의 검색어를 바로 포함시키기 전에 stringByAddingPercentEncodingWithAllowedCharacters(_:) 를 사용하여 적절히 escape작업(문자열 인코딩 때문에 필요함)을 해줍니다.
    4. 이제 NSURL을 생성하고 iTunes Search API URL에 escape한 사용자의 검색어를 GET 파라미터로 붙여줍니다.
    5. 생성했던 세션을 통해 HTTP GET요청을 수행할 NSURLSessionDataTask를 초기화합니다. NSURLSessionDataTask의 생성자에는 위에서 생성한 NSURL과 해당 작업이 성공했을 때 수행될 completion handler(클로져타입)도 같이 들어갑니다. (메소드 참고는 여기를 클릭)
    6. 작업이 완료되면 상태바의 네트워크 작업 상태 아이콘을 숨겨줍니다. 이 과정은 main 스레드에서 진행되도록 합니다.
    7. HTTP 요청이 성공적으로 끝났다면 updateSearchResults(_:)를 호출합니다. 이 메소드에서는 NSData를 Track타입으로 파싱하여 테이블뷰에 뿌려주게 됩니다.
    8. 모든 Task는 디폴트로 suspended인 상태이기 때문에, resume()를 호출함으로써 data task가 시작되게 됩니다.
    앱을 실행시켜보세요. 그리고 검색어를 입력한 뒤 검색을 하면 테이블뷰가 아래와 같이 채워질 것입니다.

    NSURLSession으로 약간의 작업만 추가했는데, HalfTunes가 벌써 있어보이네요.






    Downloading a Track

    곡의 리스트가 나타나는 것까지는 좋네요. 하지만 다운로드를 탭해서 음악을 받을 수 있다면 더 좋겠죠? 그럼 이제 그 작업을 해봅시다. 여러 다운로드 작업을 쉽게 다루기 위해서 먼저 활성화된 다운로드 작업의 상태를 나타낼 객체를 생성하도록 합니다.

    Data Objects그룹 안에 Download.swift 파일을 생성하여 아래와 같이 작성해주세요.

    코드 설명

    • url : 다운로드할 파일의 url입니다. 이 값은 Download를 식별하는 identifier의 역할도 하게 됩니다.
    • isDownloading : 다운로드가 진행중인지 중지상태인지를 알려줍니다.
    • progress : 다운로드의 진척도를 나타냅니다. 0.0에서 1.0사이의 값을 가집니다.
    • downloadTask : 파일 다운로드 작업을 수행하는 NSURLSessionDownloadTask객체입니다.
    • resumeData : 다운로드를 중지하면 받았던 데이터를 저장합니다. 서버에서 지원하면 나중에 다운로드를 재개할 때 해당 이 데이터에 이어서 다운로드를 할 수 있습니다.
    SearchViewController.swift로 가서 클래스 상단부분에 아래 코드를 넣어주세요.

    이 코드들은 다운로드 URL과 active상태인 Download객체를 맵핑해주는 역할을 합니다.

    (activeDownloads는 아래 설명에도 계속 등장할텐데요. 현재 진행중인 다운로드 작업이 이 딕셔너리에 담기게 됩니다.)


    Creating a Download Task

    다운로드작업을 구현할 준비가 끝났습니다. 우선, 다운로드 Task를 컨트롤해줄 세션객체를 생성합시다.

    SearchViewController.swift의 viewDidLoad(): 바로 윗 부분에 이 코드를 삽입해 주세요.

    이 코드를 통해 다운로드 Task를 제어할 하나의 세션을 생성하게 됩니다(디폴트 Configuration으로 생성). 또한 NSURLSession의 이벤트에 대한 처리를 수행할 delegate도 설정해주고 있습니다. 이 delegate 설정을 통해 작업이 완료되는 시점 뿐만 아니라 작업이 수행되는 중에도 작업에 대한 핸들링이 쉽게 됩니다. 


    downloadSession을 lazy로 생성하는 건 이 세션이 실제로 필요하기 전까지 생성하지 않겠다는 의미입니다. Most importantly, it lets you pass self as the delegate parameter to the initializer — even if self isn’t initialized.


    SearchViewController.swift에서 NSURLSessionDownloadDelegate를 따르는 확장구문을 하나 추가해주세요.

    코드설명

    NSURLSessionDownloadDelegate는 NSURLSession 다운로드 task를 사용할 때 사용할 메소드들을 제공합니다. 필수로 구현해야하는 메소드는 각각의 다운로드가 종료될 때 마다 호출되는 메소드인  URLSession(_:downloadTask:didFinishDownloadingToURL:)하나 뿐입니다. 이 메소드를 구현했으므로 이제 다운로드가 완료될 때마다 로그가 하나씩 찍히게 될겁니다.


    세션도 생성했고, delegate도 구현하였으니, 이제 사용자가 음악 다운로드를 요청하면 다운로드 task를 생성할 최종적인 준비가 완료되었습니다.

    SearchViewController.swift의 startDownload(_:)를 아래 코드로 구현해주세요.

    코드설명

    사용자가 트랙의 Download버튼을 누르면 해당 트랙에 대한 startDownload(_:)이 호출됩니다.

    1. 먼저 해당 트랙의 preview URL으로 Download객체를 생성합니다.
    2. 새로 만든 세션객체에서 preview URL에 해당하는 NSURLSessionDownloadTask을 생성합니다. 그리고 생성된 Task를 Download객체의 downloadTask로 설정해줍니다.
    3. resume()를 호출함으로써 다운로드 task를 시작합니다.
    4. 다운로드가 진행중임을 알리는 플래그를 설정해줍니다.
    5. 마지막으로 activeDownloads 딕셔너리에서 downloadURL에 해당 다운로드 task를 맵핑해줍니다.
    앱을 실행한 뒤 곡을 검색하고 Download 버튼을 눌러보세요. 누른 뒤 잠시 후면 콘솔창에 메시지가 나타날겁니다. 다운로드가 완료되었다는 의미겠지요.



    Saving and Playing the Track

    다운로드가 완료되면 URLSession(_:downloadTask:didFinishDownloadingToURL:) 가 다운로드한 파일의 임시 위치에 대한 URL을 제공해줍니다. 이 메소드가 return하기 전에 여러분은 이 임시위치에 있는 파일을 앱의 샌드박스 내부 디렉터리에 옮겨주어야 합니다. 그리고 다운로드가 완료되었으니 active download를 딕셔너리에서 제거해주고 테이블뷰를 업데이트 해주어야 합니다.


    이 작업을 쉽게 해줄 메소드를 등록하도록 할게요. SearchViewController.swift에서 클래스내부에 아래 메소드를 추가해주세요.

    이 메소드는 단순히 searchResults에서 해당 Track이 몇 번재 인덱스에 있는지를 리턴해줍니다.


    다음으로 URLSession(_:downloadTask:didFinishDownloadingToURL:)을 아래의 코드로 대체해주세요.

    코드 설명

    1. 다운로드 task로부터 original request의 URL을 받아와 이를 localFilePathForUrl(_:)메소드에 넣어줍니다. localFilePathForUrl(_:)은 URL의 lastPathComponent(파일의 이름과 파일의 확장자)을 Append하여 영구적으로 이 파일을 저장할 주소(디렉터리 경로)를 리턴해줍니다.
    2. NSFileManager을 통해 다운로드한 파일을 임시 파일위치에서 영구적인 파일 위치로 이동시켜 줍니다. 이 때, 파일이 저장될 위치에는 아무 파일도 없도록 removeItem를 해주고 있네요.
    3. active downloads에 다운로드한 파일과 일치하는 객체(Download)를 찾아 제거해줍니다.
    4. 마지막으로 테이블뷰에서 다운로드한 파일에 해당하는 Track의 셀을 업데이트 해줍니다.
    앱을 실행시켜 봅시다. 아무 곡이나 정해서 다운로드를 해보세요. 다운로드가 완료되면 파일이 저장된 위치의 URL이 콘솔에 로그로 찍힙니다.

    이제 노래가 디바이스에 다운로드 되었기 때문에 다운로드 버튼도 사라집니다. 곡을 터치하면 아래화면 처럼 MPMoviePlayerViewController를 이용하여 노래를 들을 수 있습니다.








    Monitoring Download Progress

    현재 구현한 바로는 다운로드 진행 상황을 모니터링할 수가 없습니다.  UX 개선을 위해 다운로드 상황을 캐치하여 화면에 표시해줄 수 있도록 해봅시다.

    SearchViewController.swift에 NSURLSessionDownloadDelegate을 따르는 확장구문을 찾아 아래 delegate메소드를 추가해주세요.

    코드 설명

    1. 메소드에서 제공하는 downloadTask의 URL을 사용하여 active download 딕셔너리에서 이 task에 해당하는 Download객체를 찾습니다.
    2. 이 메소드는 다운로드한 바이트 수와 다운로드 해야할 총 바이트 수를 알려줍니다. 이 두 값의 비율을 통해 다운로드 상황을 계산해낼 수 있습니다. 이 계산한 값을 Download객체에 저장해줍니다. 이 값을 통해 progress view를 업데이트 해줄 겁니다.
    3. NSByteCountFormatter는 바이트 값을 받아 사람이 이해할 수 있는 문자열 값을 만들어 줍니다. 다운로드 해야할 총 바이트수를 받아서 적절한 스트링을 만들어 주고 있는데요, 이 값을 통해 화면에는 다운로드의 완료 퍼센트를 나타내게 됩니다.
    4. 마지막으로 다운로드 중인 파일에 대한 셀을 찾아 이전 단계에서 얻은 값들로 progress view와 progress label을 업데이트 해주고 있습니다.

    다음으로 다운로드가 진행 될 때마다 progress view와 다운로드 상태에 대한 표시를 적절하게 해줄 수 있는 작업을 해보도록 하겠습니다.

    tableView(_:cellForRowAtIndexPath:):

    메소드내에서 아래의 코드가 있는 라인을 찾아주세요.


    찾으신 라인 바로 위에 아래 코드를 넣어주세요.

    다운로드가 진행중인 트랙에 대해 showDownloadControls을 true로 설정하고 있습니다. 그렇지 않은 경우에는 false로 설정해주고 있구요. 이제 showDownloadControls의 값에 따라 progress view와 progress label을 보여줄 수 있게 되었습니다.


    다운로드가 진행중인 트랙에 대해서는 "Downloading..."이라는 메시지가 표시되고 아닌 경우에는 "Paused"라는 메시지가 나타나게 되겠네요.

    마지막으로 이 코드를


    아래의 코드로 바꿔주세요.


    다운로드가 완료되었거나 진행중인 트랙에서는 다운로드 버튼을 숨기도록 했습니다.

    앱을 실행한 뒤 다운로드를 진행하면 아래처럼 상태바와 앱의 다운로드 상태가 표시되는 모습을 보실 수 있습니다.









    Pausing, Resuming and Cancelling Downloads

    다운로드를 중지하거나, 취소하고 싶다면 어떻게 해야할까요? 이번 섹션에서는 중지, 취소, 재개를 구현해보도록 하겠습니다.


    먼저 사용자들이 다운로드를 취소하는 기능을 구현하도록 하죠.

    cancelDownload(_:)를 아래의 코드로 대체해주세요.

    다운로드를 취소하기 위해서, active download 딕셔너리에 있는 Download 객체에서 취소한 트랙에 해당하는 객체의 download task를 가져온 뒤 cancel()을 호출해줍니다. 그 뒤 active download 딕셔너리에서 해당 객체를 제거해줍니다.


    다운로드를 중지하는 기능은 취소와 개념적으로는 유사합니다. 하지만 차이점은 Pause는 다운로드를 취소하긴 하지만 다시 재개(resume)할 수 있다는 것입니다. (호스트 서버에서 이 기능을 제공해주어야 하긴 합니다.)

    Note: You can only resume a download under certain conditions. For instance, the resource must not have changed since you first requested it. For a full list of conditions, check out the Apple documentation here.

    이제 pauseDownload(_:)를 아래의 코드로 대체해줍시다.

    눈에 띄는 차이점은 cancel()대신에 cancelByProducingResumeData(_:)를 호출한다는 것입니다. 코드를 보시면 cancelByProducingResumeData(_:)메소드에서 제공하는 클로져로부터 data를 가져와 Download 객체의 resume data에 넣어주고 있습니다. 나중에 다운로드를 재개할 때 사용되겠네요.

    또한 Download 객체의 isDownloading프로퍼티를 false로 세팅해주어 다운로드가 중단되었음을 알려줍니다. pause 함수가 완료되면 이제 resume을 해보도록 해야겠죠?


    resumeDownload(_:) 을 아래의 코드로 대체해주세요.


    사용자가 다운로드를 재개하면 먼저 Download 객체의 resume data가 존재하는지 확인해야 합니다. 존재한다면 resume data와 downloadTaskWithResumeData(_:)메소드를 통해 새로운  download task를 생성하여 resume()을 호출하도록 합니다. 만약 resume data가 없다면, 그냥 download URL으로 download task를 생성하여 다운로드 작업을 시작하도록 해줍니다. 

    두 경우 모두 Download객체의 isDownloading플래그를 true로 설정하여 다운로드가 재개되었음을 표시합니다.

    자 그럼 이제 위에서 구현한 세 가지 메소드의 작동을 완성시킬 최종 작업만이 남았습니다. 바로 Pause버튼, Cancel버튼, Resume버튼을 적절하게 show/hide하는 작업입니다.


    tableView(_:cellForRowAtIndexPath:) 로가서 아래 코드가 있는 라인을 찾으세요.

    그리고 이 let 바인딩 구문의 마지막에 아래 코드를 삽입해주세요.. (말이 좀 애매해서 스샷 첨부합니다.)



    pause메소드와 resume메소드가 같은 버튼을 사용하기 때문에 다운로드 상황에 따라 버튼의 이름을 적절하게 바꿔주고 있습니다.


    다음으로 아래의 코드를 tableView(_:cellForRowAtIndexPath:)의 마지막 부분 return바로 직전에 삽입해주세요.

    다운로드 중일 때만 버튼이 나타나도록 코드를 작성해 주었습니다.


    앱을 실행한 뒤 트랙 몇개를 다운로드해보세요. 다운로드를 중지하고 재개하거나 취소할 수 있습니다.







    Enabling Background Transfers

    이 쯤 되면 앱이 꽤나 모양새를 갖추었습니다. 하지만 결정적으로 백그라운드 전송을 아직 구현하지 못했습니다. 이 기능을 구현하면 앱이 백그라운드에 있건 크래쉬가 나건 다운로드는 중지되지 않고 계속 동작하게 됩니다. 


    앱이 not running인데 어떻게 가능할까요? 앱의 외부에는 백그라운드 전송을 관리하는 daemon이 존재합니다. 이놈이 앱에 메시지를 보내 다운로드 task를 수행하도록 하는 것입니다. 앱이 다운로드 도중 종료되더라도 다운로드 task는 이에 영향을 받지 않고 계속될 수 있습니다.


    다운로드가 완료되면 daemon은 백그라운드에서 앱을 재실행시킵니다.  이렇게 재실행된 앱은 똑같은 세션에 재연결을 한 뒤 completion delegate 메시지를 받아 필요한 작업을 수행합니다. 예를 들면 다운로드한 파일을 임시 위치에서 영구적인 위치로 옮기는 작업같은 일 말이죠.

    Note: If you terminate the app by force-quiting from the app switcher, the system will cancel all of the session’s background transfers and won’t attempt to relaunch the app.

    SearchViewController.swift에서 downloadsSession의 초기화부분에서 아래 코드의 라인을 찾으세요.

    그 뒤 이 코드를 아래의 코드로 대체해주세요.

    세션을 디폴트 configuration으로 생성하지 않고 background session configuration으로 생성해줍니다. 특정한 identifier를 같이 지정해줘야 한다는 것에 주의하세요. 위에서 말씀드린 세션의 재연결을 위해 필요한 identifier 입니다. 


    다음으로 viewDidLoad()메소드 내부에 아래의 코드를 추가해주세요.

    lazy load되는 downloadsSession을 생성함으로써 SearchViewController가 초기화되는 시점에 하나의 background session를 생성함을 보장하고 있습니다.


    만약 앱이 not running일 때 백그라운드 task가 완료되면 앱은 백그라운드에서 재실행됩니다. 이 시점을 AppDelegate에서 다루어주어야합니다.

    AppDelegate.swift의 제일 윗쪽에 아래코드를 추가해주세요.


    다음으로 아래의 메소드를 AppDelegate.swift에 추가해주세요.


    나중에 사용하기 위한 completionHandler를 저장해두기 위해  AppDelegate에 클로져변수를 하나 선언해두었습니다.

    그리고 application(_:handleEventsForBackgroundURLSession:)는 앱이 백그라운드 Task가 완료되었을 때 앱을 깨워주는 역할을 합니다. 이 두 가지를 이렇게 사용하도록 하죠.

    • 첫 째로, 앱은 델리게이트 메소드에서 제공받은 identifier를 통해 백그라운드 Session을 재연결합니다. 하지만 Seacrhdakfd의 객체가 생성될 때마다 하나의 백그라운드 Session을 생성하도록 해두었으니 이미 연결이 되어 있을 것입니다.
    • 다음으로 델리게이트 메소드에서 제공하는 completion handler를 capture해야 합니다. 이 completion handler를 실행하면 OS는 App Switcher에 표시할 UI 스크린샷을 찍게되고, OS에게 앱이 현재 세션에 해당하는 모든 백그라운드 작업이 완료되었음을 알려주게 됩니다.
    자 그러면 언제 이 completion handler를 invoke해야할까요? URLSessionDidFinishEventsForBackgroundURLSession(_:) 이 적절해보입니다. 이 메소드는 NSURLSessionDelegate의 메소드인데요, 백그라운드 session에 붙어있는 작업들이 모두 완료되면 호출됩니다.

    SearchViewController.swift의 확장구문인 아래 코드를 추가해주세요.

    위 코드는 AppDelegate에 저장된 completion Handler을 가져와서 main 스레드에서 실행하도록 해주고 있습니다. 


    앱을 실행해보세요. 몇개의 다운로드를 실행한 뒤에 홈버튼을 눌러 앱을 백그라운드로 보내봅시다. 다운로드가 끝났다고 생각될 때까지 기다려주세요. 그리고 홈버튼을 두번 눌러 App Switcher를 확인해 봅시다. 

    다운로드는 이미 완료된 상황일것이고 이에 따라 다운로드가 완료된 상황의 스크린샷이 화면에 보여지게 될겁니다. 앱을 열어 최종 확인해보세요.



    자 이제 앱이 완성되었습니다!!!



    Where to Go From Here?

    여기를 클릭!!!에서 이 튜토리얼 프로젝트의 최종 완성판을 다운로드 받으실 수 있습니다.
    (아래는 뒷심발휘 부족으로 여기까지만...)

    Congratulations! You’re now well-equipped to handle most common networking requirements in your app. There are more details to NSURLSession than would fit in this NSURLSession tutorial, such as upload tasks and session configuration settings such as timeout values and caching policies.

    To learn more about these features (and others!), check out the following resources:

    • Apple’s documentation which contains comprehensive details on all the API methods.
    • Our own iOS 7 By Tutorials book, with two full chapters dedicated to NSURLSession. You can also check out our earlier NSURLSession tutorial.
    • AlamoFire is a popular third-party iOS networking library; we covered the basics of it in our Beginning Alamofire tutorial.

    I hope you found this tutorial useful. Feel free to join the discussion below!




    출처 : https://www.raywenderlich.com/110458/nsurlsession-tutorial-getting-started


Designed by Tistory.