Skip to content

Closure Transformations

Anton edited this page Jul 16, 2017 · 10 revisions

A closure is mapped by using a custom transformer implementing the JMTransformerProtocol. Let's look at a dictionary for a business object, and see how we can map a function/closure.

Response Dictionary

{
    "business_uuid"         : 9223123456754775807,
    "business_name"         : "NYC Restaurant",
    "business_facebook_id"  : "123456789323123",
    "business_yelp_id"      : "409283409238409"
}

Let's create a mapper that parses out the values from the response which, based on the identifier, returns the closure:

let facebookIDKey = "facebook_id"
let yelpIDKey     = "yelp_id"

let itunesURL     = "itms://itunes.apple.com/us/app/apple-store/id284882215?mt=8""itms://itunes.apple.com/us/app/apple-store/id284882215?mt=8"
let yelpURL       = "yelp:///biz/"
let facebookURL   = "fb://profile/"

public class SocialClosureTransformer : JMTransformerProtocol {
    
    public func transformValues(_ inputValues : Dictionary<String, Any>?) -> Any? {
        
        if let facebookdentifier = inputValues?[facebookIDKey] as? String {
            
            func routeToFacebookApp() {
                
                if UIApplication.shared.openURL(NSURL(string:"fb://")!)
                {
                    let facebookAppLink = "\(facebookURL)\(facebookdentifier)"
                    UIApplication.shared.openURL(NSURL(string: facebookAppLink)!)
                }
                else
                {
                    UIApplication.shared.openURL(NSURL(string: itunesURL)!)
                }
            }
            
            return routeToFacebookApp
        }
        
        if let yelpIdentifier = inputValues![yelpIDKey] as? String {
            
            func routeToFacebookApp() {
                
                if UIApplication.shared.openURL(NSURL(string:"yelp://")!)
                {
                    let yelpAppLink = "\(yelpURL)\(yelpIdentifier)"
                    UIApplication.shared.openURL(NSURL(string:yelpAppLink)!)
                }
                else
                {
                    UIApplication.shared.openURL(NSURL(string: itunesURL)!)
                }
            }
            
            return routeToYelpApp
        }
        
        return nil
    }
}

Mapping - Model/Mappings/Business.json | PLIST

Now that we have created a transformer, let's add a mapping definition to for the closures as an instance variable.

{
    "uuid" : { ... },
    "name" : { ... },
    "open" : { ... },
    "routeToFacebook" : {
	"transformer" : "SocialClosureTransformer",
        "key" : [
             "facebook_id"
	]
    },
    "routeToYelp" : {
	"transformer" : "SocialClosureTransformer",
	"key" : [
	     "yelp_id"
	]
    }
}

Model Output

After the creation of the mapping, perform a build (⌘-B). The changes should be reflected accordingly in the internal _Business.swift class.

import Foundation
import JSONModelKit

class _Business {
	var uuid : Double?
	var name : String?
	var routeToFacebook : (() -> Void)?
	var routeToYelp : (() -> Void)?

 	required init() {...}

 	convenience init?(_ dictionary: Dictionary<String, Any>) {...}
}

After calling the fail-able initializer - or updateWithDictionary method with a dataDictionary representation - JSONMapperKit will use the custom transformer to map the custom closure accordingly. Although this is a simple and abstract scenario, the potential for this functionality has many outcomes to be explored.

Note: The the keys defined in the property mapping correspond to the keys in the dictionary of values passed to the public func transformValues(inputValues : Dictionary<String, Any>?) -> Any? method defined by the protocol.