【问题标题】:Swift 5 - why does my collectionview disappear when embedded in a stackview?Swift 5 - 为什么我的 collectionview 在嵌入到 stackview 时会消失?
【发布时间】:2021-11-09 06:55:09
【问题描述】:

我正在尝试制作亚马逊克隆。我正在处理产品详细信息页面。基本上你搜索,你点击你想要的项目的tableviewcell,然后你登陆详细信息页面。除了包含图像的 collectionview 之外,所有内容都会加载。当我删除堆栈视图时,一切正常,但是当我将视图的内容嵌入堆栈视图时,collectionviewcell 消失了。 cellForItemAt 方法甚至没有被调用。我不知道为什么,我真的需要一些帮助。

编辑:似乎集合单元 css 中的 imageView 展开为 nil。我不确定为什么。我将它连接到故事板中的单元格。不知道为什么它不工作。我把它变成了一个可选的 cell.imagioView?.kf.setImage(with: imageUrl) 但集合视图加载时没有里面的图像。我终于得到了水平滚动动作,但图像没有加载。当图像成为焦点时,我正在打印图像的 url,但无法将其添加到单元格中。似乎正在加载集合单元格,但由于某种原因无法添加图像。

这是应该显示它的视图控制器

class ProductViewController: UIViewController, UICollectionViewDelegate {

@IBOutlet var stackedView: UIStackView!
@IBOutlet weak var detailedView: UIView!
@IBOutlet var detailPageView: UIScrollView!
@IBOutlet var imagesCarouselCollection: UICollectionView!

@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var desc: UILabel!
@IBOutlet weak var features: UILabel!
@IBOutlet weak var price: UILabel!
@IBOutlet weak var starsLabel: UILabel!
@IBOutlet weak var noOfReviews: UILabel!
@IBOutlet weak var addToCartBtn: UIButton!
@IBOutlet weak var buyNowBtn: UIButton!

var searchedText: String = ""
var asinForSearch: String = ""
var resultsManager = ResultsManager()
var productDeets: Products?
var imagesArray = Array<String>()

override func viewDidLoad() {
    super.viewDidLoad()

    resultsManager.detailsDelegate = self
    search()
    self.setupUI()
    loadingIndicator.isAnimating = true
    imagesCarouselCollection.delegate = self
    imagesCarouselCollection.dataSource = self

imagesCarouselCollection.register(ImageCarouselViewCell.self, forCellWithReuseIdentifier: "ImageCarouselCollectionCell")
        imagesCarouselCollection.frame = imagesCarouselCollection.bounds

 DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
            self.populatePage()
}
}

@IBAction func buyNow(_ sender: Any) {

}
@IBAction func addToCart(_ sender: Any) {

}

func search(){
    resultsManager.getDetails(asinForSearch)
}

func createFeaturesLabels(featuresArray: [String]) -> String {
    var newFeatureString = ""
    for feature in featuresArray {
        newFeatureString.append(feature + "\n")
    }
    return newFeatureString
}

func populatePage(){
    if let productResults = self.productDeets {
        self.titleLabel.text = productResults.title
        self.desc.text = productResults.productDescription
        self.imagesArray = productDeets!.images
        self.features.text = createFeaturesLabels(featuresArray: productResults.featureBullets)
        self.price.text = "$" + String(productResults.price.currentPrice)
        self.starsLabel.text = productResults.reviews.rating
        self.noOfReviews.text = String(productResults.reviews.totalReviews)

        self.loadingIndicator.isAnimating = false
        self.stackedView.isHidden = false
    }
}

// MARK: - UI Setup for loading icon
private func setupUI() {
    if #available(iOS 13.0, *) {
        overrideUserInterfaceStyle = .light
    }

    self.stackedView.isHidden = true
    self.detailPageView.backgroundColor = .white

    self.detailPageView.addSubview(loadingIndicator)

    NSLayoutConstraint.activate([
        loadingIndicator.centerXAnchor
            .constraint(equalTo: self.view.centerXAnchor),
        loadingIndicator.centerYAnchor
            .constraint(equalTo: self.view.centerYAnchor),
        loadingIndicator.widthAnchor
            .constraint(equalToConstant: 50),
        loadingIndicator.heightAnchor
            .constraint(equalTo: self.loadingIndicator.widthAnchor)
    ])
}

// MARK: - Properties
let loadingIndicator: ProgressView = {
    let progress = ProgressView(colors: [.red, .systemGreen, .systemBlue], lineWidth: 5)
    progress.translatesAutoresizingMaskIntoConstraints = false
    return progress
}()
}

extension ProductViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let width: CGFloat = imagesCarouselCollection.bounds.size.width
        let height: CGFloat = imagesCarouselCollection.bounds.size.height
        return CGSize(width: width, height: height)
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ImageCarouselCollectionCell", for: indexPath) as! ImageCarouselViewCell
        let imageUrl = URL(string: imagesArray[indexPath.item])
        cell.imagioView.kf.setImage(with: imageUrl)
        return cell
    }
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    print(imagesArray.count)
    return imagesArray.count
}

func numberOfSections(in collectionView: UICollectionView) -> Int {
    return 1
}
}

extension ProductViewController: ResultsDetailDelegate {
    func updateDetails(_ resultsManager: ResultsManager, products: Products) {
        self.productDeets = products
    }
}

class ImageCarouselViewCell: UICollectionViewCell {

    @IBOutlet weak var imagioView: UIImageView!

}

