有没有一种方法可以在Swift 3 Xcode 8中首先完成异步任务?
我在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
}
}
在你完成块的,你就大功告成了建设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
背景队列中的name
和bio
阵列。这不是线程安全的。您可以通过从主队列中更新这些来解决此问题,以避免需要执行额外的同步。我甚至建议摆脱这两个不同的数组,并有一个自定义对象的单个数组,
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)
}
}
在你完成块,当你完成建设'name'和'bio'阵列,调用'DispatchQueue.main.async {self.tableView.reloadData( )}'刷新表。 – Rob
@Rob非常感谢你Rob!不能相信我已经花了数小时的时间了。此外,我做了你所说的,你是对的!工作正常。再次感谢你! – Nadz