본문 바로가기
iOS

iOS 실무 12주

by asd135 2025. 5. 21.
728x90

root view controller:

처음시작하는 화면을 root view controller라고함★

 

Action Segue vs Manual Segue



네이게이션바Navigation Controller를 추가하면 바뀌는 내용

 

Navigation Controller에 storyboard entry point가 생김

Navigation Controller의 navigation stack 가장 하단의 view controller를 root view controller라 하고 View Controller와 segue가 연결되어 있음 

Navigation Controller에 연결된 View Controller에 Navigation Item 생김

 

func prepare(for segue: UIStoryboardSegue, sender: Any?)★

 

destination의 자료형은 UIViewController

 

 

다운캐스트를 통해 자식 프로퍼티에 접근가능해짐

 

 

webview

 

mvc디자인패턴으로 변경

Models/MovieModels.swift

import Foundation

struct MovieData: Codable {
    let boxOfficeResult: BoxOfficeResult
}

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

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

Models/MovieService.swift

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    @IBOutlet weak var table: UITableView!
    
    var movieData: MovieData?
    var movieURL = "https://kobis.or.kr/...&targetDt="

    override func viewDidLoad() {
        super.viewDidLoad()
        table.delegate = self
        table.dataSource = self
        movieURL += makeYesterdayString()
        getData()
    }

    func makeYesterdayString() -> String { ... }

    func getData() {
        // 네트워크 통신 → Model로 디코딩
        ...
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "toDetail" {
            let dest = segue.destination as! DetailViewController
            let indexPath = table.indexPathForSelectedRow!
            dest.movieName = movieData?.boxOfficeResult.dailyBoxOfficeList[indexPath.row].movieNm ?? ""
        }
    }

    // TableView 관련 메서드: cellForRow, numberOfRows 등
}

Controllers/ViewController.swift

import UIKit

class ViewController: UIViewController {
    @IBOutlet weak var table: UITableView!
    
    var movieData: [DailyBoxOfficeList] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        table.delegate = self
        table.dataSource = self
        fetchMovieData()
    }
    
    func fetchMovieData() {
        MovieService.shared.fetchDailyBoxOffice { result in
            DispatchQueue.main.async {
                switch result {
                case .success(let data):
                    self.movieData = data.boxOfficeResult.dailyBoxOfficeList
                    self.table.reloadData()
                case .failure(let error):
                    print("Error fetching movie data: \(error)")
                }
            }
        }
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "toDetail",
           let indexPath = table.indexPathForSelectedRow,
           let destVC = segue.destination as? DetailViewController {
            destVC.movieName = movieData[indexPath.row].movieNm
        }
    }
}

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    func numberOfSections(in tableView: UITableView) -> Int { 1 }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return movieData.count
    }

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "😊박스오피스 (영화진흥위원회 제공)😊"
    }

    func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
        return "made by kgw"
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        // Navigation handled by segue
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = table.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) as? MyTableViewCell else {
            return UITableViewCell()
        }

        let movie = movieData[indexPath.row]
        cell.configure(with: movie)
        return cell
    }
}

Views/MyTableViewCell.swift

import UIKit

class MyTableViewCell: UITableViewCell {
    @IBOutlet weak var audiAccumulate: UILabel!
    @IBOutlet weak var audiCount: UILabel!
    @IBOutlet weak var movieName: UILabel!

    func configure(with movie: DailyBoxOfficeList) {
        movieName.text = "[\(movie.rank)위] \(movie.movieNm)"
        
        if let count = Int(movie.audiCnt) {
            audiCount.text = "어제: \(NumberFormatter.localizedString(from: NSNumber(value: count), number: .decimal))명"
        } else {
            audiCount.text = "어제: -"
        }

        if let acc = Int(movie.audiAcc) {
            audiAccumulate.text = "누적: \(NumberFormatter.localizedString(from: NSNumber(value: acc), number: .decimal))명"
        } else {
            audiAccumulate.text = "누적: -"
        }
    }
}

Controllers/DetailViewController.swift (변경 없음)

import UIKit
import WebKit

class DetailViewController: UIViewController {
    @IBOutlet weak var webView: WKWebView!
    var movieName = ""

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.title = "[\(movieName)]"

        let encoded = "https://search.naver.com/search.naver?query=" + movieName
        if let urlStr = encoded.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed),
           let url = URL(string: urlStr) {
            webView.load(URLRequest(url: url))
        }
    }
}

'iOS' 카테고리의 다른 글

iOS 실무11주  (0) 2025.05.14
iOS 실무10주차  (0) 2025.05.07
iOS 실무 9주차  (0) 2025.05.05
iOS 실무 7주차  (0) 2025.04.16
iOS 실무 6주차  (0) 2025.04.09