Ios Swift代码执行命令。For循环在方法内部来回跳跃
我有以下代码来下载一些图像,将它们复制到[UIImage]数组中,然后我应该从中创建视图:Ios Swift代码执行命令。For循环在方法内部来回跳跃,ios,arrays,swift,for-loop,methods,Ios,Arrays,Swift,For Loop,Methods,我有以下代码来下载一些图像,将它们复制到[UIImage]数组中,然后我应该从中创建视图: class ViewControllerGallery: UIViewController { @IBOutlet weak var m_loader:UIActivityIndicatorView? var m_num_images:Int = 0 var m_total_images:Int = 0 var m_str_json:String = ""
class ViewControllerGallery: UIViewController {
@IBOutlet weak var m_loader:UIActivityIndicatorView?
var m_num_images:Int = 0
var m_total_images:Int = 0
var m_str_json:String = ""
var m_images = [UIImage]()
var m_views = [UIImageView]()
override func viewDidLoad() {
super.viewDidLoad()
// BEGIN-CODE--4
self.m_loader?.startAnimating()
let jsonArray = jsonToArray(jsonString: m_str_json) //implementation of this function was omited for my post
if let _ = jsonArray {
m_total_images = (jsonArray?.count)!
}
for url in jsonArray! {
OpenImage(str_url: url)
}
if m_total_images != m_num_images {
print("the function finished without loading all images!")
} else {
self.m_loader?.stopAnimating()
}
}
func CreateViews()
{
print("createViews was called :) ")
}
func OpenImage(str_url:String) {
let url:URL = URL(string: str_url)!
getDataFromUrl(url: url){ data, response, error in
guard let data = data, error == nil else {return}
DispatchQueue.main.async {
let image = UIImage(data: data)
print(image!)
self.m_images.append(image!)
print(self.m_images.count)
self.m_num_images += 1
}
}
//2.3.3 Crear vistas cuando se han cargado todas las imagenes
print(self.m_total_images == self.m_num_images)
if self.m_total_images == self.m_num_images {
print("se igualan las imagenes")
self.performSelector(onMainThread: #selector(CreateViews), with: nil, waitUntilDone: false)
}
}
//Funciones auxiilares
func getDataFromUrl(url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> ()) {
URLSession.shared.dataTask(with: url) { data, response, error in
completion(data, response, error)
}.resume()
}
}
我希望代码从view Dod load运行,当它到达调用函数OpenImage的行时,它应该执行OpenImage()中包含的全部代码。如果我运行它,控制台会显示(由于print()语句),它会奇怪地前后跳跃:
false
false
false
the function finished without loading all images!
<UIImage: 0x60c0000afc00>, {1024, 725}
1
<UIImage: 0x60c0000afcc0>, {960, 720}
2
<UIImage: 0x60c0000afc60>, {640, 801}
3
false
假的
假的
该功能在未加载所有图像的情况下完成!
, {1024, 725}
1.
, {960, 720}
2.
, {640, 801}
3.
我希望它首先下载所有图像并将它们附加到m_images数组中。然后它应该执行performSelector方法并完成
由于某些原因,如您所见,它首先跳转到print语句,将加载的图像数与图像总数进行比较,它这样做了三次,然后跳出For语句并打印“函数完成而不加载所有图像”,然后再次进入For循环并实际加载图像!为什么?我怎样才能使它按正确的顺序工作
顺便说一下,我知道我应该使用camelCase,但我已经收到了使用snake_case的类。这是因为您调用了一个异步API(函数) 异步API通常是那些需要更多时间完成任务的网络函数。所以你的代码不会停在这一行。否则,您的UI将被这一行阻塞,这将提供糟糕的用户体验。不要等待“getDataFromUrl”完成它的工作,然后执行下一行代码。调用异步API可以让您立即执行下一行。当“getDataFromUrl”最终完成其任务时,下面的回调块就会执行
guard let data = data, error == nil else {return}
DispatchQueue.main.async {
let image = UIImage(data: data)
print(image!)
self.m_images.append(image!)
print(self.m_images.count)
self.m_num_images += 1
}
您正在循环中调用OpenImages,它进行异步调用。为了使循环正确地等待每个迭代返回,您可以使用中完全展开的调度组 您的代码应该如下所示:
override func viewDidLoad() {
super.viewDidLoad()
// Some code...
let myGroup = DispatchGroup()
for url in jsonArray! {
myGroup.enter()
let url:URL = URL(string: str_url)!
// You can cut your OpenImages in two
// here we keep the part that has the async call
getDataFromUrl(url: url){ data, response, error in
guard let data = data, error == nil else {return}
DispatchQueue.main.async {
let image = UIImage(data: data)
print(image!)
self.m_images.append(image!)
print(self.m_images.count)
self.m_num_images += 1
myGroup.leave()
}
}
}
myGroup.notify(queue: .main) {
// All the async call have finished
// Here you can finish what you started in OpenImages()
// and the rest of your code: "if m_total_images != m_num_images"
}
}
getDataFromUrl(
异步工作。闭包中的代码执行时间晚于2.3.3代码。将2.3.3代码也放入闭包中。是的,请使用camelCase!
override func viewDidLoad() {
super.viewDidLoad()
// Some code...
let myGroup = DispatchGroup()
for url in jsonArray! {
myGroup.enter()
let url:URL = URL(string: str_url)!
// You can cut your OpenImages in two
// here we keep the part that has the async call
getDataFromUrl(url: url){ data, response, error in
guard let data = data, error == nil else {return}
DispatchQueue.main.async {
let image = UIImage(data: data)
print(image!)
self.m_images.append(image!)
print(self.m_images.count)
self.m_num_images += 1
myGroup.leave()
}
}
}
myGroup.notify(queue: .main) {
// All the async call have finished
// Here you can finish what you started in OpenImages()
// and the rest of your code: "if m_total_images != m_num_images"
}
}