One of my favorite things to do after complete a feature is to perform code refactoring. Lets go ahead and try to reduce the amount of code we've written for parsing JSON data as much as possible. Hope you can pick up a few tricks today. Enjoy.
!codebreak
<div class='filename'>ApiService.swift</div>
!codebreak
!syntax-highlight
class ApiService: NSObject {
//...
func fetchFeedForUrlString(urlString: String, completion: ([Video]) -> ()) {
let url = NSURL(string: urlString)
NSURLSession.sharedSession().dataTaskWithURL(url!) { (data, response, error) in
if error != nil {
print(error)
return
}
do {
if let unwrappedData = data, jsonDictionaries = try NSJSONSerialization.JSONObjectWithData(unwrappedData, options: .MutableContainers) as? [[String: AnyObject]] {
dispatch_async(dispatch_get_main_queue(), {
completion(jsonDictionaries.map({return Video(dictionary: $0)}))
})
}
} catch let jsonError {
print(jsonError)
}
}.resume()
}
}
!codebreak
<div class='filename'>Models</div>
!codebreak
!syntax-highlight
class SafeJsonObject: NSObject {
override func setValue(value: AnyObject?, forKey key: String) {
let uppercasedFirstCharacter = String(key.characters.first!).uppercaseString
let range = key.startIndex...key.startIndex.advancedBy(0)
let selectorString = key.stringByReplacingCharactersInRange(range, withString: uppercasedFirstCharacter)
let selector = NSSelectorFromString("set\(selectorString):")
let responds = self.respondsToSelector(selector)
if !responds {
return
}
super.setValue(value, forKey: key)
}
}
class Video: SafeJsonObject {
var thumbnail_image_name: String?
var title: String?
var number_of_views: NSNumber?
var uploadDate: NSDate?
var duration: NSNumber?
var channel: Channel?
override func setValue(value: AnyObject?, forKey key: String) {
if key == "channel" {
//custom channel setup
self.channel = Channel()
self.channel?.setValuesForKeysWithDictionary(value as! [String: AnyObject])
} else {
super.setValue(value, forKey: key)
}
}
init(dictionary: [String: AnyObject]) {
super.init()
setValuesForKeysWithDictionary(dictionary)
}
}
class Channel: SafeJsonObject {
var name: String?
var profile_image_name: String?
}