简体   繁体   中英

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) eg

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

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

As of Mantle 2.0 the provided answer above does not work.

The reason is that MTLValueTransformerBlock has changed to have 3 parameters, and reversibleTransformerWithForwardBlock:reverseBlock is deprecated.

Here is an example of what works in 2.0. (Note that ISO8601DateFormatter is a singleton, and my function happens to be a class function)

class func dateTransformer() -> NSValueTransformer {
    let _forwardBlock: MTLValueTransformerBlock? = { (value, success, error) in
        return ISO8601DateFormatter.sharedDateFormatter.dateFromString(value as! String!)
    }
    let _reverseBlock: MTLValueTransformerBlock? = { (value, success, error) in
        return ISO8601DateFormatter.sharedDateFormatter.stringFromDate(value as! NSDate!)
    }

    return MTLValueTransformer(usingForwardBlock:_forwardBlock, reverseBlock:_reverseBlock)
}

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?).

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