使用Task返回UIImage异步

时间:2018-03-06 14:33:58

标签: swift firebase task firebase-storage

我有一个单元格的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存储中检索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 * domain:@“com.google.HTTPStatus” - 代码:404

1 个答案:

答案 0 :(得分:1)

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

E.g。您可以将代码更新为以下内容:

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()
}