3

I have 200 items in the array and I am passing to the collection view While Running on the device it gets Crashed due to memory warning. Is there any way to limit cell to a row at index path according to scrolling.Due to downloading images it showing memory warning. if I skip the downloading part then it's not crashing.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    var cell:ProductListCell? = collectionView.dequeueReusableCell(withReuseIdentifier: "ProductListCell", for: indexPath) as? ProductListCell

    if (cell == nil) {
        let nib: NSArray = Bundle.main.loadNibNamed("ProductListCell", owner: self, options: nil)! as NSArray
        cell = (nib.object(at: 0) as? ProductListCell)!
        cell?.layer.shouldRasterize = true
        cell?.layer.rasterizationScale = UIScreen.main.scale;
    }

        if let url = NSURL(string: ((self.objCategorywiseResponse.SimilirProductsList![indexPath.row].productPic)!)) {
            cell?.imgProduct.sd_setImage(with: url as URL, placeholderImage: UIImage(named: "placeholder.png"))
        }

    if let strProductName = self.objCategorywiseResponse.SimilirProductsList![indexPath.row].ProductName {
        cell?.lblProductName.text = strProductName
    }

    cell?.lblProductDesc .text = ""

    if let strProductPrice = self.objCategorywiseResponse.SimilirProductsList![indexPath.row].MRP {
        cell?.lblProductPrice.attributedText = Common().setPrice(Price:strProductPrice, StrikePrice1:(self.objCategorywiseResponse.SimilirProductsList![indexPath.row].discountprice)!)
    }

    if let strDiscount = self.objCategorywiseResponse.SimilirProductsList![indexPath.row].DiscountPercentage {
        if strDiscount > 0 {
            cell?.btnDiscount.setTitle("\(strDiscount)% off", for: .normal)
        } else {
            cell?.btnDiscount.isHidden = true
        }
    }

    if let strRatingDesc = self.objCategorywiseResponse.SimilirProductsList![indexPath.row].TotalRating_Reviews {
        cell?.lblRatingdesc.text = strRatingDesc
    }

    if let strRating = self.objCategorywiseResponse.SimilirProductsList![indexPath.row].AvgRatingCount {
        cell?.lblRating.text = "\(strRating)"
    }

    if let intRating = self.objCategorywiseResponse.SimilirProductsList![indexPath.row].AvgRatingCount {
        cell?.subViewRating.rating = intRating
    }

    if let strShopName = self.objCategorywiseResponse.SimilirProductsList![indexPath.row].ShopName {
        cell?.lblShopName.text = strShopName
    }

    if let strDisctance = self.objCategorywiseResponse.SimilirProductsList![indexPath.row].Distance {
        cell?.lblDistance.setTitle("\(strDisctance) km near by you", for: .normal)
    }

    if let strLandLineNo = self.objCategorywiseResponse.SimilirProductsList![indexPath.row].LandLineNumber {
        cell?.lblMobileNo.text = "\(strLandLineNo)"
    }

    cell?.btnAddToCompare.tag = indexPath.row
    cell?.btnAddToCompare.addTarget(self, action: #selector(btnClickedAddToCompare(_:)), for: .touchUpInside)

    cell?.btnAddProduct.tag = indexPath.row
    cell?.btnAddProduct.addTarget(self, action: #selector(btnClickedAddProduct(_:)), for: .touchUpInside)

    cell?.btnCall.tag = indexPath.row
     cell?.btnCall.addTarget(self, action: #selector(self.callCellactn(_:)), for: .touchUpInside)

    cell?.btnMap.tag = indexPath.row
     cell?.btnMap.addTarget(self, action: #selector(self.locationCellactn(_:)), for: .touchUpInside)

    return cell!
}
Abhiram
  • 247
  • 2
  • 14

4 Answers4

2

I don't think the number of cells is the issue. UICollectionView manages the collection of cells automatically, including disposing of off-screen cells.

I think it's more likely that you are experiencing memory leaks that prevent the cells from being actually deallocated when UICollectionView lets go of them. You have a lot of blocks in there that may be causing such memory leaks.

Clafou
  • 15,250
  • 7
  • 58
  • 89
  • if I remove setting image for url then it is not crashing if let url = NSURL(string: ((self.objCategorywiseResponse.SimilirProductsList![indexPath.row].productPic)!)) { cell?.imgProduct.sd_setImage(with: url as URL, placeholderImage: UIImage(named: "placeholder.png")) } – Abhiram Jan 19 '18 at 11:44
  • 1
    @Abhiram before that line, add cell?.imgProduct.sd_cancelCurrentImageLoad() and try – HMHero Jan 30 '18 at 08:30
1

You can use pagination concept to stop loading all the cell at a time. And it revoke the high memory usage of reusable cell.

check this link will elaborate to use of Pagination concept.

Jaydeep Vora
  • 6,085
  • 1
  • 22
  • 40
  • is there any way for calling cell for item at index after scrolling – Abhiram Jan 19 '18 at 11:52
  • reusing cells is implemented exactly for that purposes.. no more cells than are needed to be displayed are in fact instantiated - how would pagination help? – Milan Nosáľ Jan 19 '18 at 12:15
0

You are not properly reusing the cell that is the reason for memory warning Remove this `

if (cell == nil) {
    let nib: NSArray = Bundle.main.loadNibNamed("ProductListCell", owner: self, options: nil)! as NSArray
    cell = (nib.object(at: 0) as? ProductListCell)!
}

` Use the below code in viewDidLoad

 self.collectionView.register(UINib.init(nibName: "ProductListCell", bundle: nil), forCellWithReuseIdentifier: "ProductListCell")

If the issue is still occuring use the below library for image caching Kingfisher

it is a lightweight library with less memory impact

Akhil
  • 170
  • 1
  • 13
  • func setView() { self.clvProducts.register(UINib(nibName: "ProductListCell", bundle: nil), forCellWithReuseIdentifier: "ProductListCell") self.clvProducts.register(UINib(nibName: "ProductGridCell", bundle: nil), forCellWithReuseIdentifier: "ProductGridCell") } – Abhiram Jan 19 '18 at 12:16
  • I did that thing – Abhiram Jan 19 '18 at 12:16
  • I would suggest you to use kingfisher library for image download – Akhil Jan 19 '18 at 12:21
  • but the best way is after scrolling collection view only we can get data – Abhiram Jan 19 '18 at 12:24
  • If you use kingfisher it will take care of the rest.It will update the image automatically Without causing any memory issues.Even if you scroll fast it wont download the image multiple times – Akhil Jan 19 '18 at 12:27
  • by using kingfisher then also same thing – Abhiram Jan 19 '18 at 12:49
  • yah bro, iam following same procedure – Abhiram Jan 19 '18 at 12:58
  • Not related to the issue .But by looking at your code i could see a lot of dangerous coding eg self.objCategorywiseResponse.SimilirProductsList![indexPath.row] why it this code is repeated and you are force unwrapping the array. In the first line assign this object to a variable and and use that variable in the rest of your code – Akhil Jan 19 '18 at 13:04
0

I have placed Collection View in ScrollView Thats why it is calling All 100 cells at a time. then i removed Scroll view then it is working Fine

Abhiram
  • 247
  • 2
  • 14