我是第一次使用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'
)。这很奇怪,如果有人可以对此发表评论......
答案 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 .....
它对我有用,希望你也是。