简体   繁体   English

UICollectionView查询出队

[英]UICollectionView queries with dequeuing

I have an UICollectionView that makes a grid. 我有一个UICollectionView,使网格。 Each cell to make the grid has a UIImage in it (created in IB). 组成网格的每个单元都有一个UIImage(在IB中创建)。

I am using reuseable cells to keep the requests down. 我正在使用可重复使用的单元格以减少请求。 How can I use this cell and the UIImage ? 如何使用此单元格和UIImage? Is there someway of storing it in an array before it goes away ? 在它消失之前是否有某种方式将其存储在数组中? I have created a tag but I don't if this will help ? 我已经创建了标签,但是这样做是否有帮助? If i created each cell manually then there will be around 100 @IBOutlets in my controller !! 如果我手动创建每个单元,则控制器中将有大约100个@IBOutlets! Here is my code to get the cells displayed.. 这是我的代码以显示单元格。

Any ideas would be brilliant. 任何想法都会很棒。 I am trying to get the UIImage inside the cell, so I can hide it and also name it before the cell dequeues. 我试图将UIImage放入单元格中,因此我可以将其隐藏并在单元出队之前对其进行命名。

 func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("LetterCell", forIndexPath: indexPath) as UICollectionViewCell

        cell.tag = indexPath.row
        return cell
    }

Images take up a surprising amount of memory. 图像占用大量内存。 As a result, you generally do not want an architecture that requires you to hold all of images (or worse, cells) in memory at one time. 结果,您通常不希望一种架构要求您一次将所有图像(或更糟糕的是,单元格)保存在内存中。 You want your collection view cells to be reused and you want to retrieve the images from persistent storage in a just-in-time manner (aka, "lazy" image loading). 您希望您的集合视图单元格可以重用,并且您希望以一种及时的方式(也就是“惰性”图像加载)从持久性存储中检索图像。

To minimize the memory footprint of your app, so your model would generally contain the minimal amount of information, for example just references to those images (such as filenames). 为了最大程度地减少应用程序的内存占用,因此模型通常只包含最少量的信息,例如仅引用这些图像(例如文件名)。 Only load the images only when they're really needed by the UI. 仅在UI真正需要时才加载图像。

For example, let's assume that the images were files in the “Application Support” folder of the device, then you might have an array of filenames (called imageNames in my example below), and you might do something like: 例如,假设图像是设备的“应用程序支持”文件夹中的文件,那么您可能具有文件名数组(在下面的示例中称为imageNames ),并且您可能会执行以下操作:

var imageNames = [String]()   // this is populated elsewhere, perhaps `viewDidLoad`

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! CustomCell

    let imageURL = try! FileManager.default
        .url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
        .appendingPathComponent(imageNames[indexPath.item])

    cell.imageView.image = UIImage(contentsOfFile: imageURL.path)

    return cell
}

If you really wanted to hold those images in memory (for example, for even smoother response time), you might use a NSCache , but make sure this cache empties itself upon receiving memory pressure. 如果您确实想将这些图像保存在内存中(例如,为了获得更平滑的响应时间),则可以使用NSCache ,但是请确保在收到内存压力时此缓存清空。 For example: 例如:

var imageCache = ImageCache()

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! CustomCell

    let imageName = imageNames[indexPath.item]
    if let image = imageCache[imageName] {
        cell.imageView.image = image
    } else {
        let imageURL = try! FileManager.default
            .url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
            .appendingPathComponent(imageName)
        let image = UIImage(contentsOfFile: imageURL.path)
        imageCache[imageName] = image
        cell.imageView.image = image
    }

    return cell
}

Where 哪里

class ImageCache: NSCache<NSString, UIImage> {

    var observer: NSObjectProtocol?

    override init() {
        super.init()

        // empty queue upon memory pressure

        observer = NotificationCenter.default.addObserver(forName: UIApplication.didReceiveMemoryWarningNotification, object: nil, queue: .main) { [unowned self] notification in
            self.removeAllObjects()
        }
    }

    deinit {
        NotificationCenter.default.removeObserver(observer!)
    }

    subscript(key: String) -> UIImage? {
        get { return object(forKey: key as NSString) }
        set { setValue(newValue, forKey: key) }
    }
}

There are other optimizations that one might consider, too. 人们可能还会考虑其他优化。 For example, if these images are large, you might make sure that you're loading the image view with images resized to something optimal for the collection view cell. 例如,如果这些图像很大,则可能要确保您正在加载的图像视图中的图像大小已调整为最适合集合视图单元格的大小。 But hopefully this illustrates some of the basic concepts when dealing with images in a UICollectionView . 但是希望这可以说明在UICollectionView处理图像时的一些基本概念。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM