加载远程json数据后,UIActivityIndi​​catorView(spinner)不会显示或停止

时间:2015-05-31 20:42:21

标签: json swift core-data

我正在开发一个带有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中插入微调器停止函数,因为它不知道那里的UIActivityIndi​​catorView。我已经尝试为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...")
          //  })
        }
        
    }

我是否需要将其发送到主线程,甚至询问微调器是否正在动画?

1 个答案:

答案 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()