1

I want to map between any two objects which conform to the same protocol. It would be convenient to do so via a function with the signature:

func mapFrom<T>(objectA: T, to inout objectB: T)

Even better though (for immutable types) would be to have it in the form:

func map<T, U: T>(from source: T) -> U

where somehow it could initialize a U object from the values in T.

I would like to do this via Swift Reflection rather than using the Objective-C run-time, but I would settle for that if it was the only way. If somehow it could be done without reflection that would be amazing, but I don't see how.

The reason I want to do this is because I have mutable Realm classes which conform to their respective protocol, and I want to map them to the immutable struct types.

An example would be:

/**
    The protocol.
 */
protocol Food {
    var name: String { get }
    var weight: Float { get }
    var price: Float { get }
}

/**
    The mutable Realm class representation.
 */
final class FoodEntity: Object, Food {
    dynamic var name = ""
    dynamic var weight = 0.0
    dynamic var price = 0.0
}

/**
    The final struct I want to map to from the Realm representation.
 */
struct FoodProduct: Food {
    let name: String
    let weight: Float
    let price: Float
}

I would like to be able to have a generic function or method with which to map a FoodEntity to a FoodProduct without having to manually do something like:

FoodProduct(name: entity.name, weight: entity.weight, price: entity.price)

How can this be done, if it can be done at all?

Infinity James
  • 4,667
  • 5
  • 23
  • 36

1 Answers1

0

I think you are looking for something like this.

 func fetchAllFoodProducts() -> [FoodProduct]
    {
        var foodProducts : [FoodProduct] = []

        // Fetch From Realm

        let products = realm.objects(FoodEntity.self)

        for product in products
        {
            foodProducts.append(FoodProduct(name: product.name, weight: product.weight, price: product.price))
        }

        return foodProducts
    }

The thing is that there can't be a generic way to do this. Because you have to assign the values of name, weight & price somehow. This is the closest you can get, I think.

Or you can do something like this.

 func fetchAllFoodProducts() -> [FoodProduct]
    {
        var foodProducts : [FoodProduct] = []

        // Fetch From Realm

        let products = realm.objects(FoodEntity.self)

        for product in products
        {
           foodProducts.append(FoodProduct(entity: product))
        }

        return foodProducts
    }

By altering your FoodEntity a little.

 struct FoodProduct: Food {
        let name: String
        let weight: Float
        let price: Float

        init(entity : FoodEntity)
        {
            self.name = entity.name
            self.weight = entity.weight
            self.price = entity.price
        }
    }