简体   繁体   中英

Two different model types in same view model? Swift - Xcode?

Im working on a project which uses GraphQL to get product information from a shopify store. I query data by searching the products ProductID and get the data in the form Storefront.Product. However my view model requires it to be in the form Storefront.ProductEdge.

Im trying to adding two different model types (Storefront.Product and Storefront.ProductEdge) in the same view model (ProductViewModel).

Heres my code:

import Foundation
import Buy

final class ProductViewModel: ViewModel {

    typealias ModelType = Storefront.ProductEdge
    typealias ModelType1 = Storefront.Product

    let model:    ModelType
    let model1:   ModelType1
    let cursor:   String

    var id:       String
    var title:    String
    var summary:  String
    var price:    String
    var images:   PageableArray<ImageViewModel>
    var variants: PageableArray<VariantViewModel> ///Ive changed let to var here so i can assign values in HomeController

    // ----------------------------------
    //  MARK: - Init -
    //
    required init(from model: ModelType) {
        self.model    = model
        self.cursor   = model.cursor

        let variants = model.node.variants.edges.viewModels.sorted {
            $0.price < $1.price
        }

        let lowestPrice = variants.first?.price

        self.id       = model.node.id.rawValue
        self.title    = model.node.title
        self.summary  = model.node.descriptionHtml
        self.price    = lowestPrice == nil ? "No price" : Currency.stringFrom(lowestPrice!)

        self.images   = PageableArray(
            with:     model.node.images.edges,
            pageInfo: model.node.images.pageInfo
        )

        self.variants = PageableArray(
            with:     model.node.variants.edges,
            pageInfo: model.node.variants.pageInfo
        )
    }


    required init(from model1: ModelType1){
        self.model1 = model1


        self.cursor = ""

        let variants = model1.variants.edges.viewModels.sorted {
            $0.price < $1.price
        }
        let lowestPrice = model1.variants.edges.first?.viewModel.price

        self.id = model1.id.rawValue
        self.title = model1.title
        self.summary = model1.descriptionHtml
        self.price = lowestPrice == nil ? "No price" : Currency.stringFrom(lowestPrice!)

        self.images = PageableArray(
            with: model1.images.edges,
            pageInfo: model1.images.pageInfo
        )

        self.variants = PageableArray(
            with: model1.variants.edges,
            pageInfo: model1.variants.pageInfo
        )

    }

}

extension Storefront.ProductEdge: ViewModeling {
    typealias ViewModelType = ProductViewModel
}

It is saying

Return from initializer without initializing all stored properties

Is this possible to do?

please help?

EDIT:

By making model and model1 options or using Enums on model or model1, I get the error

Type 'ProductViewModel' does not conform to protocol 'ViewModel'

Do I need to somehow do an If statement or enum on Storefront.ProductEdge and Storefront.Product??

here is the ViewModel protocol:

import Foundation

protocol ViewModel: Serializable {

    associatedtype ModelType: Serializable

    var model: ModelType { get }

    init(from model: ModelType)
}

extension ViewModel {

    static func deserialize(from representation: SerializedRepresentation) -> Self? {
        if let model = ModelType.deserialize(from: representation) {
            return Self.init(from: model)
        }
        return nil
    }

    func serialize() -> SerializedRepresentation {
        return self.model.serialize()
    }
}

. I am unable to change this protocol.

Please help?

In Swift you are required to assign a value to all properties before exiting an initializer. It appears that in both cases you're either not assigning a value to model or model1 . If it's intentional for on our the other to be used, but not both, I'd recommend an enum with an associated value. Something like this:

enum ModelObject {
    case model(Model)
    case model1(Model1)
}

Then in your initializer you can do:

self.modelObject = .model1(model1)

or

self.modelObject = .model(model)

If for some reason that doesn't work, you could also make them both optional and assign one to nil and the other to the value it was initialized with.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM