네트워킹 API, JSON Parsing

인생노잼시기·2021년 6월 15일
0

FLO-클론코딩

목록 보기
3/3

꼼꼼한 재은 씨 기초편에서 봤던 내용

//웹에 있는 데이터를 가져오는 방법
        //cell.thumbnail.image = UIImage(data: try! Data(contentsOf: URL(string: row.thumbnail!)!)) 축약
        let url: URL! = URL(string: row.thumbnail!)
        let imageData = try! Data(contentsOf: url)
        cell.thumbnail.image = UIImage(data: imageData)
    //처음 한 번만 실행
    override func viewDidLoad() {
        
        //URL은 파운데이션 프레임워크에 정의된 객체, NSURL클래스를 바탕으로 만들어짐
        let url = "http://swiftapi.rubypaper.co.kr:2029/hoppin/movies?version=1&page=1&count=10&genreId=&order=releasedateasc"
        let apiURL: URL! = URL(string: url)
        
        //restAPI GET방식으로 호출
        let apidata = try! Data(contentsOf: apiURL)
        
        //NSString 타입의 문자열로 변환해 로그로 출력 (데이터를 편리하게 인코딩해서 문자열로 변환할 수 있다)
        let log = NSString(data: apidata, encoding: String.Encoding.utf8.rawValue) ?? ""
        NSLog("API Result=\(log)")
        
        do {
            //JSON객체를 파싱하여 NSDictionary 객체러 변환
            let apiDictionary = try JSONSerialization.jsonObject(with: apidata, options: []) as! NSDictionary
        
            let hoppin = apiDictionary["hoppin"] as! NSDictionary
            let movies = hoppin["movies"] as! NSDictionary  //{키:값} 형태일 때
            let movie = movies["movie"] as! NSArray //[값] 형태일 때
            
            for row in movie {
                let r = row as! NSDictionary
                let mvo = MovieVO()
                mvo.title = r["title"] as? String
                mvo.description = r["genreNames"] as? String
                mvo.thumbnail = r["thumbnailImage"] as? String
                mvo.detail = r["linkUrl"] as? String
                mvo.rating = (r["ratingAverage"] as! NSString).doubleValue
                
                self.list.append(mvo)
            }
        } catch {
            
        }
    }

Udemy에서 봤던 내용

URL session 활용하기

//
//  WeatherManager.swift
//  Clima
//
//  Created by Angela Yu on 03/09/2019.
//  Copyright © 2019 App Brewery. All rights reserved.
//

import Foundation
import CoreLocation

protocol WeatherManagerDelegate {
    func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel)
    func didFailWithError(error: Error)
}

struct WeatherManager {
    let weatherURL = "https://api.openweathermap.org/data/2.5/weather?appid=e72ca729af228beabd5d20e3b7749713&units=metric"
    
    var delegate: WeatherManagerDelegate?
    
    func fetchWeather(cityName: String) {
        let urlString = "\(weatherURL)&q=\(cityName)"
        performRequest(with: urlString)
    }
    
    func fetchWeather(latitude: CLLocationDegrees, longitude: CLLocationDegrees) {
        let urlString = "\(weatherURL)&lat=\(latitude)&lon=\(longitude)"
        performRequest(with: urlString)
    }
    
    func performRequest(with urlString: String) {
        if let url = URL(string: urlString) {
            let session = URLSession(configuration: .default)
            let task = session.dataTask(with: url) { (data, response, error) in
                if error != nil {
                    self.delegate?.didFailWithError(error: error!)
                    return
                }
                if let safeData = data {
                    if let weather = self.parseJSON(safeData) {
                        self.delegate?.didUpdateWeather(self, weather: weather)
                    }
                }
            }
            task.resume()
        }
    }
    
    func parseJSON(_ weatherData: Data) -> WeatherModel? {
        let decoder = JSONDecoder()
        do {
            let decodedData = try decoder.decode(WeatherData.self, from: weatherData)
            let id = decodedData.weather[0].id
            let temp = decodedData.main.temp
            let name = decodedData.name
            
            let weather = WeatherModel(conditionId: id, cityName: name, temperature: temp)
            return weather
            
        } catch {
            delegate?.didFailWithError(error: error)
            return nil
        }
    }
    
    
    
}

