skip to Main Content

Hi I’ve HomeCollectionViewCellComponent which is using in HomeCollectionViewCell and also there is a struct that holds size calculation logics for my collectionView (HomeCollectionViewCellSizeCalculator). it is calling in sizeForItem method of UICollectionViewDelegateFlowLayout. I hide my imageView when kingfisher is failed to downloading but I also want to compute imageSize as zero. I should tell to sizeCalculator from the setData function inside the HomeCollectionViewCellComponent. I used NotificationCenter but its objc method does not called.

HomeCollectionViewCellComponent setData func

    func setData(with data: Article?) {
    guard let data = data else { return }
    
    if let imageUrl = data.urlToImage, let url = URL(string: imageUrl) {
        self.newsImageView.kf.setImage(with: url) { [weak self] result in
            guard let self = self else { return }
            switch result {
            case .success(_):
                break
            case .failure(_):
                self.newsImageView.isHidden = true
                NotificationCenter.default.post(name: .kingfisherFail, object: nil)
            }
        }
    }
}

HomeCollectionViewCellSizeCalculator

class HomeCollectionViewCellSizeCalculator {

private let width: CGFloat
private let article: Article?
private var imageDownloadingFailed: Bool = false

init(width: CGFloat, article: Article?) {
    self.width = width
    self.article = article
    
    NotificationCenter.default.addObserver(self, selector: #selector(didImageDownloadingFailed), name: .kingfisherFail, object: nil)
}

private var imageSize: CGSize {
    return imageDownloadingFailed ? .zero : CGSize(width: width, height: HomeCollectionViewCellComponentViewConstants.imageViewHeight + HomeCollectionViewCellComponentViewConstants.imageTopSpacing)
}

@objc func didImageDownloadingFailed(notification: Notification) {
    print("didImageDownloadingFailed")
    self.imageDownloadingFailed = true
}

HomeViewCollectionViewDelegate

final class HomeViewCollectionViewDelegate: NSObject, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

private var viewModel: HomeViewModel

init(viewModel: HomeViewModel) {
    self.viewModel = viewModel
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    guard let article = viewModel.getArticle(at: indexPath) else { return CGSize(width: collectionView.frame.width, height: collectionView.frame.height) }
    
    let sizeCalculator = HomeCollectionViewCellSizeCalculator(width: collectionView.frame.width, article: article)
    return CGSize(width: collectionView.frame.width, height: sizeCalculator.itemSize.height)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    return 15
}

}

2

Answers


  1. Try the following code

     NotificationCenter.default.addObserver(self, selector: #selector(self. didImageDownloadingFailed(_:)), name: .kingfisherFail, object: nil)
    
    @objc func didImageDownloadingFailed(_ notification: Notification){ }
    
    Login or Signup to reply.
  2. The problem is here:

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        guard let article = viewModel.getArticle(at: indexPath) else { return CGSize(width: collectionView.frame.width, height: collectionView.frame.height) }
        
        let sizeCalculator = HomeCollectionViewCellSizeCalculator(width: collectionView.frame.width, article: article)
    

    At this point in time, you have a sizeCalculator, and it is listening to the notification because the init(width:article:) function added itself as an observer.

    Then you use the size calculator:

        return CGSize(width: collectionView.frame.width, height: sizeCalculator.itemSize.height)
    }
    

    But now, with ^ this closing curly brace, you return from that method and don’t hold on to the size calculator, so it is dealloced, and is no longer alive to listen to any notifications.

    You need to consider what object should be listening to the notification, and responding to the failure. Or indeed, maybe not consider using Notification Center at all.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search