使用异步编程在 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
一段时间以来,我一直在努力解决这个问题。我想我几乎已经用尽了所有的研究选择,所以我把它拿出来给你,所以偷看。
我有一个 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