我正在开发一个带有Core Data的应用程序,并且在预加载本地数据之后,它会触发从S3 url加载json数据。所以,我想展示微调器,因为由于某种原因,显示数据平均需要8秒(空白冻结的tableview),所以我需要显示一个灰色微调器(活动指示器)并在数据时正确停止它完成加载。 远程数据将在先前预设的几秒钟内开始与服务器同步(我将其设置为4小时,以便在研讨会会话期间不创建如此多的请求)并在AppDelegate的applicationDidBecomeActive中启动服务器负载。
问题是,我正在遇到微调器在加载数据时显示它的问题/在完成显示数据行时停止指示器,因此空白的tableview仍然阻止了UI。
Case1)spinner在viewDidLoad中启动,并在controllerDidChangeContent中停止(在主线程中)。结果:我没有看到微调器,似乎数据仍在加载,因此它显示空白的tableview没有微调器 - 在这种情况下,或者它太快或者看起来controllerDidChangeContent在数据加载完成之前完成。
案例2)微调器在viewWillAppear中启动并在viewWillDissapear中停止。它在右侧屏幕中的正确时间显示旋转视图,但仅在用户更改视图时停止。
案例3)然后我尝试使用标志。比如,isLoading等于true,并且假定停止微调器。
#AppDelegate
func updateSeedJsonFromServer() {
let task = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string:seedLoadURL)!, completionHandler: { (data, response, error) -> Void in
var error: NSError? = nil
let jsonArray = NSJSONSerialization.JSONObjectWithData(data!, options: nil, error: &error) as! NSArray
let entity = NSEntityDescription.entityForName("EventModel", inManagedObjectContext: self.managedObjectContext!)
for jsonDictionary in jsonArray {
let eventSectionDate = jsonDictionary["eventSectionDate"] as! String
let priority = jsonDictionary["priority"] as! NSNumber
let room = jsonDictionary["room"] as! String
let sessionDate = jsonDictionary["sessionDate"] as! String
let desc = jsonDictionary["desc"] as! String
let sessionTitle = jsonDictionary["sessionTitle"] as! String
let speaker = jsonDictionary["speaker"] as! String
let breakDate = jsonDictionary["breakDate"] as! String
let isFavorite = jsonDictionary["isFavorite"] as! Bool
let newEvent = EventModel(entity: entity!,
insertIntoManagedObjectContext: self.managedObjectContext)
newEvent.eventSectionDate = eventSectionDate
newEvent.priority = priority
newEvent.room = room
newEvent.sessionDate = sessionDate
newEvent.desc = desc
newEvent.sessionTitle = sessionTitle
newEvent.speaker = speaker
newEvent.breakDate = breakDate
newEvent.isFavorite = NSNumber(bool:isFavorite)
}
self.managedObjectContext?.save(&error)
println("Imported \(jsonArray.count) events from server...")
//Go ahead and set a lastServerCheck value
// stop spinner here?
NSUserDefaults.standardUserDefaults().setObject(NSDate(), forKey: "lastServerCheck")
NSUserDefaults.standardUserDefaults().synchronize()
})
task.resume()
}
/////
func applicationDidBecomeActive(application: UIApplication) {
//kick off background refresh from server if hasn't been too soon, when app becomes active
let tooSoonSeconds: NSTimeInterval = 60 * 240 // 4h
if endOfTimeDate.compare(NSDate()) == NSComparisonResult.OrderedDescending {
let lastServerCheck = NSUserDefaults.standardUserDefaults().valueForKey("lastServerCheck") as? NSDate ?? begginingOfTimeDate
if NSDate().timeIntervalSinceDate(lastServerCheck) > tooSoonSeconds {
let fetchserverRequest = NSFetchRequest(entityName: "EventModel")
var error: NSError? = nil
let results = managedObjectContext?.countForFetchRequest(fetchserverRequest, error: &error)
if (results != nil) {
if let results = managedObjectContext?.executeFetchRequest(fetchserverRequest, error: &error) {
for obj in results {
let e = obj as! EventModel
managedObjectContext?.deleteObject(e)
}
}
managedObjectContext?.save(&error)
}
// dispatch_async(dispatch_get_main_queue(), {
self.updateSeedJsonFromServer()
println("Firing off updateFromServer...")
// })
}else {
//Not checking with server at the moment-
println("NOT checking with the server right now at \(NSDate()); last check was \(lastServerCheck)")
}
} else {
//Kill switch ON-
println("Not checking anymore with aws server - Kill switch ON")
}
}
在ScheduleViewController中,我在prev中调用此函数。提到的地方:
func startSpinner() {
spinner.activityIndicatorViewStyle = .Gray
spinner.center = self.view.center
spinner.hidesWhenStopped = true
self.parentViewController?.view.addSubview(spinner)
spinner.startAnimating()
}
###
func stopSpinner() {
if !isLoading {
if self.spinner.isAnimating() {
dispatch_async(dispatch_get_main_queue(), {
self.spinner.stopAnimating()
println("spinner stopping...")
// self.tableView.reloadData()
println("reloading table...")
})
}
}
}
我认为,正确的位置应该在调用任务恢复行之后,但是我无法在AppDelegate的applicationDidBecomeActive中插入微调器停止函数,因为它不知道那里的UIActivityIndicatorView。我已经尝试为spinner创建一个swift类,因此它会抛出红色错误,因为它无法识别UIViews,甚至导入UIKit。
我在哪里设置微调器的开始和放大器在AppDelegate中完成同步时停止功能?感谢您对此的帮助。如果需要更多代码,请告诉我。提前谢谢。
NetworkSpinner.swift Cocoa类:
import UIKit
class NetworkSpinner: NSObject {
class func startSpinner(spinner: UIActivityIndicatorView) {
spinner.activityIndicatorViewStyle = .Gray
spinner.center = self.view.center
spinner.hidesWhenStopped = true
self.parentViewController?.view.addSubview(spinner)
spinner.startAnimating()
}
}
使用stopSpinner类方法检查NewtorkSpinner类:
class func stopSpinner(spinner: UIActivityIndicatorView) {
//use Local spinner var
if spinner.isAnimating() {
//put it on a main thread
// dispatch_async(dispatch_get_main_queue(), {
spinner.stopAnimating()
println("spinner is stopping...")
// })
}
}
我是否需要将其发送到主线程,甚至询问微调器是否正在动画?
答案 0 :(得分:0)
使用完成处理程序显示隐藏微调器:
func updateSeedJsonFromServer() {
self.startSpinner()
NSURLSession.sharedSession().dataTaskWithURL(NSURL(string:seedLoadURL)!, completionHandler: { (data, response, error) -> Void in
//on the first line
self.stopSpinner()
}).resume()