Home » Swift » High memory usage in UICollectionView [duplicate]

High memory usage in UICollectionView [duplicate]

Posted by: admin November 30, 2017 Leave a comment

Questions:

This question already has an answer here:

Answers:

it’s pretty interesting, in my testing project, i commented out the prepareForReuse part in the EmojiView, and the memory usage became steady, project started at 19MB and never goes above 21MB, the (self.contentView.subviews[0] as! UILabel).text = nil is causing the issues in my test.

Questions:
Answers:

I think you don’t use storyboard to design the collection view. I searched around and found out that you need to register the class with identifier before you populate the collection view cell. Try to call the following method on viewDidLoad or something.

collectionView.registerClass(UICollectionViewCell.self , forCellWithReuseIdentifier: "emojiCell")

Questions:
Answers:

Since you have memory issues you should try lazy loading your labels.

// Define an emojiLabel property in EmojiView.h
var emojiLabel: UILabel!

// Lazy load your views in your EmojiView.m
lazy var emojiLabel: UILabel  = {
    var tempLabel: UIImageView = UILabel(frame: self.contentView.frame)
    tempLabel.textAlignment = .Center
    tempLabel.userInteractionEnabled = true
    contentView.addSubview(tempLabel)

    return tempLabel;
}()

override func prepareForReuse() {
    super.prepareForReuse()
    emojiLabel.removeFromSuperview()
    emojiLabel = nil
}

//...

class EmojiViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

    //...

    override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        //The reuse id "emojiCell" is registered in the view's init.
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier("emojiCell", forIndexPath: indexPath) as! EmojiView
        //Get recently used emojis
        if indexPath.section == 0 {
            cell.emojiLabel.text = recent.keys[recent.startIndex.advancedBy(indexPath.item)]
        //Get emoji from full, hardcoded list
        } else if indexPath.section == 1 {
            cell.emojiLabel.text = emojiList[indexPath.item]
        }
        return cell
    }

That way you’re certain that the label is released when you scroll.

Now I have one question. Why do you add a gesture recognizer to your EmojiViews ? UICollectionView already implements this functionality with its didSelectItemAtIndexPath: delegate. Allocating extra gestureRecognizers for each loaded cell is pretty heavy.

func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath){

    let cell : UICollectionViewCell = collectionView.cellForItemAtIndexPath(indexPath) as! EmojiView
    // Do stuff here
}

To sum up, I would recommand to get rid of your whole init function in EmojiViews.m, use lazy loading for the labels and didSelectItemAtIndexPath: delegate for the selection events.

NB : I’m not used to swift so my code might contain a few mistakes.