使用优秀的Alamofire库v1.2,在IOS 8,Xcode 6.3和swift项目中,我正在尝试从JSON-API响应中序列化对象,我想知道哪个是实现它的最佳方法。 我认为以下代码中的主要问题是:
JSON-API响应是:
hits = [{
"_id" : "5470def9e0c0be27780121d7",
"imageUrl" : "https:\/\/s3-eu-west-1.amazonaws.com\/api-static\/clubs\/5470def9e0c0be27780121d7_180.png",
"name" : "Mondo",
"hasVip" : false,
"location" : {
"city" : "Madrid"
}
}, {
"_id" : "540b2ff281b30f3504a1c72f",
"imageUrl" : "https:\/\/s3-eu-west-1.amazonaws.com\/api-static\/clubs\/540b2ff281b30f3504a1c72f_180.png",
"name" : "Teatro Kapital",
"hasVip" : false,
"location" : {
"address" : "Atocha, 125",
"city" : "Madrid"
}
}, {
"_id" : "540cd44581b30f3504a1c73b",
"imageUrl" : "https:\/\/s3-eu-west-1.amazonaws.com\/api-static\/clubs\/540cd44581b30f3504a1c73b_180.png",
"name" : "Charada",
"hasVip" : false,
"location" : {
"address" : "La Bola, 13",
"city" : "Madrid"
}
}]
通用响应收集序列化:
@objc public protocol ResponseCollectionSerializable {
static func collection(#response: NSHTTPURLResponse, representation: AnyObject) -> [Self]
}
extension Alamofire.Request {
public func responseCollection<T: ResponseCollectionSerializable>(completionHandler: (NSURLRequest, NSHTTPURLResponse?, [T]?, NSError?) -> Void) -> Self {
let serializer: Serializer = { (request, response, data) in
let JSONSerializer = Request.JSONResponseSerializer(options: .AllowFragments)
let (JSON: AnyObject?, serializationError) = JSONSerializer(request, response, data)
if response != nil && JSON != nil {
return (T.collection(response: response!, representation: JSON!), nil)
} else {
return (nil, serializationError)
}
}
return response(serializer: serializer, completionHandler: { (request, response, object, error) in
completionHandler(request, response, object as? [T], error)
})
}
}
俱乐部对象类
final class Club: ResponseCollectionSerializable {
@objc static func collection(#response: NSHTTPURLResponse, representation: AnyObject) -> [Club] {
var clubs = [Club]()
if let representation = representation as? [[String: AnyObject]] {
for representationValue in representation {
let club = Club(JSON: representationValue)
clubs.append(club)
}
}
return clubs
}
let id: String
let name: String
let imageUrl: String
let hasVip: Bool
let location: String
init(JSON: AnyObject) {
id = JSON.valueForKeyPath("id") as! String
name = JSON.valueForKeyPath("name") as! String
imageUrl = JSON.valueForKeyPath("imageUrl") as! String
hasVip = JSON.valueForKeyPath("hasVip") as! Bool
//is OK this implementation?
location = JSON.valueForKeyPath("location") as! String
}
}
视图控制器类
class ClubsViewController: UIViewController, UITableViewDataSource{
var results: [JSON]? = []
var clubs: [Club]?
@IBOutlet var tableview:UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.loadClubsObjects()
}
func loadClubsObjects(){
var URL = NSURL(string: "https://api.com/v1/clubs")
var mutableURLRequest = NSMutableURLRequest(URL: URL!)
mutableURLRequest.setValue("Content-Type", forHTTPHeaderField: "application/x-www-form-urlencoded")
mutableURLRequest.HTTPMethod = "GET"
mutableURLRequest.setValue("Bearer R01.iNsG3xjv/r1LDkhkGOANPv53xqUFDkPM0en5LIDxx875fBjdUZLn1jtUlKVJqVjsNwDe1Oqu2WuzjpaYbiWWhw==", forHTTPHeaderField: "Authorization")
let manager = Alamofire.Manager.sharedInstance
let request = manager.request(mutableURLRequest)
request.responseCollection { (request, response, clubs: [Club]?, error) in
println("request = \(request)")
println("response = \(response)")
println("clubs = \(clubs)")
println("error = \(error)")
if (json != nil){
var jsonObj = JSON(json!)
if let data = jsonObj["hits"].arrayValue as [JSON]? {
self.results = data
self.tableview.reloadData()
}
}
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.results?.count ?? 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCellWithIdentifier("clubsObjectCell") as! ClubsTableViewCell
cell.clubsObject = self.results?[indexPath.row]
return cell }
}
println(club)输出是:
request = <NSMutableURLRequest: 0x7fd553725870> { URL: https://api.com/v1/clubs }
response = Optional(<NSHTTPURLResponse: 0x7fd553439e20> { URL: https://api.com/v1/clubs } { status code: 200, headers {
"Access-Control-Allow-Headers" = "X-Requested-With, Accept, Origin, Referer, User-Agent, Content-Type, Authorization";
"Access-Control-Allow-Methods" = "GET,PUT,POST,DELETE,OPTIONS";
"Access-Control-Allow-Origin" = "*";
Connection = "keep-alive";
"Content-Encoding" = gzip;
"Content-Type" = "application/json; charset=utf-8";
Date = "Tue, 21 Apr 2015 20:18:07 GMT";
Etag = "W/\"sEDn5KBhpfpInjAtNsF4gQ==\"";
Server = "nginx/1.6.2";
"Transfer-Encoding" = Identity;
Vary = "Accept-Encoding";
"X-Powered-By" = Express;
} })
clubs = Optional([])
error = nil
答案 0 :(得分:1)
为了确保,您能否将ViewController
课程中的最后一行更改为以下内容?
request.responseJSON { request, response, json, error in
println(request)
println(response)
println(json)
println(error)
}
我想确保您已正确设置您的请求并获得您期望的回复。这肯定是成功的一半。一旦你可以验证,那么我们就可以使用responseCollection
解析逻辑。
此外,您使用的是什么版本的Xcode以及什么版本的Alamofire?
您遇到的问题有两方面。
首先,您没有正确调用responseCollection
方法。您应该按如下方式调用它:
request.responseCollection { request, response, clubs: [Club], error in
println("request = \(request)")
println("response = \(response)")
println("clubs = \(clubs)")
println("error = \(error)")
}
然后,这将正确调用您的Club
课程。
第二个问题是您没有在collection
对象中实现Club
方法。如果没有实际迭代整个系列,你永远不会得到任何俱乐部。大致如下的东西应该让你朝着正确的方向前进。
final class Club: ResponseCollectionSerializable {
@objc static func collection(#response: NSHTTPURLResponse, representation: AnyObject) -> [Club] {
var clubs = [Club]()
if let representation = representation as? [[String: AnyObject]] {
for representationValue in representation {
let club = Club(JSON: representationValue)
clubs.append(club)
}
}
return clubs
}
let id: String
let name: String
let imageUrl: String
let hasVip: Bool
init(JSON: AnyObject) {
id = JSON.valueForKeyPath("id") as! String
name = JSON.valueForKeyPath("name") as! String
imageUrl = JSON.valueForKeyPath("imageUrl") as! String
hasVip = JSON.valueForKeyPath("hasVip") as! Bool
}
}
一旦你的collection
函数实际迭代了JSON数组中的所有表示值,你应该有更多的运气。
对于奖励积分,以下是一些改进代码的其他提示。
Club
类中使用可用的初始化程序,以保证仅在成功解析JSON时才创建对象responseCollection
完成时间内的实施,以实际存储新的俱乐部价值,并在表格视图中显示这些俱乐部。返回
responseCollection
闭包的对象不再是可以与SwiftyJSON一起使用的JSON AnyObject,而是一个俱乐部数组。