I'm using NSNotificationCenter
to trigger tableView.reloadData()
upon receiving data via an http request. 99% of the time, the tableView
does not reload. Only after terminating the app, deleting, cleaning, and again running does it operator...but only the first time.
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
This is the VC that presents my form and makes the http request, whereafter returning to the 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: {})
}
I've added the println("executed")
to the end of the needMet()
function to verify that it does make it to the end of function. Reliably, "executed" is always printed.
When I utilize startConnectionAt(url) and tableView.reloadData() anywhere else it behaves as it should. Why does it not operate as it should here?
You're posting your notification immediately after your request is sent, not once it's finished. You need to move the postNotificationName
call inside your completion closure on sendAsynchronousRequest
:
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue.mainQueue()) {
(response, data, error) in
println(NSString(data: data, encoding: NSUTF8StringEncoding))
NSNotificationCenter.defaultCenter().postNotificationName(needMetNotificationKey, object: nil, userInfo: nil)
}
Also, you need to make sure that you do all your UI work on the main queue, so in your needMet
function, you should use dispatch_async
to dispatch the work to the main queue:
func needMet() {
startConnectionAt(url)
dispatch_async(dispatch_get_main_queue()) {
tableView.reloadData()
println("executed")
}
}
Note: I'd recommend reading up on Concurrency Programming to learn about dispatch_async
, why you need use it, and some alternatives.
You also seem to have defined signupForNeed
inside viewDidLoad
. That should really be a function in the class itself and not a nested function.