嵌入在容器中的UITableView没有刷新

时间:2016-02-23 23:04:02

标签: ios xcode swift

简而言之,我想确定用户的位置,从源获取一些JSON数据(需要先知道位置),然后根据返回的数据创建一个表。

我使用Swift在Xcode 7中有一个自定义UITableView和一个原型单元。当这个表视图是初始视图时,它加载得很好。

现在,我正在尝试将其嵌入另一个UIView的容器中; 2)每当数据发生变化时都要更新。两者都不起作用......容器中的表永远不会出现。我已经花了将近一个星期的时间,而且有点疯狂(这是我的第一个iOS应用程序)。

我注意到的一些事情:

  1. reloadData,setNeedsDisplay和setNeedsLayout似乎没有做任何事情。
  2. 未调用cellForRowAtIndexPath,但numberOfRowsInSection为。
  3. 我尝试从父UIView以及TableViewController调用项目符号1中列出的所有函数。
  4. 以下是代码目前的样子: 的的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?

    UITableView doesn't populate when waiting for CLLocationManagerDelegate 's didUpdateToLocation method on iPhone SDK

    这是一篇冗长的帖子,但如果我错过了任何必要的细节,请告诉我。我感谢任何帮助。

1 个答案:

答案 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实现将取决于您正在使用的库。