ios - 如何将 imageData 保存到 NSManagedObject 属性

标签 ios swift core-data grand-central-dispatch

我的应用程序从 Flickr 下载图像并将其显示在 CollectionViewController 中,并将图像保留在 Core Data 中。我试图将 imageData 保存到我的 NSManagedObject 上下文中,但我可以看出我没有正确执行此操作,因为我从未到达 cellForRowAt 函数中逻辑的“else”部分。在哪里以及如何使用 imageData 属性更新我的“图像”NSManagedObject?

这是我的客户类别:

    func getImagesFromFlickr(pin: Pin, context: NSManagedObjectContext, page: Any, completionHandlerForGetImages: @escaping (_ success: Bool, _ errorString: String?) -> Void) {

    let methodParameters = [
        Constants.FlickrParameterKeys.Method: Constants.FlickrParameterValues.FlickrPhotosSearch,
        Constants.FlickrParameterKeys.APIKey: Constants.FlickrParameterValues.APIKey,
        Constants.FlickrParameterKeys.Format: Constants.FlickrParameterValues.ResponseFormat,
        Constants.FlickrParameterKeys.Extras: Constants.FlickrParameterValues.MediumURL,
        Constants.FlickrParameterKeys.NoJSONCallback: Constants.FlickrParameterValues.DisableJSONCallback,
        Constants.FlickrParameterKeys.Lat: pin.latitude as Any,
        Constants.FlickrParameterKeys.Lon: pin.longitude as Any,
        Constants.FlickrParameterKeys.PerPage: Constants.FlickrParameterValues.PerPage,
        Constants.FlickrParameterKeys.Page: page
    ]

    taskForGetImages(methodParameters: methodParameters, latitude: pin.latitude, longitude: pin.longitude) { (results, error) in

        if let error = error {
            completionHandlerForGetImages(false, "There was an error getting the images: \(error)")
        } else {

            // Create a dictionary from the data:

            /* GUARD: Are the "photos" and "photo" keys in our result? */
            if let photosDictionary = results![Constants.FlickrResponseKeys.Photos] as? [String:AnyObject], let photoArray = photosDictionary[Constants.FlickrResponseKeys.Photo] as? [[String:AnyObject]] {

                for photo in photoArray {

                    let image = Images(context: CoreDataStack.sharedInstance().context)

                    // GUARD: Does our photo have a key for 'url_m'?
                    guard let imageUrlString = photo[Constants.FlickrResponseKeys.MediumURL] as? String else {
                        completionHandlerForGetImages(false, "Unable to find key '\(Constants.FlickrResponseKeys.MediumURL)' in \(photo)")
                        return
                    }

                    // Get metadata
                    let imageURL = URL(string: imageUrlString)!
                    let title = photo["title"] as? String ?? ""

                    // Assign the metadata to images NSManagedObject
                    image.imageURL = String(describing: imageURL)
                    image.pin = pin
                    image.title = title

                    CoreDataStack.sharedInstance().context.insert(image)
                }
                CoreDataStack.sharedInstance().saveContext()
            }
            completionHandlerForGetImages(true, nil)
        }
    }
}

func withBigImage(_ urlString: String?, completionHandler handler: @escaping (_ image:UIImage) -> Void){

    DispatchQueue.global(qos: .userInitiated).async { () -> Void in

        if let url = URL(string: urlString!) {
            if let imgData = try? Data(contentsOf: url) {
                if let img = UIImage(data: imgData) {

                    performUIUpdatesOnMain {
                        let image = Images(context: CoreDataStack.sharedInstance().context)
                        image.imageData = imgData as NSData
                        CoreDataStack.sharedInstance().saveContext()
                    }

                    performUIUpdatesOnMain {
                        handler(img)
                    }
                }
            }
        }
    }
}

和我的 cellForItemAt 方法:

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath as IndexPath) as! CollectionViewCell

    cell.activityIndicator.hidesWhenStopped = true
    cell.activityIndicator.activityIndicatorViewStyle = .whiteLarge
    cell.activityIndicator.center = CGPoint(x: cell.frame.size.width/2, y: cell.frame.size.height/2)

    performUIUpdatesOnMain {
        cell.activityIndicator.startAnimating()
    }
    let image = self.fetchedResultsController.object(at: indexPath)

    if image.imageData == nil {
        print("Image data doesn't exist")

        FlickrClient.sharedInstance().withBigImage(image.imageURL, completionHandler: { (cellImage) in

            performUIUpdatesOnMain {
                cell.imageView.image = cellImage
                cell.activityIndicator.stopAnimating()
            }
        })
    } else {
        print("Image data exists")
        performUIUpdatesOnMain {
            cell.imageView.image = image.image
            cell.activityIndicator.stopAnimating()
        }
    }

    if let _ = self.selectedIndexes.index(of: indexPath) {
        cell.imageView.alpha = 0.5
    } else {
        cell.imageView.alpha = 1.0
    }
    return cell
}

*注意:performUIUpdatesOnMain 是我的 GCD DispatchQueue.main.async 方法。

我相信这可能是后台和主队列问题,但我不确定如何解决它。

最佳答案

您是否检查过您的 sqlite 数据库是否存储了图像数据?您可以使用DB Browser for SQLite如果您正在使用模拟器。 您真的需要将图像存储在 coredata 中吗?更好的方法是仅将图像路径/元数据存储在 coredata 中,并将纯图像存储在文件系统中。

无论如何。如果没有数据写入sqlite数据库,您可以尝试使用UIImageJPEGRepresentation转换图像并保存转换后的数据

let imgData = UIImageJPEGRepresentation(img!, 1)

关于ios - 如何将 imageData 保存到 NSManagedObject 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48393453/

相关文章:

ios - 从 DateFormatter 得到错误的输出

ios - 如何降低广告 RSSI 值?

xcode - 我应该将 UIIMageViews 直接放在 Controller 的 View 中吗?

ios - 如何从 HealthKit 运行锻炼中获取海拔增益、步频和运行配速?

ios - CoreData MapKit swift 3

ios - NSUserDefaults 或存储大型数组时的其他内容?

ios - WebAPI 返回时更新内容的适当方法

ios - cabasicanimation 需要重置

ios - UITableview 更新单个单元格

ios - 如果两者相同,如何匹配 NSUserDefaults 和 CoreData 属性并获取数据