Steps
- Create UIImages in array
- Load UIImage into reusable collection view cell
- Scroll
- View memory XCode
Code that repros the issue
import UIKit
class Cell: UICollectionViewCell {
static let ReuseIdentifier = "reuseID"
var imageView: UIImageView
override init(frame: CGRect) {
imageView = UIImageView()
super.init(frame: frame)
addSubview(imageView)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
imageView.frame = bounds
super.layoutSubviews()
}
func configureWith(image: UIImage) {
imageView.image = image
layoutSubviews()
}
}
class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
var images:[UIImage] = []
var collectionView: UICollectionView
required init?(coder: NSCoder) {
let layout = UICollectionViewFlowLayout()
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
collectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: layout)
collectionView.register(Cell.self, forCellWithReuseIdentifier: Cell.ReuseIdentifier)
super.init(coder: coder)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
view.addSubview(collectionView)
collectionView.frame = view.frame
collectionView.backgroundColor = .green
collectionView.dataSource = self
collectionView.delegate = self
loadMoreImages()
collectionView.reloadData()
}
func loadMoreImages() {
for _ in 0...50 {
images.append(cloneImage(image: UIImage(named: "bigImage")!))
}
}
// MARK: - UICollectionViewDataSource
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
print(images.count)
return images.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: Cell.ReuseIdentifier, for: indexPath) as! Cell
cell.configureWith(image: images[indexPath.row])
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return view.frame.size
}
}
func cloneImage(image:UIImage) -> UIImage {
let newCgIm = image.cgImage!.copy()!
let newImage = UIImage(cgImage: newCgIm, scale: image.scale, orientation: image.imageOrientation)
return newImage
}
Video demo: https://i.stack.imgur.com/QRDWl.gif
Things that resolve the issue
- Make UIImages optional, and set UIImages to nil after they've been displayed
- Comment out
imageView.image = image - Not using
cloneImage, and insteadimages.append(UIImage(named: "bigImage")!)
Any idea what UIImageView is doing under the hood that causes unbounded memory growth? Seems like it's allocating a bunch of memory in the UIImage object that never gets released.
