简体   繁体   English

使用Alamofire和Bearer令牌序列化对象

[英]Serializing Objects with Alamofire and bearer token

Using the excellent Alamofire library v1.2, in a IOS 8, Xcode 6.3 and swift project, I'm trying to serialize objects from JSON-API response and I would like to know which is the best way to accomplish it. 在IOS 8,Xcode 6.3和swift项目中,使用出色的Alamofire库v1.2,我正在尝试从JSON-API响应序列化对象,我想知道哪种是实现此目标的最佳方法。 I think the main issues in the code below are: 我认为以下代码中的主要问题是:

  • in the class controller, println(data) shows nil. 在类控制器中,println(data)显示nil。
  • in the Club Object Class, location property is not mapped correctly. 在俱乐部对象类中,位置属性未正确映射。

The JSON-API response is: 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"
  }
}]

Generic Response Collection Serialization: 通用响应集合序列化:

@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)
        })
    }
}

the Club Object Class 俱乐部对象类

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
    }
}

the View Controller Class 视图控制器类

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    }

}

the println(clubs) output is: println(clubs)输出为:

   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

Just to make sure, could you change your last lines in the ViewController class to be the following? 为了确保您能将ViewController类的最后几行更改为以下内容?

request.responseJSON { request, response, json, error in
    println(request)
    println(response)
    println(json)
    println(error)
}

I want to make sure that you have set up your request properly and are getting the response back that you expect. 我想确保您已经正确设置了请求,并且正在获得期望的响应。 That is certainly half the battle. 那肯定是成功的一半。 Once you can verify that, then we can work on the responseCollection parsing logic. 一旦您可以验证,就可以处理responseCollection解析逻辑。

Also, what version of Xcode are you using and what version of Alamofire? 另外,您正在使用什么版本的Xcode和什么版本的Alamofire?


UPDATE UPDATE

The issue you are having is two-fold. 您遇到的问题有两个方面。

Issue 1 第1期

First, you are not calling your responseCollection method correctly. 首先,您没有正确调用您的responseCollection方法。 You should instead call it as follows: 您应该改为按以下方式调用它:

request.responseCollection { request, response, clubs: [Club], error in
    println("request = \(request)")
    println("response = \(response)")
    println("clubs = \(clubs)")
    println("error = \(error)")
}

This will then call into your Club class properly. 然后,这将正确地进入您的Club班级。

Issue 2 第2期

The second issue is that you are not implementing the collection method inside your Club object. 第二个问题是您没有在Club对象内部实现collection方法。 You're never going to get any clubs without actually iterating through the collection. 如果没有真正遍历整个系列,您将永远不会得到任何俱乐部。 Something roughly like the following should get you going in the right direction. 大致类似以下内容的内容可以使您朝正确的方向前进。

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
    }
}

Once your collection function is actually iterating through all the representation values in the JSON array, you should have more luck. 一旦您的collection功能实际上遍历了JSON数组中的所有表示形式的值,您应该会更加幸运。

Bonus Points 奖励积分

For bonus points, here are a few other tips to improve your code. 对于奖励积分,这里有一些其他技巧可以改善您的代码。

  • Switch to using a failable initializer in your Club class to guarantee that objects are only created if the JSON is parsed successfully 切换到在Club类中使用失败的初始化程序,以确保仅在JSON成功解析后才创建对象
  • Change your implementation inside the responseCollection completion closure to actually store the new clubs value and display those clubs in your table view. responseCollection完成闭包中更改您的实现,以实际存储新的Club值并在表视图中显示这些Club。

The object returned to the responseCollection closure is no longer a JSON AnyObject that you can use with SwiftyJSON, but instead an array of Clubs. 返回到responseCollection闭包的对象不再是可与SwiftyJSON一起使用的JSON AnyObject,而是一个Clubs数组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM