(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 之前有延迟