1

嗨,在将用户“用户名”保存在内部数据库中后,我正在使用以下功能从当前的根视图控制器交换到新的根视图控制器。虽然代码有效并且我可以进行切换,但转换需要很长时间。有时长达 15 秒。

    func switchRootViewController(rootViewController: UIViewController, animated: Bool, completion: (() -> Void)?) {
    if animated {
        UIView.transitionWithView(self.window!, duration: 0.5, options: .TransitionCrossDissolve, animations: {
            let oldState: Bool = UIView.areAnimationsEnabled()
            UIView.setAnimationsEnabled(false)
            self.window!.rootViewController = rootViewController
            UIView.setAnimationsEnabled(oldState)
            }, completion: { (finished: Bool) -> () in
                if (completion != nil) {
                    completion!()
                }
        })
    } else {
        self.window!.rootViewController = rootViewController
    }
}

这就是我调用函数的方式:

   api.postMulti(apiKey, contentType: "application/json", payLoad: payLoad, urlString: urlString, parameter: parameter){ (succeeded: Int, msg: String) -> () in

        var alert = UIAlertView(title: "Failed", message: msg, delegate: nil, cancelButtonTitle: "Okay")

        if succeeded == 422 {
            alert.title = "Failed"
            alert.message = "Username is already in use. Please selecet another one!"
        }

        else if succeeded == 500{
            alert.title = "Failed"
            alert.message = "Internal Server Error. Unable to process Request!"
        }

        else if succeeded == 200{
            //save to internal DataBase table: User
            let entityDescription = NSEntityDescription.entityForName("User", inManagedObjectContext: self.managedObjectContext!)

            let users = User(entity: entityDescription!, insertIntoManagedObjectContext: self.managedObjectContext)

            users.username = self.userName.text

            var error: NSError?

            self.managedObjectContext?.save(&error)

            if let err = error {
                println(err.localizedFailureReason)
            } else {

                self.userName.text = ""
                alert.title = "Success"
                alert.message = "Loading App..."



                let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                var secondViewController: EveryTimeRun = mainStoryboard.instantiateViewControllerWithIdentifier("everytime") as! EveryTimeRun

                self.switchRootViewController(secondViewController, animated: true, completion: nil)




                self.window?.makeKeyAndVisible()


            }
        }

        // Move to the UI thread
        dispatch_async(dispatch_get_main_queue(), { () -> Void in
            // Show the alert
            alert.show()
        })
    }

我犯了一个错误吗。

更新:

我正在发布我的 POST 功能。这可能需要很长时间:

        func postMulti(apikey: String, contentType: String, payLoad: Dictionary<String,Dictionary<String,String>>, urlString: String, parameter: String, postCompleted : (succeeded: Int, msg: String) -> ()){

    let joinedUrl = urlString + parameter
    let url = NSURL(string: joinedUrl)
    let request = NSMutableURLRequest(URL: url!)

    var session = NSURLSession.sharedSession()
    request.HTTPMethod = "POST"
    request.addValue(contentType, forHTTPHeaderField: "Content-Type")
    request.addValue(apikey, forHTTPHeaderField: "apikey")
    var error: NSError?


    let payLoadJSON = NSJSONSerialization.dataWithJSONObject(payLoad, options: nil, error: &error)
    request.HTTPBody = payLoadJSON

    var task = session.dataTaskWithRequest(request, completionHandler: {data, response, error -> Void in
        var strData = NSString(data: data, encoding: NSUTF8StringEncoding)


        var err: NSError?
        var json = NSJSONSerialization.JSONObjectWithData(data, options: .MutableLeaves, error: &err) as? NSDictionary
        // Did the JSONObjectWithData constructor return an error? If so, log the error to the console
        if(err != nil) {
            //            println(err!.localizedDescription)
            let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)

            postCompleted(succeeded: 0, msg: "Portal is not reachable. Please try again later")
        }
        else {
            // 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
                if let statusCode = parseJSON["statusCode"] as? Int {

                    postCompleted(succeeded: statusCode, msg: "")
                }
            }
            else {
                // Woa, okay the json object was nil, something went worng. Maybe the server isn't running?
                let jsonStr = NSString(data: data, encoding: NSUTF8StringEncoding)

                postCompleted(succeeded: 1, msg: "Portal is not reachable. Please try again later")
            }
        }
    })

    task.resume()
}
4

2 回答 2

0

我认为最昂贵的时间是这条线:

self.managedObjectContext?.save(&error)

所以sou应该在后台保存或者在viedDidAppear上切换后保存secondViewController

使用MagicalRecord有一些有用的方法saveWithBlock: completion:

更新:

要为视图设置动画,您可以使用以下方法:

var overlaywindow: UIWindow!
//

var storyboard = UIStoryboard(name: "Main", bundle: nil)

    if let popupVC = storyboard.instantiateViewControllerWithIdentifier("everytime") as? EveryTimeRun
    {
        var frame = UIScreen.mainScreen().bounds
        overlayWindow = UIWindow(frame: frame)

        popupVC.overlayWindow = overlayWindow
        overlayWindow.windowLevel = UIWindowLevelAlert
        overlayWindow.rootViewController = popupVC

        overlayWindow.makeKeyAndVisible()
        overlayWindow.alpha = 0

        UIView.animateWithDuration(0.3, animations:
        {
            self.overlayWindow.alpha = 1
        })
    }
于 2015-05-18T08:28:43.907 回答
0

我已经间接解决了这个问题。跟踪代码后,我意识到以下组件导致了延迟:

  1. 调用 REST API 的 POST 方法 - 网络延迟
  2. 将用户名保存到 CoreData - 写入延迟
  3. 卸载现有(ID:FirstTimeRun)视图控制器 - 卸载延迟
  4. 加载新的标签栏(ID:EveryTimeRun)视图控制器 - 加载延迟

其中 3 和 4 是最高的。

所以为了解决这个问题,我在网上做了一些研究,并认为最好的做法是加载 EveryTimeRun 视图控制器,然后如果用户尚未登录,则在此之上以模态方式加载 FirstTimeRun。然后在成功后关闭 FirstTimeRun登录。

我想这是实现我想要做的更好的方法。加载和卸载视图控制器有点像 hack。

于 2015-05-19T04:08:15.507 回答