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

2024-03-17

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

我发现这个问题(堆栈溢出问题 https://stackoverflow.com/questions/32163480/how-to-make-loop-wait-until-block-has-finished)这似乎解释了问题的原因是该块在不同时间完成任务,因此数组的顺序基于先完成的任务。然后他们建议使用 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++}
                }

            })

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

非常感谢你的帮助。


Update 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++}
                }

            })

Update 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])”行上返回错误“展开可选值时意外发现 nil”。这与我在尝试实现 GCD 之前遇到的错误相同......


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

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

EDIT:发布 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 循环中声明 self 弱引用。你应该向外声明。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在块内循环以错误的顺序附加到数组 - Swift 2.0 的相关文章

随机推荐