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)
}
}
我正在尝试制作一个亚马逊克隆。我正在处理产品详细信息页面。基本上你搜索,你点击你想要的项目的 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)
}
}