使用异步编程在 TableView 上显示 activity 指示器 - Swift

Display activity indicator on TableView with async programming - Swift

一段时间以来,我一直在努力解决这个问题。我想我几乎已经用尽了所有的研究选择,所以我把它拿出来给你,所以偷看。

我有一个 table 视图可以转到 Web 视图。 Web 视图绘制地图,有时有数千个坐标,因此加载时间有时会有些长,这显然取决于用户的设备。所以我想插入一个 activity 指示器让用户知道应用程序没有崩溃。

所以我以编程方式创建了 activity 指标,并将其设置为在 didSelectRowAtIndexPath 上激活。这里的问题是指标在任务完成之前不会开始显示 - 那么指标的意义是什么。所以我认为这里的解决方案是异步执行此操作,但我尝试过的解决方案没有效果。我也尝试将代码插入 prepareForSegue 函数,但更糟糕的是 - 它会在加载数据之前转到地图视图,从而显示空白地图。

这里有什么帮助吗?下面是我的代码。谢谢!

class MapSelect: UITableViewController {

    let subdivisionArray = [There's an array here]

    let selectionArray = [There's an array here]

    let model = Model()
    var myView = UIView()
    var activityIndicator = UIActivityIndicatorView()


    override func viewDidLoad() {
        super.viewDidLoad()

        self.navigationController?.navigationBarHidden = false

        myView = UIView(frame: CGRectMake(0, 0, self.tableView.frame.size.width, self.tableView.frame.size.height))
        myView.backgroundColor=UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1.0)
        myView.alpha = 0.0
        UIView.animateWithDuration(1.0, animations: { () -> Void in
            self.myView.alpha = 0.5
        })
        self.view.addSubview(myView)
        activityIndicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.WhiteLarge)
        activityIndicator.startAnimating()
        activityIndicator.center = CGPointMake(self.tableView.frame.size.width / 2, self.tableView.frame.size.height / 2)
        self.tableView.addSubview(activityIndicator)
        self.stopSpinner()


    }

    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }


    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return subdivisionArray.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell!

        cell.textLabel?.font = UIFont.boldSystemFontOfSize(18)
        cell.textLabel?.text = subdivisionArray[indexPath.row]

        return cell
    }

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
    {
        if subdivisionArray[indexPath.row] != "County" {
            performSegueWithIdentifier("toMapSelect2", sender: self)
        } else {

            self.spinner()

            let seconds = 0.1
            let delay = seconds * Double(NSEC_PER_SEC)  // nanoseconds per seconds
            let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
            dispatch_after(dispatchTime, dispatch_get_main_queue(), {

                  self.performSegueWithIdentifier("toMapView", sender: self)

            })
            self.stopSpinner()

        }

    }

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { ... }

    func spinner() {
        myView.hidden = false
        myView.alpha = 0.0
        UIView.animateWithDuration(1.0, animations: { () -> Void in
            self.myView.alpha = 0.5
        })
        activityIndicator.startAnimating()
        activityIndicator.hidden = false
    }

    func stopSpinner() {
        myView.hidden = true
        activityIndicator.stopAnimating()
        activityIndicator.hidden = true
    }

}

这也是在单独的 "MapView class" 中将地图加载到 Web 视图的代码:

override func viewDidLoad() {
        super.viewDidLoad()


        do {
            if prevSelectionType == "ed" {
                prevSelectionLabel = prevSelection
                prevSelection = model.decodeElectionDistrict(prevSelection)
            } else {
                prevSelectionLabel = prevSelection
            }

        }

        var regionEds : Array<String> = Array<String>()

        do {
            var pred : NSPredicate
            pred = NSPredicate(format: "region = %@", "")
            if prevSelectionType != "county" {
                if prevSelectionType != "ed" {
                    pred = NSPredicate(format: "region = %@" , prevSelection)
                } else {
                    pred = NSPredicate(format: "ed = %@" , prevSelection)
                }
                requestPick3.predicate = pred
            }
            requestPick3.resultType = NSFetchRequestResultType.DictionaryResultType
            requestPick3.propertiesToFetch = ["ed"]
            requestPick3.returnsDistinctResults = true
            let resultsPre = try context.executeFetchRequest(requestPick3)
            for result in resultsPre {
                let resultEd : String = result["ed"] as! String
                regionEds.append(resultEd)
            }
        } catch {
            print("Error")
        }

        self.mapView.delegate = self

        var dCoords : Array<Double> = Array<Double>()
        var twdString : String = String()
        var query : PFQuery = PFQuery()
        do {
            if prevSelectionType != "county" {
                let predicate = NSPredicate(format:"twd IN %@", regionEds)
                query = PFQuery(className: "Coords2016", predicate: predicate)
            } else {
                query = PFQuery(className: "Coords2016")
            }
            query.limit = 1000
            let userArray = try query.findObjects()
            //            print(userArray)
            for item in userArray {
                dCoords = item["coords"] as! Array<Double>
                twdString = item["twd"] as! String
                twdString = model.twdToEdAbbrev(twdString)
                addBoundry(dCoords, twd: twdString)
            }

        } catch {
            print("Error")
        }

        // DEFINE CENTER LOCATION
        let initialLocation = CLLocation(latitude: centerLat, longitude: centerLong)

        // DEFINE ZOOM SIZE
        centerMapOnLocation(initialLocation)

        toggleSwitch.setOn(false, animated: true)

    }

您的代码的问题在于您启动了微调器,然后几乎立即再次停止它,而且肯定是在任何工作完成之前

您需要将所有工作放入后台队列,但更新 UI 的所有工作都需要在主队列中完成

dispatch_async(dispatch_get_main_queue(), {
    self.spinner()
})

之后

dispatch_async(dispatch_get_main_queue(), {
    self.updateMapInSomeWay()
})

如果你这样做了,你就不需要在开始前纠结0.1秒的延迟

这里有一个很好的教程,可以帮助您开始进行后台处理http://www.raywenderlich.com/92428/background-modes-ios-swift-tutorial