Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios Swift代码执行命令。For循环在方法内部来回跳跃_Ios_Arrays_Swift_For Loop_Methods - Fatal编程技术网

Ios Swift代码执行命令。For循环在方法内部来回跳跃

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 = ""

我有以下代码来下载一些图像,将它们复制到[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 = ""

    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"
    }

}