这是我的主viewcontroller的代码
import UIKit
class ViewController: UIViewController
{
@IBOutlet weak var progressUI: UIProgressView!
override func viewDidLoad()
{
super.viewDidLoad()
simulateDownload()
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
func simulateDownload() -> Array<Tweak>
{
var results = [Tweak]()
let searchQuery = "activator"
let url = URL(string: "https://cydia.saurik.com/api/macciti?query=" + searchQuery)
let urlData = try? Data(contentsOf: url!)
var i = 0
let jsonResult = try? JSONSerialization.jsonObject(with: urlData!, options: JSONSerialization.ReadingOptions.mutableContainers) as! [String: Any]
let resultTweaks = jsonResult?["results"] as! Array<Any>
for tweak in resultTweaks
{
i += 1
let progress = (Float(i) / Float(resultTweaks.count))
results.append(Tweak(tweakdata: tweak as! [String: String]))
DispatchQueue.main.async()
{
self.progressUI.progress = progress
}
print(progress)
}
print("done")
return results
}
}
这是我的Tweak类,在创建它的实例时会下载图标
import Foundation
import UIKit
class Tweak
{
var name, id, section, description, version, thumbURL: String
var icon: UIImage
init(tweakdata: Dictionary<String, Any>)
{
self.name = tweakdata["display"] as! String
self.id = tweakdata["name"] as! String
self.section = tweakdata["section"] as! String
self.description = tweakdata["summary"] as! String
self.version = tweakdata["version"] as! String
self.thumbURL = "https://cydia.saurik.com/icon@2x/" + self.id + ".png"
//load icon
let imgURL = URL(string: self.thumbURL)
let imgData = try? Data(contentsOf: imgURL!)
self.icon = UIImage(data: imgData!)!
}
}
我希望在制作每个Tweak实例时更新UIProgressView(progressUI)。但UI仅在函数返回后更新。有人可以解释我所有这些工作以及如何进行线程化吗? 我是swift和异步编程的新手。
答案 0 :(得分:1)
您的for循环已经在主线程上,因此它将阻止任何UI更新,这不仅会禁用进度条更新,还会禁用用户交互。
任何长时间运行的任务都应该在后台线程上运行。幸运的是,这在Swift中很容易。
由于您已经在更新进度视图,因此可以使用以下内容:
DispatchQueue.global(qos: .background).async {
simulateDownload()
}
而不是仅在simulateDownload
viewDidLoad
请注意,使用此方法,您无法直接从主线程使用函数的返回值。
你应该做的是从闭包中提供值,如下所示:
func simulateDownload(@escaping closure: (_ result:Array<Tweak>) -> ()) {
DispatchQueue.global(qos: .background).async {
[...]
DispatchQueue.main.async{
closure(results)
}
}
}
并像这样使用它:
simulateDownload(closure: {
results in
[...]
})
这只是表面上看,如果你想了解更多有关Swift中闭包的信息,我建议你阅读:https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Closures.html#//apple_ref/doc/uid/TP40014097-CH11-ID94