有效地使用来自CoreData的图像填充TableView |迅速

时间:2018-08-17 20:25:55

标签: ios arrays swift uitableview core-data

我正在尝试使用用户之前上传的图像填充UITableView。 使用CoreData将图像作为二进制数据存储在用户设备上(已启用外部存储)。

首先,应用程序从contactsArray中的CoreData获取数据。该函数在viewDidLoad中调用

    func loadContacts() {
    let request : NSFetchRequest<ProfileData> = ProfileData.fetchRequest()
    do {
    contactsArray = try context.fetch(request)
    } catch {
        print("Error fetching data from context: \(error)")
    }
}

然后填充TableView-Cells。

     cell.contactNameLabel?.text = contactsArray[indexPath.row].contactsName

    if let data = self.contactsArray[indexPath.row].photo {
        cell.contactImageView.image = UIImage(data:data)
    }
    if cell.contactImageView.image == nil {
        cell.contactImageView.image = UIImage(named: "blank_Profile.jpg")
    }

通过这种方式,TableView的滞后性超过了我以前见过的一切。 因此,我尝试将图像加载到“ cellForRowAt indexPath”函数之外。

getImages()在viewDidLoad中的loadContacts()之后立即被调用。它将二进制数据转换为UIImages并将它们放入一个数组中,然后在cellForRowAt indexPath中使用它。

    func getImages(){
    var i = 0
    while i < contactsArray.count {
        print(i)
        if let data = contactsArray[i].photo {
            imageArray.append(UIImage(data:data)!)
        }
        if contactsArray[i].photo == nil {
            imageArray.append(UIImage(named: "blank_Profile.jpg")!)
        }
        i += 1
    }
}

...

    cell.contactImageView.image = imageArray[indexPath.row]

现在问题出在另一个地方。 该应用程序现在需要15秒钟以上才能启动。 如果有人可以告诉我该如何使该应用程序快速有效地运行,我将感到非常高兴。

3 个答案:

答案 0 :(得分:0)

所以我想知道您的提取请求是什么样的,这可能是一个痛苦的问题。 我可能会建议使用NSFetchedResultsController很难比这更优化。对于NSFetchedResultsController并不难找到教程,但是this是我最后使用的教程。 同样,我可能会一起放弃getImages()。只需在配置单元的任何地方处理该逻辑。

if let contact = contactsArray[indexPath.row] {
    cell.contactNameLabel?.text = contact.contactsName
    if let imageData = contact.data, let contactImage = UIImage(data: imageData)  {
    cell.contactImageView.image = contactImage
        } else {
        cell.contactImageView.image = // #imageLiteral(resourceName: "blank_Profile.jpg")
    }
}

我可能只是通过单元的接触,然后让单元进行配置,但这很大程度上取决于设计选择。对此有很多选择和意见。

如果您决定保留getImages(),则可以尝试以下另一种方法:

func getImages() {
    for (_, contact) in contactsArray.enumerated() {
        if let data = contact.photo, let image = UIImage(data:data) {
            imageArray.append(image)
            continue
        }
        let profilePlaceholder = // #imageLiteral(resourceName: "blank_Profile.jpg")
            imageArray.append(profilePlaceholder)
    }
}

但是同样有很多不同的方法可供选择。

我希望这会有所帮助! 祝你好运,编码愉快!

答案 1 :(得分:0)

Ypu需要将图像存储在文档目录中的缓存中,并将该缓存的路径存储在核心数据中。从核心数据加载图像是一项艰巨的任务。

答案 2 :(得分:0)

cell.contactNameLabel?.text = contactsArray[indexPath.row].contactsName

if let data = self.contactsArray[indexPath.row].photo {

    DispatchQueue.global(qos: .background).async {
        // fetch the image data
        // if data fetched, the update the image
        if fetched {
            DispatchQueue.main.async {
                // update the fetched data. this way you can load more faster. and image
                // pulling happens in the background.
                // NOTE: Additionally you can cache this image in memory to load more faster when scrolling
            }
        } else {
            DispatchQueue.main.async {
                // If something went wrong while fetching image
                // show the placeholder in the here
            }
        }
    }
}