以错误顺序附加到数组的块内循环 - Swift 2.0

Loop within block appending to array in the wrong order - Swift 2.0

我有一个从 Parse 下载的 PFFiles 数组,我正在尝试将它们转换为一个 NSData (imageDataArray) 数组,以便将它们保存到 Core Data。我现在似乎遇到的唯一问题是 imageDataArray 的元素以错误的顺序添加,这意味着当我搜索 Core Data 时找到了错误的图像。

我发现了这个问题(),它似乎解释了问题的原因,因为块在不同的时间完成任务,因此数组的顺序基于完成的那个第一的。然后他们建议使用 Grand Central Dispatch,但它全部在 Obj C 中,作为编码的新手,我正在努力将它转换为 Swift 用于我的项目。

能否请您向我解释一下我将如何使用 GCD(或任何其他方法)按照与原始 PFFile 数组相同的顺序创建 imageDataArray?

    override func viewDidLoad() {
    super.viewDidLoad()


    let appDel: AppDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

    let context: NSManagedObjectContext = appDel.managedObjectContext


   let dealsQuery = PFQuery(className: ("Deals"))
    dealsQuery.orderByAscending("TrailId")

    dealsQuery.findObjectsInBackgroundWithBlock { (objects, error) -> Void in
        if let objects = objects {

            self.trailID.removeAll(keepCapacity: true)
            self.trailStep.removeAll(keepCapacity: true)
            self.dealNumber.removeAll(keepCapacity: true)
            self.imageFile.removeAll(keepCapacity: true)

            for object in objects {

                self.trailID.append(object["TrailID"] as! Int)
                self.trailStep.append(object["TrailStep"] as! Int)
                self.dealNumber.append(object["dealNumber"] as! Int)
                self.imageFile.append(object["dealImage"] as! PFFile!)

            }

        }


            var counter = 0

            for file in self.imageFile {

            let dealImage = file

            dealImage.getDataInBackgroundWithBlock({ (imageData: NSData?, error: NSError?) -> Void in

                if error == nil {

                    weak var aBlockSelf = self

                    let image = UIImage(data: imageData!)
                    aBlockSelf!.imageDataArray.append(imageData!)
                    self.imagesArray.append(image!)

                    if counter == self.trailStep.count - 1{

                        print(self.trailID.count)
                        print(self.trailStep.count)
                        print(self.dealNumber.count)
                        print(self.imageDataArray.count)

                        print(self.trailStep[0])
                        print(self.dealNumber[0])
                        let image = UIImage(data: self.imageDataArray[0])
                        self.imageView.image = image

                    } else {counter++}
                }

            })

很抱歉在这里发布了我的所有代码。我想问题出在底部,但作为初学者,我认为我可能在其他地方犯了错误,所以我认为我最好将其全部发布。

非常感谢您的帮助。


更新 1

我已经尝试添加一个预填充数组 (imageArray) 并尝试将数据放入其中,但在搜索 trailStep 和 dealNumber 时它仍然随机出现。我错过了什么?谢谢

 var i = 0

            var imageArray = [NSData!](count: self.trailStep.count, repeatedValue: nil)

            for file in self.imageFile {

            let dealImage = file

            dealImage.getDataInBackgroundWithBlock({ (imageData: NSData?, error: NSError?) -> Void in

                if error == nil {

                    //weak var aBlockSelf = self

                    let image = UIImage(data: imageData!)
                    imageArray[i] = imageData!

                    if i == self.trailStep.count - 1{

                        print(self.trailID.count)
                        print(self.trailStep.count)
                        print(self.dealNumber.count)
                        print(self.imageDataArray.count)

                        print(self.trailStep[3])
                        print(self.dealNumber[3])
                        let image = UIImage(data: imageArray[3])
                        self.imageView.image = image

                    } else {i++}
                }

            })

更新 2

我一直在研究和尝试 GCD 和串行调度,这就是我目前的位置。我认为我对 GCD 的看法过于简单,但我不太了解它的工作原理以及它如何让我的块以正确的顺序添加到 imageDataArray。

var counter = 0

        var imageArray = [NSData!](count: self.trailStep.count, repeatedValue: nil)

        weak var aBlockSelf = self

        var serialQueue = dispatch_queue_create("serial", nil)

        for file in self.imageFile {

            let dealImage = file

            var imageDataArray = [NSData!](count: self.imageFile.count, repeatedValue: nil)

            dispatch_async(serialQueue, { () -> Void in

            dealImage.getDataInBackgroundWithBlock({ (imageData: NSData?, error: NSError?) -> Void in



                    if error == nil {

                        let imageIndex = self.imageFile.indexOf(file)
                        let image = UIImage(data: imageData!)
                        imageDataArray.insert(imageData!, atIndex: imageIndex!)

                        if counter == self.trailStep.count - 1{

                            print(self.trailID.count)
                            print(self.trailStep.count)
                            print(self.dealNumber.count)
                            print(imageDataArray.count)

                            print(self.trailStep[0])
                            print(self.dealNumber[0])
                            let image = UIImage(data: imageDataArray[4])
                            self.imageView.image = image

                        } else {counter++}

                        return
                    }

                })

此代码在“let image = UIImage(data: imageDataArray[4])”行返回 "unexpectedly found nil while unwrapping an Optional value" 错误。这与我在尝试实施 GCD 之前遇到的错误相同...

您不需要为此使用 GCD;你只需要一个数组(或映射,如果你想将每个图像与其文件名相关联)来在检索每个图像时将其粘贴。换句话说,如果您有文件 "f1"、"f2"、"f3" 和 "f4",请按此顺序创建一个数组来保存检索到的图像,并将它们插入到任何索引对应于文件名列表中文件名的索引。

这应该相当简单。虽然 GCD 调度组是理想的选择,但您可以通过保留一个 for 循环计数器来解决这个问题。

在您的完成块中,使用父数组推断您当前在 for 循环中的对象的索引。在您的最终图像数组中,在此索引捕获的索引处添加对象。

编辑: Post OP 问题 - 这是我希望的快速预览:

weak var aBlockSelf = self

for file in self.imageFile {

    let dealImage = file

    dealImage.getDataInBackgroundWithBlock({ (imageData: NSData?, error: NSError?) -> Void in

        if error == nil {
            let imageIndex = self.imageFile.indexOf(file)
            let image = UIImage(data: imageData!)
            aBlockSelf.imageDataArray.insert(imageData!, atIndex: imageIndex)
            aBlockSelf.imagesArray.insert(image!, atIndex: imageIndex)

另一方面,不要在for循环中声明自弱引用。你应该在外面申报。