【问题标题】:Returning UIImage Async using Task使用任务返回 UIImage 异步
【发布时间】:2018-03-07 01:47:23
【问题描述】:

我有一个 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 * 域:@"com.google.HTTPStatus" - 代码:404

【问题讨论】:

    标签: swift firebase task firebase-storage


    【解决方案1】:

    您可以使用完成块异步返回 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()
    }
    

    【讨论】:

    • 感谢您的回答。但是,有一个错误:关闭使用非转义参数 'completion' 可能允许它转义在完成(img)行中
    • 我添加了@escaping 关键字。会让你知道发生了什么
    • 我收到异常线程 1:EXC_BAD_ACCESS (code=1, address=0x10)
    • 在函数中 - (void)invokeFetchCallbacksOnCallbackQueueWithData:(GTM_NULLABLE NSData *)data error:(GTM_NULLABLE NSError *)error {
    • 在这个处理程序中:if (handler) { [self invokeOnCallbackQueueUnlessStopped:^{ handler(data, error);
    猜你喜欢
    • 1970-01-01
    • 2013-04-16
    • 2016-10-03
    • 2015-01-12
    • 2014-10-01
    • 2016-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多