代码之家  ›  专栏  ›  技术社区  ›  Zhou Haibo

Swift:具有多类型值的字典

  •  0
  • Zhou Haibo  · 技术社区  · 4 年前

    下面的代码,dict中的值很难处理 sectionMoviesBundle = [HomeSection: [T]] 可以是 MovieViewModel ActorViewModel 哪两个是结构类型。

    那么一般来说,我该怎么处理这条格言呢 [String: [typeA or typeB...]] ,使用泛型或任何类似 nowPlaying.results.map(MovieViewModel.init) as AnyObject

    import SwiftUI
    import Combine
    
    
    class MovieListViewModel: ObservableObject {
        private var webService = WebService()
        private var cancellableSet: Set<AnyCancellable> = []
    
        @Published var sectionMoviesBundle = [HomeSection: [T]]() // Don't know how to deal with it now=.=!
    
        func getSectionMoviesBundle() {
            webService.getSectionsPublisher()
                .receive(on: DispatchQueue.main)
                .sink(receiveCompletion: { status in
                    switch status {
                    case .finished:
                        break
                    case .failure(let error):
                        print("ERROR: \(error)")
                        break
                    }
                }) { (nowPlaying, popular, upComing, topActor) in
                    self.sectionMoviesBundle[.NowPlaying] = nowPlaying.results.map(MovieViewModel.init)
                    self.sectionMoviesBundle[.Popular] = popular.results.map(MovieViewModel.init)
                    self.sectionMoviesBundle[.Upcoming] = upComing.results.map(MovieViewModel.init) 
                    self.sectionMoviesBundle[.TopActor] = topActor.results.map(ActorViewModel.init) 
            }.store(in: &self.cancellableSet)
        }
    }
    
    1 回复  |  直到 4 年前
        1
  •  0
  •   aiwiguna    4 年前

    我想你可以试试别的办法

    1. [字符串:[任何]]

    2. 创建一个协议,并将其实现到要在字典中使用的所有结构,然后使用[String:[someProtocol]]

        2
  •  0
  •   ozmpai    4 年前

    您可以使用的许多方法之一是:

    enum MovieSectionType {
        case actor, movie
    }
    protocol MovieSectionViewModelProtocol {
        var sectionType: MovieSectionType { get }
        var name: String { get set }
    }
    struct MovieViewModel: MovieSectionViewModelProtocol{
    
        var sectionType: MovieSectionType = .movie
        var name: String
        var title: String
    
    }
    struct ActorViewModel: MovieSectionViewModelProtocol {
        var sectionType: MovieSectionType = .actor
        var name: String
        var birthday: Date
    
    }
    
    class MovieListViewModel: ObservableObject {
        private var webService = WebService()
        private var cancellableSet: Set<AnyCancellable> = []
    
        @Published var sectionMoviesBundle = [HomeSection: [MovieSectionViewModelProtocol]]() // Don't know how to deal with it now=.=!
    
        func getSectionMoviesBundle() {
            self.sectionMoviesBundle[.Upcoming] = [MovieViewModel(name: "Movie", title: "Movie Title")]
            self.sectionMoviesBundle[.TopActor] = [ActorViewModel(name: "Actor", birthday: Date())]
    
            let item = self.sectionMoviesBundle[.Upcoming]!.first!
            switch item.sectionType {
            case .actor:
                guard let actor = item as? ActorViewModel else {
                    return
                }
                print(actor.birthday)
                break
            case .movie:
                guard let movie = item as? MovieViewModel else {
                    return
                }
                print(movie.title)
                break
            }
    
        }
    }
    
        3
  •  0
  •   rob mayoff    4 年前

    您可以使用sum类型,在Swift中是 enum :

    enum SectionContent {
        case actors([ActorViewModel])
        case movies([MovieViewModel])
    }
    
    @Published var sectionMoviesBundle = [HomeSection: SectionContent]()
    
    func getSectionMoviesBundle() {
        webService.getSectionsPublisher()
            .receive(on: DispatchQueue.main)
            .sink(receiveCompletion: { status in
                switch status {
                case .finished:
                    break
                case .failure(let error):
                    print("ERROR: \(error)")
                    break
                }
            }) { (nowPlaying, popular, upComing, topActor) in
                self.sectionMoviesBundle[.NowPlaying] = .movies(nowPlaying.results.map(MovieViewModel.init))
                self.sectionMoviesBundle[.Popular] = .movies(popular.results.map(MovieViewModel.init))
                self.sectionMoviesBundle[.Upcoming] = .movies(upComing.results.map(MovieViewModel.init))
                self.sectionMoviesBundle[.TopActor] = .actors(topActor.results.map(ActorViewModel.init))
        }.store(in: &self.cancellableSet)
    }