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

时间:2014-07-29 01:47:07

标签: ios swift xcode segue

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

我正在创建一个应该调用API的简单测试应用程序,然后以编程方式将其划分到不同的视图以显示检索到的信息。

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

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

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

我试图弄清楚为什么segue不会立即发生,或者如何调试它,我有点卡住了!

Heres The Full View控制器:

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')。这很奇怪,如果有人可以对此发表评论......

2 个答案:

答案 0 :(得分:4)

我相信你在调用

时不在主线程上
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())将等待FOREVER(也就是说,冻结你的应用程序).​​.....所以要注意这一点。 / p>

答案 1 :(得分:0)

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

我在Apple Developer论坛上找到了解决方案! JSFiddle

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

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

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