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

Posted

技术标签:

【中文标题】(Xcode 6 beta / Swift) performSegueWithIdentifier 在 segue 之前有延迟【英文标题】:(Xcode 6 beta / Swift) performSegueWithIdentifier has delay before segue 【发布时间】:2014-07-29 01:47:06 【问题描述】:

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

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

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

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

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

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

这是完整视图控制器:

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

    

还有我的 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()


        

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

let that = self

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

else

    dispatch_async(dispatch_get_main_queue()) 
        println(that)
        that.delegate?.didReceiveAPIResults(jsonResult)
    

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

【问题讨论】:

我认为 'println()' 编译问题只是 Beta 版的副作用。我有很多奇怪的副作用。仍然是一个测试版。所以...谢谢你的问题。很有趣。 【参考方案1】:

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

self.delegate?.didReceiveAPIResults(jsonResult)

如果你好奇你是否在主线程上,作为练习,你可以做 NSThread.isMainThread() 返回一个布尔值。

无论如何,如果事实证明你不在主线程上,你一定是!为什么?因为后台线程没有优先级,并且会等待很长时间才能看到结果,这与系统的高优先级主线程不同。这是做什么......在getInfoFromAPI替换

self.delegate?.didReceiveAPIResults(jsonResult)

dispatch_sync(dispatch_get_main_queue())

    self.delegate?.didReceiveAPIResults(jsonResult)

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

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

【讨论】:

你也可以使用dispatch_async,这样可以避免死锁。 你的意思是 dispatch_sync? 没有。我的意思是不要使用dispatch_sync,而是使用dispatch_async。从主线程调用dispatch_sync(dispatch_get_main_queue(), ...) 会导致死锁。 dispatch_async 没有。 是的,但我认为他的问题是因为他在后台线程上,我 99% 确定。【参考方案2】:

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

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

此人说这是 iOS 8 中的错误。

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

它对我有用,希望你也一样。

【讨论】:

以上是关于(Xcode 6 beta / Swift) performSegueWithIdentifier 在 segue 之前有延迟的主要内容,如果未能解决你的问题,请参考以下文章

将 xcode 6 beta 6 升级到 xcode 6 GM 种子后的 Swift 编译器错误

Xcode 6 Beta / Swift - Playground 未更新

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

如何在 swift 中制作动画(xcode 6 beta)

Swift 5 (Xcode 11 Betas 5 & 6) - 如何写入 JSON 文件?

swift 3(xCode8-beta6)上的可达性问题