简而言之,我想确定用户的位置,从源获取一些JSON数据(需要先知道位置),然后根据返回的数据创建一个表。
我使用Swift在Xcode 7中有一个自定义UITableView和一个原型单元。当这个表视图是初始视图时,它加载得很好。
现在,我正在尝试将其嵌入另一个UIView的容器中; 2)每当数据发生变化时都要更新。两者都不起作用......容器中的表永远不会出现。我已经花了将近一个星期的时间,而且有点疯狂(这是我的第一个iOS应用程序)。
我注意到的一些事情:
以下是代码目前的样子: 的的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 */
}
}
以下是我试图模仿解决方案的一些相关问题: 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?
这是一篇冗长的帖子,但如果我错过了任何必要的细节,请告诉我。我感谢任何帮助。
答案 0 :(得分:0)
您目前拥有以下代码:
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()})
})
这将在后台线程中运行getLocations
,然后在主线程上刷新表tableView。都好。但是,getLocations
本身会执行JSON调用(目前只是注释),这无疑也会在另一个后台线程上运行。因此,在JSON完成之前,getLocations
几乎会立即返回。
您应该将完成处理程序传递给getLocations
,当JSON完成时(在其完成处理程序中),调用您自己的完成处理程序。沿着:
let backgroundQueue:dispatch_queue_t = dispatch_queue_create("com.example.workQueue", DISPATCH_QUEUE_SERIAL);
dispatch_async(backgroundQueue, {
self.getLocations(completion: {
dispatch_async(dispatch_get_main_queue(), {
self.tableView.reloadData()
})
})
})
(我可能在这里有不匹配的牙箍)。然后getLocations
定义为:
func getLocations(completion completion: (() -> Void)){
// fetch demographic/location info
// abort call if no location
if currentLatLong == "" {
return
}
getTheJsonAndInItsCompletion(... success: {
completion()
})
}
实际的JSON实现将取决于您正在使用的库。