2017-08-26 83 views
0

我在SWIFT编程很新,我不是熟悉的Web服务。我想创建一个iOS移动应用程序的诗歌。有没有一种方法可以在Swift 3 Xcode 8中首先完成异步任务?

我能够检索JSON编码的数据,但我的问题是,我可以在这里不会转移到我的tableview。当我运行它时,我认为问题是由于异步任务。既然是在异步任务,当name.count仍然是0,因为在执行委托FUNC后的任务也只是运行的tableview(numberOfRows)的委托功能被执行。这就是为什么我无法在我的TableView中看到我的数据......我希望有人能帮助我。我GOOGLE了,并尝试完成处理程序(我不知道它用于什么),我试图将其更改为同步,这导致我出错。非常感谢!

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 

    } 
} 
+0

在你完成块,当你完成建设'name'和'bio'阵列,调用'DispatchQueue.main.async {self.tableView.reloadData( )}'刷新表。 – Rob

+0

@Rob非常感谢你Rob!不能相信我已经花了数小时的时间了。此外,我做了你所说的,你是对的!工作正常。再次感谢你! – Nadz

回答

1

在你完成块的,你就大功告成了建设namebio阵列时,通过从主队列调用reloadData刷新表:

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

有几个其他我会建议的东西:

  • 你应该删除那NSURLConnection代码。它执行多余的请求,你对响应没有做任何事情;再加上它是一个弃用的API,应该删除;

  • 您应该使用URL而不是NSURL;

  • 您应该使用URLRequest代替NSMutableURLRequest;

  • 您应该使用String而不是NSString;

  • 您应该使用Swift ArrayDictionary而不是NSArrayNSDictionary;

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

  • 您正在更新URLSession背景队列中的namebio阵列。这不是线程安全的。您可以通过从主队列中更新这些来解决此问题,以避免需要执行额外的同步。

  • 我甚至建议摆脱这两个不同的数组,并有一个自定义对象的单个数组,Poem。这使得代码更简单。它开辟了新的可能性,太(例如,如果你想将name数组排序......你怎么会相应地更新单独bio阵列;使用一个自定义的对象,这个问题就会消失)。

这样:

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) 
    } 
} 
相关问题