Swift 5 - 为什么我的 collectionview 在嵌入 stackview 时消失了?

Swift 5 - why does my collectionview disappear when embedded in a stackview?

我正在尝试制作一个亚马逊克隆。我正在处理产品详细信息页面。基本上你搜索,你点击你想要的项目的 tableviewcell,然后你登陆详细信息页面。除了包含图像的 collectionview 之外,所有内容都会加载。当我删除 stackview 时,一切都加载正常,但是当我将视图的内容嵌入到 stackview 中时,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!

}

我发现了问题 - 它与布局有关。正如我所怀疑的那样,教程中的一半代码没有被删除。最终尝试在故事板中以编程方式声明 collectionview 及其内容。它已按照本教程中的布局建议修复 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 class 而是使用 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)
    }

}