方法在巨大延迟后更新 UI

Posted

技术标签:

【中文标题】方法在巨大延迟后更新 UI【英文标题】:Method is updating the UI after huge delay 【发布时间】:2016-09-15 15:52:46 【问题描述】:

我有一个 UIView 作为父视图和一个 UIActivityIndicator 作为子视图。每当用户提交凭据时,我都会启动活动动画并在方法名称startLoadingAnimator() 中分配 parentViews alpha = 1.0,然后它会调用 API,并且当 API 完成调用时,我正在设置恢复活动通过停止它并在名为 stopLoadingAnimator() 的方法中设置父视图的 alpha = 0.0 来制作动画。 问题是stopLoadingAnimator() 正在完美地调用它的时间,但它在延迟后显示在屏幕上的效果 它应该就像当方法运行时它应该在那一刻消失但它需要很长时间才能消失。

停止活动动画。

func stopLoadingAnimator() -> Void 
    UIView.animateWithDuration(0.25, animations: 

        self.loadingView.alpha = 0
        self.activityIndicator.stopAnimating()
    )




启动活动动画。

func startLoadingAnimator() -> Void 
    UIView.animateWithDuration(0.25, animations: 

        self.loadingView.alpha = 1
        self.activityIndicator.startAnimating()

    )

API方法

    func connectToWebWith(username:String, password:String) -> Void 
        self.startLoadingAnimator()
        let params = ["email":username, "password":password]

//        params.setValue(username, forKey: "email")
//        params.setValue(password, forKey: "password")

        let request = NSMutableURLRequest(URL: NSURL(string: "https://callvabo.com/user/signin")!)
        let session = NSURLSession.sharedSession()
        request.HTTPMethod = "POST"

        do 
            request.HTTPBody = try NSJSONSerialization.dataWithJSONObject(params, options: .PrettyPrinted)
         catch 
            self.stopLoadingAnimator()

            //handle error. Probably return or mark function as throws
            print(error)
            return
        
        request.addValue("application/json", forHTTPHeaderField: "Content-Type")
        request.addValue("application/json", forHTTPHeaderField: "Accept")

        let task = session.dataTaskWithRequest(request, completionHandler: data, response, error -> Void in
            // handle error
            self.stopLoadingAnimator()
            guard error == nil else 
                return
            

            print("Response: \(response)")
            let strData = NSString(data: data!, encoding: NSUTF8StringEncoding)
            print("Body: \(strData)")

            let json: NSDictionary?
            do 
                json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableLeaves) as? NSDictionary
             catch let dataError 
                // Did the JSONObjectWithData constructor return an error? If so, log the error to the console
                print(dataError)
                let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
                print("Error could not parse JSON: '\(jsonStr)'")
                // return or throw?
                return
            


            // The JSONObjectWithData constructor didn't return an error. But, we should still
            // check and make sure that json has a value using optional binding.
            if let parseJSON = json 
                // Okay, the parsedJSON is here, let's get the value for 'success' out of it
                let success = parseJSON["success"] as? Int
                print("Succes: \(success)")
            
            else 
                // Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
                let jsonStr = NSString(data: data!, encoding: NSUTF8StringEncoding)
                print("Error could not parse JSON: \(jsonStr)")
            

        )

        task.resume()
    

【问题讨论】:

永远不要从后台线程更新 UI。 是的,在主线程上更新 UI。 我想在 API 回调完成后立即更新 UI。就像在 Objective-C 中一样,我们在完成块中更新 UI 【参考方案1】:

更新您的开始和停止动画方法,以便它们始终在主线程上执行,如下所示:

停止活动动画。

 func stopLoadingAnimator() -> Void 
   dispatch_async(dispatch_get_main_queue(), ^()
        //Add method, task you want perform on mainQueue
        //Control UIView, IBOutlet all here

        UIView.animateWithDuration(0.25, animations: 
            self.loadingView.alpha = 0
            self.activityIndicator.stopAnimating()
        )
    )
 

启动活动动画。

func startLoadingAnimator() -> Void 
  dispatch_async(dispatch_get_main_queue(), ^()
       //Add method, task you want perform on mainQueue
       //Control UIView, IBOutlet all here

        UIView.animateWithDuration(0.25, animations: 
            self.loadingView.alpha = 1
            self.activityIndicator.startAnimating()
        )
     )
  

【讨论】:

以上是关于方法在巨大延迟后更新 UI的主要内容,如果未能解决你的问题,请参考以下文章

将 DAG 转换为任务的巨大延迟

UIPresentationController 在巨大延迟后呈现

在 DispatchQueue.main.async 中完成某些处理时,更新 UI 控件会出现延迟

移动端点击事件延迟的诞生消亡史

R 更新 textInput 值的闪亮延迟

风暴,螺栓延迟和总延迟之间的巨大差异?