본문 바로가기

카테고리 없음

iOS 11주차

func decode<T>(T.Type, from: Data) throws -> T //시험문제 !!!

이 함수는 스위프트에서 데이터를 우리가 원하는 타입으로 바꿀 때(예: JSON → 객체) 사용해요.

예를 들어볼게요!

  1. decode = "풀다" 또는 "변환하다" 뜻이에요.
  2. T = 원하는 타입(: MyUser, UserInfo . 여러분이 만든 구조체나 클래스)
  3. from: Data = 변환하려는 데이터(: 서버에서 받은 JSON 데이터)
  4. throws = 문제가 있으면 에러를 던질 있다는 뜻이에요.

 

이 에러 메세지도 시험 문제 !! (정답 : throw로 예외처리가 안되서 나는 에러다 !)

 

이 에러 메세지도 시험 문제 

 

Main Thread Checker관련 오류이다. (이것도 시험문제)

 

오토 레이아웃을 잡는 가장 쉬운 방법 - 스택 뷰 (Stack View)

 

//
//  ViewController.swift
//  MovieRmg
//
//  Created by 유명규 on 5/8/25.
//

import UIKit

// (예제용) 임시 배열, 현재는 사용되지 않음
let name = ["야당","야당1","야당2","야당3","야당4",]

// 영화 데이터를 담는 최상위 구조체
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        // 순위
}

// 메인 뷰 컨트롤러 클래스
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
    @IBOutlet weak var table: UITableView! // 테이블뷰 아울렛
    
    // 영화 데이터를 담는 변수
    var movieData : MovieData?
    
    // 영화진흥위원회 API 기본 URL (targetDt 뒤에 날짜를 붙여 완성함)
    var movieURL = "https://kobis.or.kr/kobisopenapi/webservice/rest/boxoffice/searchDailyBoxOfficeList.json?key=7fdcde18692ba94d2f041b80501c756f&targetDt="
    
    // 뷰가 로드되었을 때 실행됨
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 테이블뷰 데이터 소스 및 델리게이트 설정
        table.dataSource = self
        table.delegate = self
        
        // 어제 날짜를 API URL에 추가
        movieURL += makeYesterdayString()
        
        // API 호출 및 데이터 받아오기
        getData()
    }
    
    // 어제 날짜를 yyyyMMdd 형식으로 반환하는 함수
    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
    }

    // API 요청 함수
    func getData() {
        guard let url = URL(string: movieURL) else { return }
        
        // URLSession 기본 설정 사용
        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 decoder = JSONDecoder()
            do {
                // 받은 JSON 데이터를 디코딩하여 movieData에 저장
                let decodedData = try decoder.decode(MovieData.self, from: JSONdata)
                self.movieData = decodedData
                
                // UI는 메인 스레드에서 업데이트해야 함
                DispatchQueue.main.async {
                    self.table.reloadData()
                }
            } catch {
                print(error)
            }
        }
        task.resume() // API 호출 실행
    }

    // 테이블뷰 셀 개수 (행 개수) 설정
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10 // 항상 10개의 박스오피스 순위를 보여줌
    }

    // 각 셀에 대한 설정
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // 커스텀 셀 가져오기 (Storyboard에서 identifier: "myCell")
        let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) as! MyTableViewCell
        
        // 순위와 영화 제목 설정
        guard let mRank = movieData?.boxOfficeResult.dailyBoxOfficeList[indexPath.row].rank else { return UITableViewCell() }
        guard let mName = movieData?.boxOfficeResult.dailyBoxOfficeList[indexPath.row].movieNm else { return UITableViewCell() }
        cell.movieName.text = "[\(mRank)위] \(mName)"
        
        // 어제 관객 수 설정 (쉼표 포맷 적용)
        if let aCnt = movieData?.boxOfficeResult.dailyBoxOfficeList[indexPath.row].audiCnt {
            let numF = NumberFormatter()
            numF.numberStyle = .decimal
            let aCount = Int(aCnt)!
            let result = numF.string(for: aCount)! + "명"
            cell.audiCount.text = "어제: \(result)"
        }

        // 누적 관객 수 설정 (쉼표 포맷 적용)
        if let aAcc = movieData?.boxOfficeResult.dailyBoxOfficeList[indexPath.row].audiAcc {
            let numF = NumberFormatter()
            numF.numberStyle = .decimal
            let aAcc1 = Int(aAcc)!
            let result = numF.string(for: aAcc1)! + "명"
            cell.audiAccumulate.text = "누적: \(result)"
        }

        return cell
    }

    // 섹션 헤더 타이틀 설정
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "🍿박스오피스(영화진흥위원회 제공: \(makeYesterdayString()))🍿"
    }

    // 섹션 푸터 타이틀 설정
    func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
        return "made by RMG"
    }

    // 셀을 클릭했을 때 호출되는 메서드
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print(indexPath.description) // 어떤 셀을 클릭했는지 로그 출력
    }

    // 테이블 뷰의 섹션 수 반환 (기본은 1개)
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
}

 

전체적인 코드를 gpt에게 설명해달라고 해보았다