【问题讨论】:

  • 当您嵌入到 stackview 时,您的数组数量是多少?
  • 你在使用 xib 那么请像这样注册 nib let nib = UINib(nibName: "ImageCarouselCollectionCell", bundle: nil) imagesCarouselCollection.register(nib, forCellReuseIdentifier: "ImageCarouselCollectionCell")
  • @YogeshPatel 我没有使用 xib
  • 好的,那么数组计数是多少?并将背景颜色添加到 UICollectionview 并检查。做一件事,将恒定高度添加到您的集合视图中,例如 100,然后查看输出是否出现。
  • @zamanada - 如果您发现问题(由于方法不正确),那么您应该关闭或删除此问题,因为它对其他用户没有帮助。

标签: uicollectionview storyboard uicollectionviewcell swift5 uistackview


【解决方案1】:

我发现了问题 - 与布局有关。正如我所怀疑的那样,教程中的一半代码没有被删除。最终尝试在情节提要中以编程方式声明集合视图及其内容。按照本教程https://www.youtube.com/watch?v=eWGu3hcL3ww

中的布局建议修复了它

对于其他面临此问题的人,这里是更新的代码。

class ProductViewController: UIViewController, UICollectionViewDelegate {

@IBOutlet var stackedView: UIStackView!
@IBOutlet weak var detailedView: UIView!
@IBOutlet var detailPageView: UIScrollView!
@IBOutlet var imagesCarouselCollection: UICollectionView!
@IBOutlet weak var imagesCarouselCollectionHeight: NSLayoutConstraint!

@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var desc: UILabel!
@IBOutlet weak var features: UILabel!
@IBOutlet weak var price: UILabel!
@IBOutlet weak var starsLabel: UILabel!
@IBOutlet weak var noOfReviews: UILabel!
@IBOutlet weak var addToCartBtn: UIButton!
@IBOutlet weak var buyNowBtn: UIButton!

var searchedText: String = ""
var asinForSearch: String = ""
var resultsManager = ResultsManager()
var productDeets: Products?
var imagesArray = Array<String>()

override func viewDidLoad() {
    super.viewDidLoad()

    resultsManager.detailsDelegate = self
    search()
    self.setupUI()
    loadingIndicator.isAnimating = true
    
    let layout = UICollectionViewFlowLayout()
    layout.itemSize = CGSize(width: 349, height: 410)
    imagesCarouselCollection.collectionViewLayout = layout
    layout.scrollDirection = .horizontal
    
    imagesCarouselCollection.register(ImageCollectionViewCell.nib(), forCellWithReuseIdentifier: ImageCollectionViewCell.identifier)
    imagesCarouselCollection.frame = imagesCarouselCollection.bounds

    DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
        self.imagesCarouselCollection.delegate = self
        self.imagesCarouselCollection.dataSource = self
        self.populatePage()
    }
}

@IBAction func buyNow(_ sender: Any) {
    
}

@IBAction func addToCart(_ sender: Any) {

}

func search(){
    resultsManager.getDetails(asinForSearch)
}

func createFeaturesLabels(featuresArray: [String]) -> String {
    var newFeatureString = ""
    for feature in featuresArray {
        newFeatureString.append(feature + "\n")
    }
    return newFeatureString
}

func populatePage(){
    if let productResults = self.productDeets {
        self.titleLabel.text = productResults.title
        self.desc.text = productResults.productDescription
        self.imagesArray = productDeets!.images
        self.features.text = createFeaturesLabels(featuresArray: productResults.featureBullets)
        self.price.text = "$" + String(productResults.price.currentPrice)
        self.starsLabel.text = productResults.reviews.rating + " out of 5 stars"
        self.noOfReviews.text = String(productResults.reviews.totalReviews) + " reviews"

        self.loadingIndicator.isAnimating = false
        self.stackedView.isHidden = false
    }
}

// MARK: - UI Setup for loading icon
private func setupUI() {
    if #available(iOS 13.0, *) {
        overrideUserInterfaceStyle = .light
    }

    self.stackedView.isHidden = true
    self.detailPageView.backgroundColor = .white

    self.detailPageView.addSubview(loadingIndicator)

    NSLayoutConstraint.activate([
        loadingIndicator.centerXAnchor
            .constraint(equalTo: self.view.centerXAnchor),
        loadingIndicator.centerYAnchor
            .constraint(equalTo: self.view.centerYAnchor),
        loadingIndicator.widthAnchor
            .constraint(equalToConstant: 50),
        loadingIndicator.heightAnchor
            .constraint(equalTo: self.loadingIndicator.widthAnchor)
    ])
}

// MARK: - Properties
let loadingIndicator: ProgressView = {
    let progress = ProgressView(colors: [.red, .systemGreen, .systemBlue], lineWidth: 5)
    progress.translatesAutoresizingMaskIntoConstraints = false
    return progress
}()
}

extension ProductViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ImageCollectionViewCell.identifier, for: indexPath) as! ImageCollectionViewCell
        let imageUrl = URL(string: imagesArray[indexPath.item])
        cell.configure(with: imageUrl!)
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return imagesArray.count
    }

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 1
    }
    
}

extension ProductViewController: ResultsDetailDelegate {
    func updateDetails(_ resultsManager: ResultsManager, products: Products) {
        self.productDeets = products
    }
}

我也不再只使用 CocoaTouch 类,而是使用 xib/nib 创建了一个新类

class ImageCollectionViewCell: UICollectionViewCell {
    
    @IBOutlet weak var productImageView: UIImageView!
    static let identifier = "ImageCollectionViewCell"
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }
    
    public func configure(with imageURL: URL) {
        productImageView.kf.setImage(with: imageURL)
    }
    
    static func nib() -> UINib {
        return UINib(nibName: "ImageCollectionViewCell", bundle: nil)
    }

}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-21
    • 1970-01-01
    • 2015-12-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-14
    • 1970-01-01
    相关资源
    最近更新 更多