//
//  ViewController.swift
//  Clima
//
//  Created by Angela Yu on 01/09/2019.
//  Copyright © 2019 App Brewery. All rights reserved.
//

import UIKit
import CoreLocation

class WeatherViewController: UIViewController {
    
    var weatherManager = WeatherManager()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        weatherManager.delegate = self
    }

}

extension WeatherViewController: WeatherManagerDelegate {
    
    func didUpdateWeather(_ weatherManager: WeatherManager, weather: WeatherModel) {
        DispatchQueue.main.async {
            self.temperatureLabel.text = weather.temperatureString
            self.conditionImageView.image = UIImage(systemName: weather.conditionName)
            self.cityLabel.text = weather.cityName
        }
    }
    
    func didFailWithError(error: Error) {
        print(error)
    }
}

URLSession를 구성하거나 Data를 사용해서 데이터를 가져올 수 있다.

URLSession을 사용하면 HTTP를 포함한 몇 가지 프로토콜을 지원하고, 인증, 쿠키 관리, 캐시 관리 등을 지원합니다.

  • URLSession Life Cycle
    • 세션 구성 및 생성
    • URL과 request객체 설정
    • Task를 결정하고 그에 맞는 Completion Hanlder나 Delegate 메소드를 작성
    • Task 실행
    • Completion Handler 실행

세션을 연결한 상태라면 앱이 실행되지 않는 상태여도 다운로드를 받을 수 있다!!! 이게 더 실제와 비슷한 거 같다
백그라운드상태에서도 음악 재생하기가 이런 기능인건가?

https://hcn1519.github.io/articles/2017-07/iOS_URLSession

HTTP requests & background downloads 실습

일시정지되거나 다시 재생할 수 있는 백그라운드 만들기

Saving and Playing the Track 부터...
와 아예 세션 연결해서
다운로드 하는 거네

URLSession 애플 개발자 문서 톺아보기

Foundation > URL Loading System > URLSession
class URLSession : NSObject

  • iOS에서는 앱이 not running이거나 suspended 상태에서 background 다운로드가 가능하다.
    (not running은 실행 전, suspended는 백그라운드에서 실행되지 않을 때)

  • 주요 delegate

    • URLSessionDelegate
    • URLSessionTaskDelegate
  • URLSession의 종류
    URLSessionConfiguration으로 설정

      1. Default Session
        디스크 기반 캐싱
      1. Ephemeral Session
        데이터를 저장하지 않는 세션
      1. Background Session
        앱이 종료된 이후에도 통신이 이뤄지는 세션
  • URL Session Tasks의 종류

    • Data tasks: send and receive data using NSData objects.
    • Upload tasks: support background uploads while the app isn’t running.
    • Download tasks: support background downloads and uploads while the app isn’t running.
    • WebSocket tasks: WebSocket(RFC 6455)을 통한 TCP and TLS
  • URLSessionTaskDelegate
    세션은 strong 참조 관계를 가지고 있기 때문에 주의해야한다.
    세션의 콜백 task를 관리하기 위해 URLSessionTaskDelegate를 사용한다.

  • 비동기성 Asynchronicity
    download(from:delegate:)다운로드 받으면서, data(from:delegate:)데이터를 가져올 수 있다.
    전송이 완료되기 까지 await 키워드를 사용해 지연시킬 수 있다.
    bytes(from:delegate:) 비동기적인 순서로 데이터를 가져올 수 있다.

  • URLProtocol을 상속받아 프로토콜도 사용 가능

URL Loading System


왼쪽은 기본 검색을 지원하는 Default 세션
오른쪽은 Private한 검색을 지원하는 Ephemeral한 세션으로 캐싱하지 않는다
하나의 URLSession에 여러가지 Task가 있다

https://developer.apple.com/documentation/foundation/urlsession
https://www.raywenderlich.com/3244963-urlsession-tutorial-getting-started

profile
인생노잼

0개의 댓글