我正在使用 NSNotificationCenter
在通过 http 请求接收数据时触发 tableView.reloadData()
。 99% 的时间,tableView
不会重新加载。只有在终止应用程序、删除、清理并再次运行后,它才会运行……但只是第一次。
MainVC.swift
import UIKit
class MainVC: UIViewController, UITableViewDelegate, UITableViewDataSource {
let needMetNotificationKey = "kNeedMetKey"
@IBOutlet var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().addObserver(self, selector: "needMet", name: needMetNotificationKey, object: nil)
}
func needMet() {
startConnectionAt(url)
tableView.reloadData()
println("executed")
}
func startConnectionAt(urlPath: String){
var url: NSURL = NSURL(string: urlPath)
var request: NSURLRequest = NSURLRequest(URL: url)
var connection: NSURLConnection = NSURLConnection(request: request, delegate: self, startImmediately: false)
connection.start()
}
AcceptVC.swift
这是呈现我的表单并发出 http 请求的 VC,然后返回到 MainVC。
import UIKit
class AcceptVC: UIViewController, UITextFieldDelegate {
@IBOutlet var receiveName: UITextField!
@IBOutlet var receiveEmail: UITextField!
@IBOutlet var receivePhone: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
@IBAction func signupForNeed() {
var URL: NSURL = NSURL(string: "http://www.domain.com/json.php")
var request: NSMutableURLRequest = NSMutableURLRequest(URL:URL)
request.HTTPMethod = "POST"
var needName = receiveName
var needEmail = receiveEmail
var needPhone = receivePhone
var signup: String = "id=\(passedID)&name=\(needName.text)&email=\(needEmail.text)&phone=\(needPhone.text)"
request.HTTPBody = signup.dataUsingEncoding(NSUTF8StringEncoding)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {
(response, data, error) in println(NSString(data: data, encoding: NSUTF8StringEncoding))
}
NSNotificationCenter.defaultCenter().postNotificationName(needMetNotificationKey, object: nil, userInfo: nil)
navigationController?.presentingViewController?.dismissViewControllerAnimated(true, completion: {})
}
我已将 println("executed")
添加到 needMet()
函数的末尾,以验证它确实到达了函数的末尾。可靠地,总是打印“已执行”。
当我在其他任何地方使用 startConnectionAt(url) 和 tableView.reloadData() 时,它会正常运行。为什么它在这里没有按应有的方式运行?
最佳答案
您是在请求发送后立即发布通知,而不是在请求完成后立即发布。您需要在 sendAsynchronousRequest
的完成闭包中移动 postNotificationName
调用:
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {
(response, data, error) in
println(NSString(data: data, encoding: NSUTF8StringEncoding))
NSNotificationCenter.defaultCenter().postNotificationName(needMetNotificationKey, object: nil, userInfo: nil)
}
此外,您需要确保在主队列上完成所有 UI 工作,因此在您的 needMet
函数中,您应该使用 dispatch_async
将工作分派(dispatch)到主队列:
func needMet() {
startConnectionAt(url)
dispatch_async(dispatch_get_main_queue()) {
tableView.reloadData()
println("executed")
}
}
注意:我建议阅读 Concurrency Programming了解 dispatch_async
、为什么需要使用它以及一些替代方案。
您似乎还在 viewDidLoad
中定义了 signupForNeed
。这实际上应该是类本身的一个函数,而不是嵌套函数。
关于ios - Swift 中的 NSNotificationCenter 行为不正确(只调用函数中的某些东西),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26043576/