본문 바로가기

Swift

UICollectionViewCompositionalLayout 관련 데이터 소스 관리

CollectionViewCompositionalLayout을 사용하고, 다양한 데이터를 섹션별로 구성하려는 경우, 하나의 데이터 소스를 사용하는 것이 더 효율적입니다. 왜냐하면 CollectionViewCompositionalLayout은 기본적으로 섹션 단위로 데이터를 구분하여 UI를 구성하도록 설계되어 있기 때문입니다.

 

아래 함수는 외부 API를 요청하는 것으로, TMDB에 요청하여 그에 맞는 데이터를 받습니다.

func fetchNowPlayingMovies(page: Int = 1) async throws -> TMDBData {
    ...
}

func fetchPopularMovies(page: Int = 1) async throws -> TMDBData {
    ...
}

func fetchTopRatedMovies(page: Int = 1) async throws -> TMDBData {
	...
}

func fetchUpcomingMovies(page: Int = 1) async throws -> TMDBData {
	...
}

 

이때, 위의 4가지의 함수를 하나의 함수로 통합하여 요청하고, 그에 맞는 데이터 모델을 세웁니다. 

func fetchAllMovies() async throws -> CombineData {

    // 비동기 API 호출을 동시에 실행
    async let nowPlayingMovies = fetchNowPlayingMovies(page: 1)
    async let popularMovies = fetchPopularMovies(page: 1)
    async let topRatedMovies = fetchTopRatedMovies(page: 1)
    async let upcomingMovies = fetchUpcomingMovies(page: 1)

    // 모든 비동기 작업의 결과 대기
    let nowPlayingResult = try await nowPlayingMovies
    let popularResult = try await popularMovies
    let topRatedResult = try await topRatedMovies
    let upcomingResult = try await upcomingMovies

    // 결과를 하나의 TMDBData 객체로 결합
    var combinedData: CombineData = CombineData(combineTMDB: [])

    // 각 결과를 combinedData에 추가
    combinedData.combineTMDB.append(nowPlayingResult)
    combinedData.combineTMDB.append(popularResult)
    combinedData.combineTMDB.append(topRatedResult)
    combinedData.combineTMDB.append(upcomingResult)

    return combinedData
}

 

아래 데이터 모델을 기본적으로 제공되는 데이터 모델입니다. 

import Foundation

// MARK: - Welcome
struct Welcome: Codable {
    let dates: Dates
    let page: Int
    let results: [Result]
    let totalPages, totalResults: Int

    enum CodingKeys: String, CodingKey {
        case dates, page, results
        case totalPages = "total_pages"
        case totalResults = "total_results"
    }
}

// MARK: - Dates
struct Dates: Codable {
    let maximum, minimum: String
}

// MARK: - Result
struct Result: Codable {
    let adult: Bool
    let backdropPath: String
    let genreIDS: [Int]
    let id: Int
    let originalLanguage: OriginalLanguage
    let originalTitle, overview: String
    let popularity: Double
    let posterPath, releaseDate, title: String
    let video: Bool
    let voteAverage: Double
    let voteCount: Int

    enum CodingKeys: String, CodingKey {
        case adult
        case backdropPath = "backdrop_path"
        case genreIDS = "genre_ids"
        case id
        case originalLanguage = "original_language"
        case originalTitle = "original_title"
        case overview, popularity
        case posterPath = "poster_path"
        case releaseDate = "release_date"
        case title, video
        case voteAverage = "vote_average"
        case voteCount = "vote_count"
    }
}

enum OriginalLanguage: String, Codable {
    case en = "en"
    case es = "es"
    case nl = "nl"
}

 

위의 데이터 모델을 필요한 대로 데이터 모델을 변경합니다. 

TMDB를 통합한 CombineData 구조체를 새로 만들었습니다.

추가로 각 함수의 결과값에 type을 통해 구분할 수 있도록 했습니다. 

import Foundation

// MARK: - Welcome
struct CombineData: Codable, Hashable{
    var combineTMDB: [TMDBData]
}

struct TMDBData: Codable, Hashable {
    var results: [MainResults]
    var type: SectionType?
    var total_pages: Int
    var total_results: Int
}

// MARK: - Result
struct MainResults: Codable, Hashable {
    var id: Int
    var original_title: String?
    var overview: String
    var popularity: Double?
    var poster_path: String?
    var release_date: String
    var title: String
    var vote_average: Double?
    var vote_count: Int
}


enum SectionType: String, Codable {
    case noewPlayingMovie = "Now Playing Movie"
    case popularMovie = "Popular Movie"
    case topRatedMovie = "Top Rated Movie"
    case upcomingMovie = "Upcoming Movie"
}

 

'Swift' 카테고리의 다른 글

ViewModel  (1) 2025.01.08
setCustomSpacing(_:after:)의 역할  (0) 2025.01.05
async / await 사용해보기  (0) 2025.01.02
async/await란?  (0) 2024.12.18
async과 await 개요  (0) 2024.12.10