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

标签 arrays xcode swift parse-platform grand-central-dispatch

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

我发现这个问题(Stack Overflow Question)似乎解释了问题的原因,因为 block 在不同时间完成任务,因此数组的顺序基于先完成的那个。然后他们建议使用 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 的看法过于简单,但我不太了解它的工作原理以及它如何让我的 block 以正确的顺序添加到 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 调度组是理想的选择,但您可以通过保留一个 for 循环计数器来解决这个问题。

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

编辑:发布 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 循环中声明自弱引用。你应该在外面声明它。

关于arrays - 以错误的顺序在 block 内循环附加到数组 - Swift 2.0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33429044/

相关文章:

arrays - 为什么在我的 if 语句中添加不等于空格会导致错误?

xcode - 自定义进度指示器 - 动画 subview 颜色从左到右叠加

ios - iOS keychain 技术用什么比较合适

ios - 如何在 Delegate 中检查 UITableView 中的当前 Controller

ios - 从应用程序中的所有图像创建数组?

c# - 在遍历数组后尝试从列表中获取随机元素时出现 ArgumentOutOfRangeException 错误 Unity3D C#

iphone - 到达 sender 对象的 'tag' 属性

ios - Spritekit 和 Swift 3 - 碰撞后改变球头速度

ios - swift/火力地堡 : Access and store data to array

java - 如何在java中删除String数组中的所有元素?