从Alamofire和SwiftyJSON填充分组表

时间:2016-06-23 19:26:11

标签: ios json swift uitableview alamofire

我一直在尝试使用Alamofire请求中的数据填充分组表。到目前为止,我已经设法用数组中的静态数据填充表格(如图所示),但经过几个小时的尝试,查找和试验,仍然没有找到如何使用JSON数据的地方。它不应该产生太大的差异,但是对于记录,这是在 Swift 3

任何帮助将不胜感激。感谢。

Here's what the layout looks like

这是我的静态代码,效果很好。

import UIKit
import Alamofire
import SwiftyJSON

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    //static Data Here:
    var array = [ ["Clients", "John Doe", "Joe Bloggs"],["Departments", "HR", "Admin", "Finance"]]
    let cellReuseIdentifier = "cell"
    @IBOutlet var tableView: UITableView!

    override func viewDidLoad() {
        tableView.delegate = self
        tableView.dataSource = self
        super.viewDidLoad()
    }
    func numberOfSections(in tableView: UITableView) -> Int {
        return array.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return array[section].count - 1
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell:AreasCustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! AreasCustomCell

         cell.areasPreview.contentMode = .scaleAspectFit
        request(.GET, "https://url.here.com", parameters: ["file": "default.png"]).response { (request, response, data, error) in
            cell.areasPreview.image = UIImage(data: data!, scale:0.5)
            }

        cell.areasCellLabel.text = array[indexPath.section][indexPath.row + 1]
        return cell
    }
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return array[section][0]
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("You tapped cell number \(indexPath.row).")
        //More things planned here later!
    }
}

这也是我正在使用的JSON的格式。

content =     {
    clients =         (
                    {
            desc = "Description here";
            group = client;
            id = "group_7jsPXXAcoK";
            name = "John Doe";
        },
                    {
            desc = "Description here";
            group = client;
            id = "group_19MrV7OLuu";
            name = "Joe Bloggs";
        }
    );
    departments =         (
                    {
            desc = "Description here";
            group = department;
            id = "group_PhAeQZGyhx";
            name = "HR";
        },
                    {
            desc = "Description here";
            group = department;
            id = "group_RMtUqvYxLy";
            name = "Admin";
        },
                    {
            desc = "Description here";
            group = department;
            id = "group_T50mxN6fnP";
            name = "Finance";
        }
    );
};
state = success;

到目前为止,我已经添加了一个新类来保存JSON数据,我认为这些数据正朝着正确的方向发展。

class Group {

    let id : String
    let name : String
    let desc : String
    let group : String

    init(dictionary : [String : AnyObject]) {
        id = dictionary["id"] as? String ?? ""
        desc = dictionary["desc"] as? String ?? ""
        name = dictionary["name"] as? String ?? ""
        group = dictionary["group"] as? String ?? ""
    }
}

最后,我的函数是首先获取应该从viewDidLoad调用的JSON数据。

func getData()
{
    let defaults = UserDefaults.standard()
    let token = defaults.string(forKey: defaultsKeys.userToken)
    let email = defaults.string(forKey: defaultsKeys.userEmail)
    request(.POST, "https://url.here.com/api/v2.php", parameters: ["type": "areas", "uEmail": email!, "token": token!])
        .responseJSON { response in
            var json = JSON(response.result.value!)
            let state = json["state"].stringValue
            if(state == "error"){
                print(json["message"].stringValue)
            } else {
                print(response.result.value)
                //Send JSON data here to Table!
            }
    }
}

4 个答案:

答案 0 :(得分:1)

好的,当您收到请求的响应时,闭包会返回3个值。 例如:

request(gibberish: DoesntMatter) {
    data, response, error in
}

您通常希望检查200结果的响应

if let httpResponse = response as? NSHTTPURLResponse {
      if httpResponse.statusCode == 200 {
            //do something with data
      }
}

此时,使用swiftyJSON时,您可以获得如下数据:

if let httpResponse = response as? NSHTTPURLResponse {
      if httpResponse.statusCode == 200 {
            let json = JSON(data: data)
      }
}

现在,检索json的最佳方法是使用闭包,因为API调用是异步完成的,我们需要知道响应何时完成。

    func performAPICall(url: NSURL, resultHandler: ((json: JSON) -> Void)) {

            let session = NSURLSession(configuration: .defaultSessionConfiguration())
            let tokenRequest = NSMutableURLRequest(URL: url)
            tokenRequest.HTTPMethod = "GET"

            let dataTask = session.dataTaskWithRequest(tokenRequest) {
                (let data, let response, let error) in
                if let httpResponse = response as? NSHTTPURLResponse {
                    if error == nil {
                          if httpResponse.statusCode == 200 {
                                let json = JSON(data: data!)
                                resultHandler(json)
                          } else {
                                print("Failed request with response: \(httpResponse.statusCode)")
                          }
                    } else {
                        print("Error during GET Request to the endpoint \(url).\nError: \(error)")
                    }
                }
            }
            dataTask.resume()
    }

然后你调用函数并用这样的数据做你喜欢的事情:

 performAPICall(url) {
              json in
          //this will have your full response
          print(json)
          //parse the json easily by doing something like
          var clientArray: [Group] = []

          let clients = json["clients"]
          for client in clients {
                var thisClient = Group()
                thisClient.id = json["id"].string
                thisClient.desc = json["desc"].string
                thisClient.name = json["name"].string
                //not quite sure how to store this one
                thisClient.group = json["group"].anyObject
                clientArray.setByAddingObject(thisClient)
          }
          //make sure to call tableView.reloadData() when you give the tableViews //it's value.
    }

