꼼꼼한 재은씨의 스위프트 swift 기본편 영화목록 앱 api json






//

//  MovieVO.swift

//  MyMovieChart

//

//  Created by stayfoolish on 28/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import Foundation

import UIKit


class MovieVO {

    var thumbnail: String? // 영화 섬네일 이미지 주소

    var title: String? // 영화 제목

    var description: String? // 영화 설명

    var detail: String? // 상세정보

    var opendate: String? // 개봉일

    var rating: Double? // 평점

    

    // 영호 썸네일 이미지를 담을 UIImage 객체를 추가한다.

    var thumbnailImage: UIImage?

}



//

//  MovieCell.swift

//  MyMovieChart

//

//  Created by stayfoolish on 29/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class MovieCell: UITableViewCell {

    

    @IBOutlet var title: UILabel!

    @IBOutlet var desc: UILabel!

    @IBOutlet var opendate: UILabel!

    @IBOutlet var rating: UILabel!

    @IBOutlet var thumbnail: UIImageView!

    

}



//

//  ListViewController.swift

//  MyMovieChart

//

//  Created by stayfoolish on 28/10/2018.

//  Copyright © 2018 stayfoolish. All rights reserved.

//


import UIKit


class ListViewController: UITableViewController {

    

    @IBOutlet var moreBtn: UIButton!

    

    /*

    // 튜플 아이템으로 구성된 데이터 세트

    var dataset = [

        ("다크 나이트","영웅물에 철학에 음악까지 더해져 예술이 되다.","2008-09-04",8.95,"darknight.jpg"),

        ("호우시절","때를 알고 내리는 좋은 비","2009-10-08",7.31,"rain.jpg"),

        ("말할 수 없는 비밀","여기서 너까지 다섯 걸음","2015-05-07",9.19,"secret.jpg")

    ]

    */

    

    // 현재까지 읽어온 데이터의 페이지 정보

    var page = 1

    

    // 테이블 뷰를 구성할 리스트 데이터

    lazy var list: [MovieVO] = {

        var datalist = [MovieVO]()

       /*

        for (title, desc, opendate, rating, thumbnail) in self.dataset {

            let mvo = MovieVO()

            mvo.title = title

            mvo.description = desc

            mvo.opendate = opendate

            mvo.rating = rating

            mvo.thumbnail = thumbnail

            

            datalist.append(mvo)

        }

       */

        return datalist

    }()



    @IBAction func more(_ sender: UIButton) {

    // 0) 현재 페이지 값에 1을 추가한다.

    self.page += 1

    

    // 영화차트 API를 호출한다.

    self.callMovieAPI()

        

        

    // 데이터를 다시 읽어오도록 테이블 뷰를 갱신한다.

    self.tableView.reloadData()

    }

    

    

    // 뷰가 처음 메모리에 로드될 때 호출되는 메소드

    override func viewDidLoad() {

        // 영화차트 API를 호출한다.

        self.callMovieAPI()


    }

    

