代码之家  ›  专栏  ›  技术社区  ›  Nadz

有没有办法在Swift 3 Xcode 8中首先完成异步任务?

  •  0
  • Nadz  · 技术社区  · 7 年前

    我能够检索json编码的数据,但我的问题是我无法将其传输到这里的tableview。当我运行它时,我认为问题是因为异步任务。由于它是在异步任务中,tableview(numberOfRows)的委托函数在命名时执行。计数仍然为0,因为任务将在执行委托函数后运行。这就是为什么我无法在TableView中查看数据。。。我希望有人能帮我。我在谷歌上搜索并尝试了完成处理程序(我不知道它是用来做什么的),然后我尝试将其更改为Synchronous,这会导致我出错。。非常感谢你!!!

    import UIKit
    import Foundation
    
    class TimelineViewController: UIViewController  {
        @IBOutlet weak var contentTableView: UITableView!
        var name = [String]()
        var bio = [String]()
    
        @IBOutlet weak var oPostBtn: UIButton!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            getPoems()
        }
    
        func getPoems()
        {
            let url:NSURL = NSURL(string: "http://192.168.1.6/Test/feed1.php")!
            let request:NSMutableURLRequest = NSMutableURLRequest(url:url as URL)
    
            request.httpMethod = "GET"
    
            NSURLConnection.sendAsynchronousRequest(request as URLRequest, queue: OperationQueue.main){(response, data, error) in }
    
            let task = URLSession.shared.dataTask(with: request as URLRequest) {
                    data, response, error in
    
                    if error != nil {
                        print("Error = \(error)")
                        return
                    }
                    do {
                        print("Response=\(response)")
    
                        let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
                        print("Response data = \(responseString)")
    
                        //Converting response to NSDictionary
                        var json: NSDictionary!
                        json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
    
                        //getting the JSONArray poems from the response
                        let returnPoems: NSArray = json["returnPoems"] as! NSArray
    
                        print(returnPoems);
    
    
                        //looping through all the json objects in the array teams
                        for i in 0 ..< returnPoems.count{
    
    
                            let aObject = returnPoems[i] as! [String : AnyObject]
    
    
                            self.name.append(aObject["fullName"] as! String)
                            self.bio.append(aObject["Bio"] as! String)
                            //displaying the data
    
                            print("Fullname -> ", self.name)
                            print("Bio ->", self.bio)
    
                            print("===================")
                            print("")
    
                        }
    
    
                    }
                    catch {
                        print("ERROR: \(error)")
                    }
    
            }
            task.resume()
    
        }
    
    }
    
    extension TimelineViewController: UITableViewDelegate, UITableViewDataSource {
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    
            let cell = contentTableView.dequeueReusableCell(withIdentifier: "PoemCell")
    
    
            cell?.textLabel?.text = name[indexPath.row]
            cell?.detailTextLabel?.text = bio[indexPath.row]
    
            return cell!
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    
            return name.count
        }
        func tableView(_ tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
            print("You selected cell #\(indexPath.row)!")
    
            let indexPath = tableView.indexPathForSelectedRow!
            let currentCell = tableView.cellForRow(at: indexPath)! as UITableViewCell
    
        } 
    }
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Rob Md Fahim Faez Abir    7 年前

    在您的完成区块中,当您完成构建 name bio reloadData 从主队列:

    DispatchQueue.main.async { 
        self.tableView.reloadData() 
    }
    

    我还提出了一些其他建议:

    • NSURLConnection 密码它正在执行冗余请求,而您没有对响应执行任何操作;另外,它是一个弃用的API,应该删除;

    • 你应该使用 URL NSURL ;

    • 你应该使用 URLRequest NSMutableURLRequest ;

    • String 而不是 NSString ;

    • 你应该使用Swift Array Dictionary 而不是 NSArray NSDictionary

    • 您的签名 didSelectRowAt 不正确。使用 IndexPath NSIndexPath

    • 您正在更新 名称 生物 来自 URLSession 后台队列。这不是线程安全的。您可以通过从主队列中更新这些来解决这个问题,以避免需要进行额外的同步。

    • Poem . 这使代码更加简单。它也开辟了新的可能性(例如,如果您想对 大堆您将如何更新单独的 生物

    struct Poem {
        let name: String
        let bio: String
    
        init?(dictionary: [String: Any]) {
            guard let name = dictionary["fullName"] as? String,
                let bio = dictionary["Bio"] as? String else {
                    print("Did not find fullName/Bio")
                    return nil
            }
    
            self.name = name
            self.bio = bio
        }
    }
    
    class TimelineViewController: UIViewController {
    
        @IBOutlet weak var contentTableView: UITableView!
    
        var poems = [Poem]()
    
        @IBOutlet weak var oPostBtn: UIButton!
    
        override func viewDidLoad() {
            super.viewDidLoad()
            getPoems()
        }
    
        func getPoems() {
            let url = URL(string: "http://192.168.1.6/Test/feed1.php")!
            var request = URLRequest(url: url)
    
            request.httpMethod = "GET"
    
            let task = URLSession.shared.dataTask(with: request) { data, response, error in
                guard let data = data, error == nil else {
                    print("Error = \(error?.localizedDescription ?? "Unknown error")")
                    return
                }
    
                if let response = response {
                    print("Response=\(response)")
                }
    
                if let responseString = String(data: data, encoding: .utf8) {
                    print("Response data = \(responseString)")
                }
    
                // Converting response to Dictionary
    
                guard let json = try? JSONSerialization.jsonObject(with: data),
                    let responseObject = json as? [String: Any],
                    let returnPoems = responseObject["returnPoems"] as? [[String: Any]] else {
                        print("did not find returnPoems")
                        return
                }
    
                print(returnPoems)
    
                // dispatch the update of model and UI to the main queue
    
                DispatchQueue.main.async {
                    self.poems = returnPoems.flatMap { Poem(dictionary: $0) }
                    self.contentTableView.reloadData()
                }
            }
    
            task.resume()
        }
    
    }
    
    extension TimelineViewController: UITableViewDelegate, UITableViewDataSource {
    
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = contentTableView.dequeueReusableCell(withIdentifier: "PoemCell", for: indexPath)
    
            let poem = poems[indexPath.row]
    
            cell.textLabel?.text = poem.name
            cell.detailTextLabel?.text = poem.bio
    
            return cell
        }
    
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return poems.count
        }
    
        func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
            print("You selected cell #\(indexPath.row)!")
    
            // let indexPath = tableView.indexPathForSelectedRow!                         // why do this? ... the indexPath was passed to this function
            // let currentCell = tableView.cellForRow(at: indexPath)! as UITableViewCell  // why do this? ... you don't care about the cell ... go back to you model
    
            let poem = poems[indexPath.row]
    
            // do something with poem, e.g.
    
            print(poem)
        }
    }