(Xcode 6 beta / Swift) performSegueWithIdentifier 在 segue 之前有延迟

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25007045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 05:17:56  来源:igfitidea点击:

(Xcode 6 beta / Swift) performSegueWithIdentifier has delay before segue

iosswiftxcodesegue

提问by CraexIt

I'm just learning Ios programming for the first time, with Swift and Xcode 6 beta.

我只是第一次学习 Ios 编程,使用 Swift 和 Xcode 6 beta。

I am making a simple test app that should call an API, and then segue programmatically to a different view to present the information that was retrieved.

我正在制作一个简单的测试应用程序,它应该调用一个 API,然后以编程方式转到不同的视图以显示检索到的信息。

The problem is the segue. In my delegate method didReceiveAPIResults, after everything has been successfully retrieved, I have:

问题是转场。在我的委托方法中didReceiveAPIResults,在成功检索到所有内容后,我有:

println("--> Perform segue")
performSegueWithIdentifier("segueWhenApiDidFinish", sender: nil)

When the app runs, the console outputs --> Perform segue, but then there is about a 5-10 second delay before the app actually segues to the next view. During this time all the UI components are frozen.

当应用程序运行时,控制台输出--> Perform segue,但在应用程序实际转到下一个视图之前大约有 5-10 秒的延迟。在此期间,所有 UI 组件都被冻结。

I'm a little stuck trying to figure out why the segue doesn't happen immediately, or how to debug this!

我有点想弄清楚为什么 segue 没有立即发生,或者如何调试它!

Heres The Full View controller:

这是全视图控制器:

import UIKit

class ViewController: UIViewController, APIControllerProtocol {

    @lazy var api: APIController = APIController(delegate: self)

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    func didReceiveAPIResults(results: NSDictionary) {

        println(results)

        println("--> Perform segue")
        performSegueWithIdentifier("segueWhenApiDidFinish", sender: nil)
    }

    @IBAction func getData(sender : AnyObject){

        println("--> Get Data from API")
        api.getInfoFromAPI()

    }
}

And my API controller:

还有我的 API 控制器:

import UIKit
import Foundation

protocol APIControllerProtocol {
    func didReceiveAPIResults(results: NSDictionary)
}

class APIController: NSObject {

    var delegate: APIControllerProtocol?

    init(delegate: APIControllerProtocol?) {
        self.delegate = delegate
    }


    func getInfoFromAPI(){

        let session = NSURLSession.sharedSession()
        let url = NSURL(string: "https://itunes.apple.com/search?term=Bob+Dylan&media=music&entity=album")

        let task = session.dataTaskWithURL(url, completionHandler: {data, response, error -> Void in
            if(error) {
                println("There was a web request error.")
                return
            }

            var err: NSError?

            var jsonResult = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.    MutableContainers, error: &err) as NSDictionary

            if(err?) {
                println("There was a JSON error.")
                return
            }

            self.delegate?.didReceiveAPIResults(jsonResult)
        })
        task.resume()


    }    
}

UPDATE: Got this working based on Ethan's answer. Below is the exact code that ended up getting the desired behavior. I needed assign thatto selfto have access to self inside the dispatch_asyncblock.

更新:根据 Ethan 的回答得到了这个工作。下面是最终获得所需行为的确切代码。我需要分配that到块self内才能访问 self dispatch_async

let that = self

if(NSThread.isMainThread()){
    self.delegate?.didReceiveAPIResults(jsonResult)

}else
{
    dispatch_async(dispatch_get_main_queue()) {
        println(that)
        that.delegate?.didReceiveAPIResults(jsonResult)
    }
}

Interestingly, this code does not work if I remove the println(that)line! (The build fails with could not find member 'didReceiveAPIResults'). This is very curious, if anyone could comment on this...

有趣的是,如果我删除该println(that)行,此代码将不起作用!(构建失败并显示could not find member 'didReceiveAPIResults')。这很好奇,如果有人可以对此发表评论......

采纳答案by Ethan

I believe you are not on the main thread when calling

我相信你在调用时不在主线程上

self.delegate?.didReceiveAPIResults(jsonResult)

If you ever are curious whether you are on the main thread or not, as an exercise, you can do NSThread.isMainThread()returns a bool.

如果您对自己是否在主线程上感到好奇,作为练习,您可以NSThread.isMainThread()返回一个布尔值。

Anyway, if it turns out that you are not on the main thread, you must be! Why? Because background threads are not prioritized and will wait a very long time before you see results, unlike the mainthread, which is high priority for the system. Here is what to do... in getInfoFromAPIreplace

无论如何,如果事实证明您不在主线程上,那么您必须在!为什么?因为后台线程没有优先级,会等待很长时间才能看到结果,不像主线程,主线程对系统来说是高优先级的。这是要做什么...getInfoFromAPI替换

self.delegate?.didReceiveAPIResults(jsonResult)

with

dispatch_sync(dispatch_get_main_queue())
{
    self.delegate?.didReceiveAPIResults(jsonResult)
}

Here you are using GCD to get the main queue and perform the UI update within the block on the main thread.

在这里,您使用 GCD 获取主队列并在主线程的块内执行 UI 更新。

But be wear, for if you are already on the main thread, calling dispatch_sync(dispatch_get_main_queue())will wait FOREVER (aka, freezing your app)... so be aware of that.

但是要穿,因为如果你已经在主线程上,调用dispatch_sync(dispatch_get_main_queue())将永远等待(也就是冻结你的应用程序).​​.....所以要注意这一点。

回答by kellz

I have a delay problem with segue from a UITableView. I have checked and I appear to be on the main thread. I checked "NSThread.isMainThread()" during prepareForSegue. It always returns true.

我有一个 UITableView 的 segue 延迟问题。我已经检查过,我似乎在主线程上。我在 prepareForSegue 期间检查了“NSThread.isMainThread()”。它总是返回真。

I found a solution on Apple Developer forums! https://forums.developer.apple.com/thread/5861

我在 Apple Developer 论坛上找到了解决方案!https://forums.developer.apple.com/thread/5861

This person says it is a bug in iOS 8.

这个人说这是iOS 8中的一个错误。

I followed their suggestion to add a line of code to didSelectRowAtIndexPath...... Despatch_async.....

我按照他们的建议在 didSelectRowAtIndexPath 中添加了一行代码...... Despatch_async .....

It worked for me, hopefully you too.

它对我有用,希望你也是。