(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
(Xcode 6 beta / Swift) performSegueWithIdentifier has delay before segue
提问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 that
to self
to have access to self inside the dispatch_async
block.
更新:根据 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 getInfoFromAPI
replace
无论如何,如果事实证明您不在主线程上,那么您必须在!为什么?因为后台线程没有优先级,会等待很长时间才能看到结果,不像主线程,主线程对系统来说是高优先级的。这是要做什么...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.
它对我有用,希望你也是。