in my app I need to display several images that I fetch from Parse and everything was great until I tested it on iPad mini and iPad 2...
To give you a better idea, my Home page is a tableview with 4 cells. The first cell must display a "big" image (50-55KB), the second cell shows a table view of thumbnail images(5-8KB) - but no more than 5 collection view cells! - and the other 2 cells are used for text, buttons etc.
I'm using Parse as a backend and I started with its tools to work with images like PFImageView: this way to load an image from the server I was using these two methods:
theImageView.file = thePFObject["<PFFileEntity>"] as? PFFile
theImageView..loadInBackground()
Once the app finished to load the home page , used memory device was at 100-110Mb, really close to 125-130Mb at witch the app is closed by the system.
I replaced the lines above with:
let imageData = NSData(contentsOfURL: NSURL(string: (stringContainingTheURL))!)
dispatch_async(dispatch_get_main_queue()) {
self.recipeImageView.image = UIImage(data: imageData!) }
and the memory usage is now at 83-85Mb. Better but as I go into another view containing only an YTPlayerView (for embedding youTube video) and a collection view of 5 thumbnail images, it easily shut down.
My strategies to reduce memory impact are: thumbnails images where possible; avoid UIImage (named:) method; avoid to work with PFFiles: this way then I store PFObjects into array, I work with strings instead of files; call didReciveMemoryWarnings() where possible to release memory
I've checked that there aren't memory leaks but I don't know how to improve the behavior. Any idea?
I'll leve you my code for the first two cells in order to compare with you.
class HomeTableViewController: UITableViewController, UICollectionViewDelegate, UICollectionViewDataSource {
//MARK: -outlets
var collectionView: UICollectionView! { didSet {collectionView.reloadData() } }
// MARK: - Model
let indexPathforcell0 = NSIndexPath(forRow: 0, inSection: 0)
let indexPathforcell1 = NSIndexPath(forRow: 1, inSection: 0)
var firstCellObject: PFObject? { didSet{ tableView.reloadRowsAtIndexPaths([indexPathforcell0], withRowAnimation: .Fade) } }
var secondCellArrayOfObjects = [PFObject]() { didSet { tableView.reloadRowsAtIndexPaths([indexPathforcell1], withRowAnimation: .Fade) } }
// MARK: - life cycle
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func viewDidLoad() {
super.viewDidLoad()
//fetch
fetchFirstCellObject()
fetchSecondCellArrayOfObjects()
}
private func fetchFirstCellObject() {
//At the end...
// self.firstCellObject = something
}
private func fetchSecondCellArrayOfObjects() {
//self.secondCellArrayOfObjects = something
}
// MARK: - Table view data source
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var mainCell = UITableViewCell()
switch indexPath.row {
case 0:
let cell = tableView.dequeueReusableCellWithIdentifier("Cell1", forIndexPath: indexPath) as! CustomTableViewCell
cell.object = firstCellObject
mainCell = cell
case 1:
var cell = self.tableView.dequeueReusableCellWithIdentifier("Cell2") as! UITableViewCell
collectionView = cell.viewWithTag(1) as! UICollectionView
collectionView.delegate = self
collectionView.dataSource = self
mainCell = cell
return mainCell
}
// MARK: - UICollectionViewDataSource
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! CommentedRecipeCollectionViewCell
cell.object = secondCellArrayOfObjects[indexPath.row]
return cell
}
}
And here how I implement the UITableViewCell:
class CustomTableViewCell: UITableViewCell {
// MARK: - Model
var object: PFObject? { didSet { updateUI() } }
@IBOutlet weak var objectImageView: PFImageView!
@IBOutlet weak var objectLabel: UILabel!
private func updateUI() {
let qos = Int(QOS_CLASS_USER_INITIATED.value)
dispatch_async(dispatch_get_global_queue(qos, 0)) {
let URLToUse = // ....
if let stringToUse = theString {
let imageData = NSData(contentsOfURL: NSURL(string: (URLToUse))!)
dispatch_async(dispatch_get_main_queue()) {
self.homeImageView.image = UIImage(data: imageData!)
}
}
}
objectLabel.text = // ....
}
}