我有一个从 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/