使用 Task 返回 UIImage 异步



我有一个单元格的UICollectionView,每个单元格都包含一个图像。我想加载单元格的图像。

我的实例化图像的代码:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
    {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "product_collection_cell", for: indexPath) as! ProductsCollectionViewCell
        let prodInCell =  searchActive ? filtered[indexPath.row] : products[indexPath.row]
        // Set fields
        cell.ProductImageView.image = prodInCell.GetProductImage()
        cell.ProductName.text = prodInCell.Name()
        cell.ProductPrice.text = String(prodInCell.Price())
        cell.productUniqueID = prodInCell.UniqueID()
        return cell
    }

我的产品的 GetProductImage 函数:

public func GetProductImage() -> UIImage
    {
        let prodID = self.UniqueID()
        let dbRef = Storage.storage().reference().child(prodID).child("pic0.jpg")
        var prodImg = #imageLiteral(resourceName: "DefaultProductImage")
        let imgTask = dbRef.getData(maxSize: 10*1024*1024, completion: // Up to 10 MB pictures
            {
                (data, error) in
                if let data = data
                {
                    if let img = UIImage(data: data)
                    {
                        prodImg = img
                    }
                }
        })
        imgTask.observe(.progress, handler: {(snapshot) in
            print (snapshot.progress ?? "NO MORE PROGRESS")
        })
        imgTask.resume()
        return prodImg
    }

我希望从 Firebase Storage 中检索 UIImage,或者返回 DefaultProductImage (如果不存在(。当前的实现卡住了我的UI,似乎并没有真正从Firebase加载任何内容。

我该如何完成这项工作?我也希望它不会花费太多时间 - 所以也许使用几个任务来每次加载图像将是一个很好的解决方案。


编辑:

这是我现在的代码:

接受可以使用完成块异步返回 UIImage。

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "product_collection_cell", for: indexPath) as! ProductsCollectionViewCell
    let prodInCell = searchActive ? filtered[indexPath.row] : products[indexPath.row]
    // Set fields
    cell.ProductImageView.image = #imageLiteral(resourceName: "DefaultProductImage")
    prodInCell.GetProductImage() { image in
        cell.ProductImageView.image = image
    }
    cell.ProductName.text = prodInCell.Name()
    cell.ProductPrice.text = String(prodInCell.Price())
    cell.productUniqueID = prodInCell.UniqueID()
    return cell
}
public func GetProductImage(completion: ((UIImage?) -> Void)) {
    let prodID = self.UniqueID()
    let dbRef = Storage.storage().reference().child(prodID).child("pic0.jpg")
    let imgTask = dbRef.getData(maxSize: 10*1024*1024, completion: { (data, error) in
        if let data = data, let img = UIImage(data: data) {
            completion(img)
        } else {
            completion(nil)
        }
    })
    imgTask.observe(.progress, handler: {(snapshot) in
        print (snapshot.progress ?? "NO MORE PROGRESS")
    })
    imgTask.resume()
}

现在我得到了

Thread 1: EXC_BAD_ACCESS (code=1, address=0x10)

在函数中

- (void)invokeFetchCallbacksOnCallbackQueueWithData:(GTM_NULLABLE NSData *)data
                                              error:(GTM_NULLABLE NSError *)error {
  // Callbacks will be released in the method stopFetchReleasingCallbacks:
  GTMSessionFetcherCompletionHandler handler;
  @synchronized(self) {
    GTMSessionMonitorSynchronized(self);
    handler = _completionHandler;
    if (handler) {
      [self invokeOnCallbackQueueUnlessStopped:^{
        handler(data, error);
        // Post a notification, primarily to allow code to collect responses for
        // testing.
        //
        // The observing code is not likely on the fetcher's callback
        // queue, so this posts explicitly to the main queue.
        NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
        if (data) {
          userInfo[kGTMSessionFetcherCompletionDataKey] = data;
        }
        if (error) {
          userInfo[kGTMSessionFetcherCompletionErrorKey] = error;
        }
        [self postNotificationOnMainThreadWithName:kGTMSessionFetcherCompletionInvokedNotification
                                          userInfo:userInfo
                                      requireAsync:NO];
      }];
    }
  }  // @synchronized(self)

排队handler(data,error);

错误

错误 NSError * 域: @"com.google.HTTPStatus" - 代码: 404

可以使用完成块异步返回 UIImage。

例如,您可以将代码更新为以下内容:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "product_collection_cell", for: indexPath) as! ProductsCollectionViewCell
    let prodInCell = searchActive ? filtered[indexPath.row] : products[indexPath.row]
    // Set fields
    cell.ProductImageView.image = #imageLiteral(resourceName: "DefaultProductImage")
    prodInCell.GetProductImage() { image in
        cell.ProductImageView.image = image
    }
    cell.ProductName.text = prodInCell.Name()
    cell.ProductPrice.text = String(prodInCell.Price())
    cell.productUniqueID = prodInCell.UniqueID()
    return cell
}

和:

public func GetProductImage(completion: ((UIImage?) -> Void)) {
    let prodID = self.UniqueID()
    let dbRef = Storage.storage().reference().child(prodID).child("pic0.jpg")
    let imgTask = dbRef.getData(maxSize: 10*1024*1024, completion: { (data, error) in
        if let data = data, let img = UIImage(data: data) {
            completion(img)
        } else {
            completion(nil)
        }
    })
    imgTask.observe(.progress, handler: {(snapshot) in
        print (snapshot.progress ?? "NO MORE PROGRESS")
    })
    imgTask.resume()
}

最新更新