swift tabbar controller tableview 영화목록 영화관 스위프트 테이블뷰 탭바 컨트롤러
//
// 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!
}
//
// 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?
}
//
// 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) 번째 행입니다.")
}
}
//
// TheaterCell.swift
// MyMovieChart
//
// Created by stayfoolish on 27/11/2018.
// Copyright © 2018 stayfoolish. All rights reserved.
//
import UIKit
class TheaterCell: UITableViewCell {
@IBOutlet var name: UILabel! // 상영관명
@IBOutlet var tel: UILabel! // 연락처
@IBOutlet var addr: UILabel! // 주소
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
//
// TheaterListController.swift
// MyMovieChart
//
// Created by stayfoolish on 27/11/2018.
// Copyright © 2018 stayfoolish. All rights reserved.
//
import UIKit
class TheaterListController: UITableViewController {
// API를 통해 불러온 데이터를 저장할 배열 변수
var list = [NSDictionary]()
// 읽어올 데이터의 시작위치
var startPoint = 0
override func viewDidLoad() {
super.viewDidLoad()
self.callTheaterAPI()
}
func callTheaterAPI(){
// URL을 구성하기 위한 상수값을 선언한다.
let requestURI = "http://swiftapi.rubypaper.co.kr:2029/theater/list" // API 요청 주소
let sList = 100 // 불러올 데이터 갯수
let type = "json" // 데이터 형식
// 인자값을 모아 URL 객체로 정의한다.
let urlObj = URL(string: "\(requestURI)?s_page=\(self.startPoint)&s_list=\(sList)&type=\(type)")
do {
// NSString 객체를 이용하여 API를 호출하고 그 결과값을 인코딩된 문자열로 받아온다.
let stringdata = try NSString(contentsOf: urlObj!, encoding: 0x80_000_422)
// 문자열로 받은 데이터를 UTF-8로 인코딩 처리한 Data로 변환한다.
let encdata = stringdata.data(using: String.Encoding.utf8.rawValue)
do {
// Data 객체를 파싱하여 NSArray 객체로 변환한다.
let apiArray = try JSONSerialization.jsonObject(with: encdata!, options: []) as? NSArray
// 읽어온 데이터를 순회하면서 self.list 배열에 추가한다.
for obj in apiArray! {
self.list.append(obj as! NSDictionary)
}
}catch {
// 경고창 형식으로 오류 메세지를 표시해준다.
let alert = UIAlertController(title: "실패", message: "데이터 분석이 실패하였습니다.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "확인", style: .cancel))
self.present(alert, animated: false)
}
// 읽어와야 할 다음 페이지의 데이터 시작 위치를 구해 저장해둔다.
self.startPoint += sList
}catch {
// 경고창 형식으로 오류 메세지를 표시해준다.
let alert = UIAlertController(title: "실패", message: "데이터를 불러오는데 실패하였습니다.", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "확인", style: .cancel ))
self.present(alert, animated: false)
}
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return self.list.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// self.list 배열에서 행에 맞는 데이터를 꺼냄
let obj = self.list[indexPath.row]
// 재사용 큐로부터 tCell 식별자를 맞는 셀 객체를 전달받음
let cell = tableView.dequeueReusableCell(withIdentifier: "tCell", for: indexPath) as! TheaterCell
cell.name?.text = obj["상영관명"] as? String
cell.tel?.text = obj["연락처"] as? String
cell.addr?.text = obj["소재지도로명주소"] as? String
return cell
}
/*
// Override to support conditional editing of the table view.
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
*/
/*
// Override to support editing the table view.
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
// Delete the row from the data source
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
}
}
*/
/*
// Override to support rearranging the table view.
override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
}
*/
/*
// Override to support conditional rearranging of the table view.
override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the item to be re-orderable.
return true
}
*/
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
'Swift > 기초&문법' 카테고리의 다른 글
swift submitvalue back userdefaults 스위프트 이전 화면 유저디폴트 데이터 전달 (0) | 2018.11.25 |
---|---|
swift submitvalue back appdelegate 스위프트 이전 화면 앱딜리게이트 데이터 전달 (0) | 2018.11.24 |
swift submitvalue back 스위프트 이전 화면으로 데이터 전달 (1) | 2018.11.23 |
swift prepare sugue 스위프트 세그 데이터 전달 (0) | 2018.11.22 |
swift submitvalue present push 스위프트 데이터 전달 (0) | 2018.11.21 |