简体   繁体   中英

Get Cell Image from UICollectionView in Swift 4

I created a UICollectionView and created a Custom cell.

I put the image in the custom cell and returned the cell.

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeCollectionViewCell", for: indexPath) as? HomeCollectionViewCell,
    let arts = self.artList else { return HomeCollectionViewCell() }

    if arts.count > indexPath.row
    {
        let model = arts[indexPath.row]

        cell.imgView.sd_setImage(with: URLHelper.createEncodedURL(url: model.url), completed: nil) // set cell image
    }

    return cell
}

Then, we execute a function that sets the vertical size of the cell.

func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath: IndexPath) -> CGFloat
{
    // get cell information

    return // cell Image Height
}

However, I do not know how to get cell information (cell vertical value) from this function.

What should I do?

You can do it like this:

if let cell = collectionView.cellForItem(at: indexPath) as? HomeCollectionViewCell { 
    return cell.imgView.frame.height
}
return 0

Use this to get the cell.

let cell = collectionView.cellForItem(at: indexPath)

But not sure why you need a cell here. If you want a dynamic height cell this is not needed at all, you should use autolayout

You can use guard-let here.

func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath: IndexPath) -> CGFloat {

  guard let cell = collectionView.cellForItem(at: indexPath) as? HomeCollectionViewCell else { 
   return 0
  }

  //do something with cell
  return 80//calculate height of cell
}

You can get the cell details as like below example.

func collectionView(_ collectionView: UICollectionView, heightForPhotoAtIndexPath indexPath: IndexPath) -> CGFloat
{
    // get cell information

    if let cell = collectionView.cellForItem(at: indexPath) as? HomeCollectionViewCell{

        let image = cell.imgView.image

        return min(image.size.height, 300.0) // cell Image Height
    }


    return 0// cell Image Height
}

i think you can solve the issue by making a public array of your cells then adding each cell in to the array just before you return the cell...

there you can get the created cells array and you can get any details related to the created cells by validating the cell array. Hope it will help

 var cellArray : [HomeCollectionViewCell] = [HomeCollectionViewCell]()

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeCollectionViewCell", for: indexPath) as? HomeCollectionViewCell,
let arts = self.artList else { return HomeCollectionViewCell() }

if arts.count > indexPath.row
{
    let model = arts[indexPath.row]

    cell.imgView.sd_setImage(with: URLHelper.createEncodedURL(url: model.url), completed: nil) // set cell image
}
self.cellArray.append(cell)
return cell
}

As the image inside model needs to be reused in following methods so download it in the model itself with rest of the data from API service.

func collectionView(collectionView: UICollectionView,
                    heightForImageAtIndexPath indexPath: IndexPath,
                    withWidth: CGFloat) -> CGFloat

&

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell

Code for downloading the image in the model:

if let url = URL(string: "image_url_string") {
    if let data = try? Data(contentsOf: url) {
        image = UIImage(data: data)
    }
}

In viewController 's PinterestLayoutDelegate :

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "HomeCollectionViewCell", for: indexPath) as? HomeCollectionViewCell,
        let arts = self.artList else { return HomeCollectionViewCell() }

    if arts.count > indexPath.row {
        let model = arts[indexPath.row]

        cell.imgView.image = model.image //Which is downloaded in the model itself.
    }

    return cell
}

func collectionView(collectionView: UICollectionView, heightForImageAtIndexPath indexPath: IndexPath, withWidth: CGFloat) -> CGFloat {

    // get image information
    let image = self.artList[indexPath.item].image

    return image.height(forWidth: withWidth) // cell Image Height
}

And don't forget to use this extension:

public extension UIImage {
    public func height(forWidth width: CGFloat) -> CGFloat {
        let boundingRect = CGRect( x: 0, y: 0, width: width, height: CGFloat(MAXFLOAT))
        let rect = AVMakeRect(aspectRatio: size, insideRect: boundingRect)
        return rect.size.height
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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