In a nutshell, I want to determine a user's location, get some JSON data from source (that requires the location to be known first), and then create a table based on the returned data.
I have a custom UITableView with one prototype cell in Xcode 7 using Swift. When this table view was the initial view, it loaded fine.
Now, I'm trying to 1) embed it in a container in another UIView and 2) have it update whenever its data changes. Neither works... the table in the container never appears. I've spent nearly a week on this and am going a bit nutty (it's my first iOS app).
Something things I've noticed:
- reloadData, setNeedsDisplay, and setNeedsLayout don't appear to do anything.
- cellForRowAtIndexPath isn't being called, but numberOfRowsInSection is.
- I've tried calling all of the functions listed in bullet 1 from both the parent UIView as well as from the TableViewController.
Here is what the code currently looks like: ViewController:
import UIKit
import MapKit
import CoreLocation
var currentLatLong: String = ""
class ViewController: UIViewController, CLLocationManagerDelegate {
// global var for location
let locationManager = CLLocationManager()
var currentLocation = CLLocation()
var lastLatLong: String = ""
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// get permission and user's location
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.desiredAccuracy = kCLLocationAccuracyHundredMeters
locationManager.startUpdatingLocation()
} else {
print("Location services are not enabled")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
if let location = locations.last {
currentLocation = locations.last!
currentLatLong = "\(currentLocation.coordinate.latitude)%2C\(currentLocation.coordinate.longitude)"
if lastLatLong != currentLatLong {
lastLatLong = currentLatLong
NSNotificationCenter.defaultCenter().postNotificationName("updateOverview", object: nil)
self.view.setNeedsDisplay()
self.view.setNeedsLayout()
print("Found user's location: \(location)")
}
//print("Found user's location: \(location)")
}
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError) {
print("Failed to find user's location: \(error.localizedDescription)")
}
}
UITableViewController:
import UIKit
import MapKit
import CoreLocation
class OverviewTableViewController: UITableViewController {
var LocRepositories = [LocationJSON]()
var TimesRepositories = [TimesJSON]()
var retrieved = [dataModelDefn]()
override func viewDidLoad() {
super.viewDidLoad()
NSNotificationCenter.defaultCenter().removeObserver(self, name: "updateOverview", object: nil)
NSNotificationCenter.defaultCenter().addObserver(self, selector: "checkRes", name: "updateOverview", object: nil)
// fetch location data
let backgroundQueue:dispatch_queue_t = dispatch_queue_create("com.example.workQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(backgroundQueue, {
self.getLocations()
dispatch_async(dispatch_get_main_queue(), {self.tableView.reloadData()})
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return retrieved.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// initialize data & cell
var cell = tableView.dequeueReusableCellWithIdentifier("EDOverviewCell", forIndexPath: indexPath) as! OverviewTableCell
var rowData = retrieved[indexPath.row]
/* update cell */
// border for cell
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.SingleLine
self.tableView.separatorColor = UIColor(red:(0/255.0), green:(128/255.0), blue:(128/255.0), alpha:1)
// alternating row colors
if indexPath.row % 2 == 0 {
cell.backgroundColor = UIColor(red:(249/255.0), green:(238/255.0), blue:(188/255.0), alpha:0.5)
}
else{
cell.backgroundColor = UIColor(red:(252/255.0), green:(244/255.0), blue:(220/255.0), alpha:0.5)
}
return cell
}
func checkRes()
{
// fetch new data because location available
getLocations()
//self.tableView.reloadData()
//dispatch_async(dispatch_get_main_queue(),{ self.tableView.reloadData() })
}
func getLocations(){
// fetch demographic/location info
// abort call if no location
if currentLatLong == "" {
return
}
/* get JSON data */
}
}
Here are just some of the related questions I've attempted to mimic the solution to: Loading data after one second in uitableview. Any alternate way to eliminate this delay
How to stop UITableView from loading until data has been fetched?
It's a lengthy post, but if I've missed any necessary details please let me know. I appreciate any help.