Search code examples
iosobjective-cswiftgithub-mantle

How to use Github Mantle's MTLValueTransformer with Swift?


Preface: I'm mostly an obj-c && swift n00b. I'm somewhat familiar with iOS and Cocoa frameworks through using RubyMotion for the past year. So if there's something wicked stupid or obvious I'm missing that would be why...

I'm having trouble using Mantle's JSONTransformer, in a New iOS Project (with CoreData). I have been trying to implement the following [obj-c code] in Swift:

+ (NSValueTransformer *)updatedAtJSONTransformer {
    return [MTLValueTransformer reversibleTransformerWithForwardBlock:^(NSString *str) {
        return [self.dateFormatter dateFromString:str];
    } reverseBlock:^(NSDate *date) {
        return [self.dateFormatter stringFromDate:date];
    }];
}

I've got the following dateFormatter function defined:

func dateFormatter() -> NSDateFormatter {
    let _dateFormatter = NSDateFormatter()
    _dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
    _dateFormatter.dateFormat = "yyyy-MM-dd'T' HH:mm:ss'Z'"
    return _dateFormatter
}

When using the implementations below I consistently receive errors similar to:

'AnyObject!' is not a subtype of 'NSString'

or

Cannot convert the expression's type 'MTLValueTransformer!' to type 'NSString?'

I've tried the following:

func createdAtJSONTransformer() -> NSValueTransformer {
    let _forwardBlock: (String) -> NSDate = { str in
        return self.dateFormatter().dateFromString(str)
    }
    let _reverseBlock: (NSDate) -> NSString = { date in
        let str: NSString = self.dateFormatter().stringFromDate(date)
        return str
    }
    let mtlTransformer = MTLValueTransformer.reversibleTransformerWithForwardBlock(_forwardBlock, reverseBlock: _reverseBlock)
    return mtlTransformer
}

and

func updatedAtJSONTransformer() -> NSValueTransformer {
    func forwardBlock(str: NSString?) -> NSDate {
        return self.dateFormatter().dateFromString(str!)
    }

    func reverseBlock(date: NSDate?) -> NSString {
       return self.dateFormatter().stringFromDate(date!)
    }

    return MTLValueTransformer.reversibleTransformerWithForwardBlock(forwardBlock, reverseBlock: reverseBlock)
}

Also a shot at using optional type arguments for the blocks as well...

func createdAtJSONTransformer() -> NSValueTransformer {
    let _forwardBlock: (String?) -> NSDate = { str in
        let date: NSDate = self.dateFormatter().dateFromString(str!)
        return date
    }
    let _reverseBlock: (NSDate?) -> NSString = { date in
        let str: NSString = self.dateFormatter().stringFromDate(date!)
        return str
    }
    let mtlTransformer = MTLValueTransformer.reversibleTransformerWithForwardBlock(forwardBlock, reverseBlock: reverseBlock)
    return mtlTransformer
}

and

func createdAtJSONTransformer() -> NSValueTransformer {
    func forwardBlock(str: NSString?) -> NSDate {
        return self.dateFormatter().dateFromString(str!)
    }

    func reverseBlock(date: NSDate?) -> NSString {
        return self.dateFormatter().stringFromDate(date!)
    }

    return MTLValueTransformer.reversibleTransformerWithForwardBlock(forwardBlock, reverseBlock: reverseBlock)
}

I can see, when I use the autocomplete in xcode it's looking for something that matches:

MTLValueTransformer.reversibleTransformerWithForwardBlock(forwardBlock: MTLValueTransformerBlock?, reverseBlock: MTLValueTransformerBlock?)

Finally, I've also tried specifying the name of the first argument, in all my examples (failures) e.g.

MTLValueTranso.reversibleTransformerWithForwardBlock(forwardBlock: _forwardBlock, reverseBlock: _reverseBlock)

Any help, or guidance is greatly appreciated-- thank you!


Solution

  • I eventually got it working with:

    func createdAtJSONTransformer() -> NSValueTransformer {
        let _forwardBlock: MTLValueTransformerBlock? = { str in
            return self.dateFormatter().dateFromString(str as String!)
        }
        let _reverseBlock: MTLValueTransformerBlock? = { date in
            return self.dateFormatter().stringFromDate(date as NSDate!)
        }
        return MTLValueTransformer.reversibleTransformerWithForwardBlock(_forwardBlock, reverseBlock: _reverseBlock)
    }
    

    Setting the type of the block using the typedef (typealias?).