您也可以通过init执行此操作,但请确保正确设置该功能。否则我只会将对象的值初始化为nil或empty。此外,您的JSON响应返回的值不是字符串。确保你搞砸它找到一个正确的存储方式。希望这有帮助!

答案 1 :(得分:1)

我经常使用它。只需将“POST”或“GET”传递给method参数,然后在body参数中输入正文,如果是GET请求,则输入nil。您可以删除Reachability部分,但我通常喜欢使用某种形式检查与API调用的网络连接,因此如果我没有连接,我立即可以诊断错误。你可以使用几种不同的git项目。现在的警报控制器只是我放在UIViewController上的一个扩展,用于更容易的警报消息。

这里唯一棘手的部分是身体。如果if遵循RESTful设计,而不是将主体作为遵循此设计的String传递

“key1 =(value1)& key2 =(value2)& key3 =(value3)& key4 =(value4)& key5 =(value5)”etc ...

你也可以通过json序列化来做到这一点我相信,这更干净,但我还没有发现它在我的任何项目中都是必要的。

   typealias APIResultHandler = ((response: Int, json: JSON) -> Void)

    func performAPICall(url: NSURL, method: String, body: String?, resultHandler: APIResultHandler) {
        if Reachability.isConnectedToNetwork() == true {
            print("Internet connection OK")
            let session = NSURLSession(configuration: .defaultSessionConfiguration())
            let tokenRequest = NSMutableURLRequest(URL: url)
            tokenRequest.HTTPMethod = method
            if body != nil && method == Constant.POST {
                tokenRequest.HTTPBody = body!.dataUsingEncoding(NSUTF8StringEncoding)
            }
            let dataTask = session.dataTaskWithRequest(tokenRequest) {
                (let data, let response, let error) in
                if let httpResponse = response as? NSHTTPURLResponse {
                    if error == nil {
                        let json = JSON(data: data!)
                        resultHandler(response: httpResponse.statusCode, json: json)
                    } else {
                        print("Error during \(method) Request to the endpoint \(url).\nError: \(error)")
                    }
                }
            }
            dataTask.resume()
        } else {
            print("Internet connection FAILED")
            presentAlertController("No Internet Connection", message: "Make sure your device is connected to the internet.")
        }
    }

答案 2 :(得分:1)

typealias APIResultHandler = ((response: Int, json: JSON) -> Void)

func performAPICall(url: NSURL, method: String, body: String?, resultHandler: APIResultHandler) {
    let session = NSURLSession(configuration: .defaultSessionConfiguration())
    let tokenRequest = NSMutableURLRequest(URL: url)
    tokenRequest.HTTPMethod = method
    if body != nil && method == Constant.POST {
        tokenRequest.HTTPBody = body!.dataUsingEncoding(NSUTF8StringEncoding)
    }
    let dataTask = session.dataTaskWithRequest(tokenRequest) {
        (let data, let response, let error) in
        if let httpResponse = response as? NSHTTPURLResponse {
            if error == nil {
                let json = JSON(data: data!)
                resultHandler(response: httpResponse.statusCode, json: json)
            } else {
                print("Error during \(method) Request to the endpoint \(url).\nError: \(error)")
            }
        }
    }
    dataTask.resume()
}

struct Client {     var id:String     var desc:String     var name:String

init() {
    id = ""
    desc = ""
    name = ""
}

}

var clientArray:[Client] = [] let body =“key1 =(value1)& key2 =(value2)& key3 =(value3)& key4 =(value4)& key5 =(value5)”etc ...... override func viewDidLoad(){   super.viewDidLoad()

   performAPICall(url, method: "POST", body: body) {
            json in
        //this will have your full response
        print(json)

        //put this as a class variable instead in the call
        var clientArray: [Client] = []

        let clients = json["clients"]
        for client in clients {
              var thisClient = Client()
              thisClient.id = json["id"].string
              thisClient.desc = json["desc"].string
              thisClient.name = json["name"].string
              clientArray.append(thisClient)
        }
        tableview.reloadData()
  }

}

func tableView(tableView:UITableView,cellForRowAtindexPath:IndexPath) - > UITableViewCell {

    if section == 0 {
      let cell:AreasCustomCell = self.tableView.dequeueReusableCell(withIdentifier: cellReuseIdentifier) as! AreasCustomCell

      cell.areasPreview.contentMode = .scaleAspectFit
      cell.areasCellLabel.text = clientArray[indexPath.row]
    }

    if section == 1 {
        //do stuff for the other cell
    }
}

答案 3 :(得分:0)

这不需要很长时间,但我现在没有时间。星期一下班后我下次还会有几分钟看代码。我的电子邮件是sethmr21@gmail.com。给我发一封电子邮件,如果你还是想不通,我会帮你的。当你第一次启动时,搞乱闭包,异步事件,API调用以及诸如此类的东西可能会令人困惑。虽然有很多好文章。我会建议你找一本像SWIFT这本不错的大小书。我相信你可以在网上找到一些书籍的免费pdf。从后到前阅读它们将为你提供一个通过略过堆栈溢出而难以获得的基础。

相关问题