처음부터 차근차근

OpenAPI 사용해서 앱만들기 본문

프로그래밍/Swift

OpenAPI 사용해서 앱만들기

_soyoung 2022. 5. 19. 20:25
반응형

사전 지식

1급 객체(first class object), 1급 시민(first class citizen)

Swift의 함수는 1급 객체이다.

 

1급 객체의 조건

1) 변수에 저장할 수 있다.

func inchesToFeet (inches: Float) -> Float {
	return inches * 0.0833333
}
let toFeet = inchesToFeet 
print(toFeet(10))

 

2) 매개변수로 전달할 수 있다.

func inchesToFeet (inches: Float) -> Float {
	return inches * 0.0833333
}
func outputConversion(converterFunc: (Float) -> Float, value: Float) {//함수를 매개변수로 사용
	let result = converterFunc(value) //toFeet(10)
	print("Result = \(result)")
}

outputConversion(converterFunc:toFeet, value: 10)

 

3) 리턴값으로 사용할 수 있다.

func inchesToFeet (inches: Float) -> Float {
	return inches * 0.0833333
}
func inchesToYards (inches: Float) -> Float {
	return inches * 0.0277778
}


func decideFunction (feet: Bool) -> (Float) -> Float { //매개변수형 리턴형이 함수형
	if feet {
		return toFeet //함수를 리턴
	} else {
		return toYards
	}
}

let myFunc = decideFunction(feet: true)

 

 

클로저(closure)

func add(x: Int, y: Int) -> Int {
	return(x+y)
}

// 클로저
let add1 = { (x: Int, y: Int) -> Int in
	return(x+y)
}

 

 

후행 클로저(trailing closure)

클로저가 함수의 마지막 argument라면 마지막 매개변수명을 생략한 후 함수 소괄호 외부에 클로저를 작성한다.

func math(x: Int, y: Int, cal: (Int, Int) -> Int) -> Int {
	return cal(x, y)
}

// 클로저 구현
func math(x: Int, y: Int, cal: {(val1: Int, val2: Int) -> Int in
	return val1 + val2
})

// 후행 클로저
func math(x: Int, y: Int) {(val1: Int, val2: Int) -> Int in
	return val1 + val2
})

 

 

OpenAPI 사용

1. movieURL지정과 데이터 가져올 메서드 지정하고 호출

필자의 경우 영화진흥위원회 Open API를 사용함

let movieURL = "https://www.kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=자신이발급받은키&targetDt=20220530"

주의 사항 : http를 https로 변경해야함

 

2. 네트워킹

1) URL 만들기

failable initializer이므로 url을 옵셔널 바인딩

 

2) URLSession 만들기


3) URLSession 인스턴스에게 task주기

dataTask(with:completionHandler:)

지정된 URL의 내용을 검색하는 작업을 만든(create) 다음, 완료시 handler(클로저)를 호출


4) task시작하기( task.resume() )

task.resume() 

작업이 일시 중단된(새로 초기화된 작업) 경우 다시 시작하는 메서드

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    table.delegate = self
    table.dataSource = self

    //movieURL += makeYesterdayString()
    getData()
}

func getData() {
    guard let url = URL(string: movieURL) else {return} // URL 만들기
    let session = URLSession(configuration: .default) // URL Session 만들기

    // URLSession 인스턴스에게 task주기
    let task = session.dataTask(with: url) { (data, response, error) in 
        if error != nil {
            print(error!)
            return
        }
        guard let JSONdata = data else { return }
            let dataString = String(data: JSONdata, encoding: .utf8)
            print(dataString!) //data를 String형식으로 찍어 보기

    }
    task.resume()
}

 

 

3. 파싱을 쉽게 하기 위한 MovieData형 구조체 만들기

리턴되는 json의 형태가 이미지와 같으므로 아래의 구조체를 만든다.

 

struct  MovieData : Codable {
    let  boxOfficeResult : BoxOfficeResult
}

struct  BoxOfficeResult : Codable {
    let  dailyBoxOfficeList : [DailyBoxOfficeList]
}

struct  DailyBoxOfficeList : Codable {
    let  movieNm : String
    let  audiCnt : String
    let  audiAcc : String
}

moviewNm : 영화명

audioCnt : 해당일의 관객수

audioAcc : 누적 관객수

 

 

4. JSONDecoder 객체 만들고, decode 함수 예외처리해서 호출.

그리고 MovieData형 프로퍼티 만들어 decodedData 저장

var movieData : MovieData?
func getData() {
    guard let url = URL(string: movieURL) else {return}
    let session = URLSession(configuration: .default)
    let task = session.dataTask(with: url) { (data, response, error) in
        if error != nil {
            print(error!)
            return
        }
        guard let JSONdata = data else { return }
        let dataString = String(data: JSONdata, encoding: .utf8)
        print(dataString!)
        let decoder = JSONDecoder()
        do {
            let decodedData = try decoder.decode(MovieData.self, from: JSONdata)
            self.movieData = decodedData
            DispatchQueue.main.async {
                self.table.reloadData()
            }
        }catch{
            print(error)
        }
    }
    task.resume()
}

JSONDecoder : JSON객체에서 데이터 타입의 인스턴스를 디코딩하는 객체

 

func decode(_ type: T.Type, from data: Data) throws -> T where T : Decodable

 

static metatype : .self

String이 type이고 ”Hello”가 instance의 value

String.Type은 type이고 String.self가 metatype의 value

.self는 static metatype이고 compile time에서의 object type

 

reloadData() : 테이블 뷰의 row과 section을 다시 로드

DispatchQueue.main.async { } :

앱의 기본 스레드(메인 스레드) 또는 백그라운드 스레드에서 작업 실행을 순차 또는 동시 처리로 관리하는 개체

현재 프로세스의 main 스레드와 관련된 디스패치 큐

UI관련 소스는 main thread에서 처리해야하기 때문에 이 함수를 사용한다!

 

 

예외처리(exception handling)

런타임 시 오류를 발견하여 응답하고 복구하는 과정이다.

작업이 실패할 때 코드가 적절히 응답할 수 있도록 함으로써 오류의 원인을 이해하는 데 도움을 줄 수 있다.

 

오류의 원인에 따라 다양한 대응이 필요한 경우, 오류의 정보를 정확히 전달함으로써 오류를 복구하는데 도움을 줄 수 있다.

ex) 디스크상의 파일을 읽어서 처리하는 작업에서 발생할 수 있는 오류 ('존재하지 않는 파일', '읽기 권한 없음', '호환되는 형식이 아님' 등 다양)

Swift 2.0 이후부터 error handling을 도입했다.

 

오류 처리 4가지 방법

  • Throwing Functions을 이용한 오류 전파(Propagating Errors Using Throwing Functions)
  • Do-Catch를 이용한 오류 처리(Handling Errors Using Do-Catch)
  • Error를 Optional Values로 변환(Converting Errors to Optional Values
  • 오류 전파 비활성화(Disabling Error Propagation)

 

throwing function

func add(_ number: Int) throws -> Int {    // 1
   guard number > 0 else { 
       throw TestError.outOfRange                // 2
   } 
   return number + 1
}

 

To indicate that a function, method, or initializer can throw an error, 
you write the throws keyword in the function’s declaration after its parameters.

함수, 메서드 또는 이니셜라이저가 오류를 던질 수 있음을 나타내려면,
함수 선언에서 매개변수 뒤에 throw 키워드를 작성합니다.

 

 

do~try~catch

do {
	try 오류 발생 코드
	오류가 발생하지 않으면 실행할 코드
} catch 오류패턴1 {
	처리 코드
} catch 오류패턴2 where 조건 {
	처리 코드
} catch {
	처리 코드
}

 

Label 디자인 변경시 : Resolve Auto Layout Issues

바뀐 것으로 업데이트 인터페이스빌더가 제안 모든 제약 삭제

 

Selected Views vs All Views in View Controller

가장 쉬운 방법: Clear후 Reset

 

 

개선 : 앱을 실행하면 어제 날짜로 자동 조회하기

    var movieData : MovieData?
    var movieURL = "https://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=3c47a88b3298a90aabde4fef7b450779&targetDt=20220522"
    @IBOutlet weak var table: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        table.delegate = self
        table.dataSource = self
        
        movieURL += makeYesterdayString()
        getData()
    }
    
    func makeYesterdayString() -> String {
        let y = Calendar.current.date(byAdding: .day, value: -1, to: Date())!
        let dateF = DateFormatter()
        dateF.dateFormat = "yyyyMMdd"
        let day = dateF.string(from: y)
        return day
    }

 

 

출처 : iOS프로그래밍실무(22-1학기)한성현교수 강의 내용 변형 및 요약

반응형

'프로그래밍 > Swift' 카테고리의 다른 글

RESTful과 OpenAPI  (0) 2022.05.16
TableView  (0) 2022.05.13
Swift 용어 정리  (0) 2022.05.09
간단한 앱 만들기 실습  (0) 2022.04.16
Swift 문법 복습5  (0) 2022.04.11
Comments