    func callMovieAPI() {

        // 1) 호핀 API를 호출을 위한 URI를 생성

//        let url = "http://swiftapi.rubypaper.co.kr:2029/hoppin/movies?version=1&page=\(self.page)&count=10&genreId=&order=releasedateasc"

        let url = "http://swiftapi.rubypaper.co.kr:2029/hoppin/movies?version=1&page=\(self.page)&count=30&genreId=&order=releasedateasc"

        

        let apiURL: URL! = URL(string: url)

        

        // 2) REST API를 호출

        let apidata = try! Data(contentsOf: apiURL)

        

        // 3) 데이터 전송 결과를 로그로 출력 (반드시 필요한 코드는 아님)

        let log = NSString(data: apidata, encoding: String.Encoding.utf8.rawValue) ?? "데이터가 없습니다"

        NSLog("API Result=\( log )")

        

        // 4) JSON 객체를 파싱하여 NSDictionary 객체로 받음

        do {

            let apiDictionary = try JSONSerialization.jsonObject(with: apidata, options: []) as! NSDictionary

            

            // 5) 데이터 구조에 따라 차례대로 캐스팅하며 읽어온다.

            let hoppin = apiDictionary["hoppin"] as! NSDictionary

            let movies = hoppin["movies"] as! NSDictionary

            let movie = movies["movie"] as! NSArray

            

            // 6) Iterator 처리를 하면서 API 데이터 MovieVO 객체에 저장한다.

            for row in movie {

                // 순회 상수를 NSDictionary 타입으로 캐스팅

                let r = row as! NSDictionary

                

                // 테이블 뷰 리스트를 구성할 데이터 형식

                let mvo = MovieVO()

                

                // movie 배열의 각 데이터를 mvo 상수의 속성에 대입

                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)

                

                // 웹상에 있는 이미지를 읽어와 UIImage 객체로 설정

                let url: URL! = URL(string: mvo.thumbnail!)

                let imageData = try! Data(contentsOf: url)

                mvo.thumbnailImage = UIImage(data:imageData)

                

                

                // list 배열에 추가

                self.list.append(mvo)

                

                // 7) 전체 데이터 카우트를 얻는다.

                let totalCount = (hoppin["totalCount"] as? NSString)!.integerValue

                

                // 8) totalCount가 읽어온 데이터 크기와 같거나 클 경우 더보기 버튼을 막는다.

                if (self.list.count >= totalCount){

                    self.moreBtn.isHidden = true

                }

            }

        }catch { NSLog("Parse Error!!")}

    }

    

    func getThumnailImage(_ index: Int) -> UIImage {

        // 인자값으로 받은 인덱스를 기반으로 해당하는 배열 데이터를 읽어옴

        let mvo = self.list[index]

        

        // 메모이제이션 : 저장된 이미지가 있으면 그것을 반환하고, 없을 경우 내려받아 저장한 후 반환

        if let savedImage = mvo.thumbnailImage {

            return savedImage

        }else {

            let url: URL! = URL(string: mvo.thumbnail!)

            let imageData = try! Data(contentsOf: url)

            mvo.thumbnailImage = UIImage(data:imageData) // UIImage를 MovieVO 객체에 우선 저장

            

            return mvo.thumbnailImage! // 저장된 이미지를 반환

        }

        

        

    }


    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

            return self.list.count

    }

    

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        // 주어진 행에 맞는 데이터 소스를 읽어온다.

        let row = self.list[indexPath.row]

        

        // 로그 출력

        NSLog("제목:\(row.title!), 호출된 행번호:\(indexPath.row)")

        

        // 테이블 셀 객체를 직접 생성하는 대신 큐로부터 가져옴

        // as! UITableViewCell => as! MovieCell 로 캐스팅 타입 변경

        let cell = tableView.dequeueReusableCell(withIdentifier: "ListCell") as! MovieCell

        

        // 데이터 소스에 저장된 값을 각 아울렛 변수에 할당

        cell.title?.text = row.title

        cell.desc?.text = row.description

        cell.opendate?.text = row.opendate

        cell.rating?.text = "\(row.rating!)"


        /*

        // 섬네일 경로를 인자값으로 하는 URL 객체를 생성

        let url: URL! = URL(string: row.thumbnail!)

        

        // 이미지를 읽어와 Data 객체에 저장

        let imageData = try! Data(contentsOf: url)

        

        // UIImage 객체를 생성하여 아울렛 변수의 image 속성에 대입

        cell.thumbnail.image = UIImage(data: imageData)

        */

        

        /*

        // 이미지 객체를 대입힌다.

        cell.thumbnail.image = row.thumbnailImage

        */

        

        // 비동기 방식으로 섬네일 이미지를 읽어옴

        DispatchQueue.main.async(execute: {

            NSLog("비동기 방식으로 실행되는 부분입니다")

            cell.thumbnail.image = self.getThumnailImage(indexPath.row)

        })

 

        NSLog("메소드 실행을 종료하고 셀을 리턴합니다.")

        // 셀 객체를 반환

        return cell

    }

    

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        NSLog("선택된 행은 \(indexPath.row) 번째 행입니다.")

    }

}




+ Recent posts