Vertical scrolling with TableView inside horizontal CollectionView - ios

I have a horizontal UICollectionView (with paging) where each cell has a fullscreen UITableView. The parent ViewController has a navigation bar with large titles where an animation occurs during vertical scrolling. However, since my table views are within the horizontal collection view, the large navigation bar does not animate when scrolling.
I have attempted a solution of setting a delegate for the tableview scrolling and then set the y offset of the collection view but the result glitches and does not work correctly.
Here is my current code (without TableView/CollectionView delegate/datasource methods)
class HomeViewController: UIViewController, HomeCellDelegate {
var delegate: HomeViewControllerDelegate!
var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
create()
}
func create() {
view.backgroundColor = .background
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = 0
layout.minimumInteritemSpacing = 0
layout.sectionInset = .zero
collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
view.addSubview(collectionView)
collectionView.anchor(top: view.topAnchor, left: view.leftAnchor, bottom: view.bottomAnchor, right: view.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
collectionView.backgroundColor = .clear
collectionView.showsHorizontalScrollIndicator = false
collectionView.isPagingEnabled = true
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(HomeCell.self, forCellWithReuseIdentifier: "cellID")
}
//Delegate from UICollectionView cell (the table view)
func tableViewDidScroll(_ contentOffset: CGPoint) {
collectionView.contentOffset.y = contentOffset.y //Glitches
}
}
protocol HomeCellDelegate {
func tableViewDidScroll(_ contentOffset: CGPoint)
}
class HomeCell: UICollectionViewCell {
var events = [String]()
let tableView = UITableView()
var delegate: HomeCellDelegate!
override init(frame: CGRect) {
super.init(frame: frame)
create()
}
func create() {
backgroundColor = .clear
addSubview(tableView)
tableView.anchor(top: topAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
tableView.contentInsetAdjustmentBehavior = .never
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offset = CGPoint(x: 0.0, y: scrollView.contentOffset.y + scrollView.adjustedContentInset.top)
delegate.tableViewDidScroll(offset)
}
required init?(coder: NSCoder) {
fatalError()
}
}

Related

errors with UICollectionViewFlowLayout scrolling

I am setting up a UiCollectionView and I am trying to have the view scroll horizontally. The View is setup up and I can see labels and images but it does not scroll at all. The height of the collectionViewCell itself is 350 and how i am setting up the cell is
let SubView: UIView = {
let view = UIView()
view.backgroundColor = GREEN_Theme
view.layer.cornerRadius = 10
return view
}()
let headerLabel: UILabel = {
let label = UILabel()
label.text = "label"
label.font = UIFont.systemFont(ofSize: 30)
label.font = .boldSystemFont(ofSize: 30)
label.numberOfLines = 0
label.textColor = UIColor.black
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
addSubview(SubView)
SubView.anchors(top: topAnchor, topPad: 0, bottom: nil, bottomPad: 0, left: leftAnchor, leftPad: 0, right: rightAnchor, rightPad: 0, height: 1, width: self.bounds.width - 20)
addSubview(headerLabel)
headerLabel.anchors(top: SubView.bottomAnchor, topPad: 5 , bottom: nil, bottomPad: 0, left: safeAreaLayoutGuide.leftAnchor, leftPad: 15, right: nil, rightPad: 0, height: 50, width: 200)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let recentCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = UIColor.clear
collectionView.translatesAutoresizingMaskIntoConstraints = false
return collectionView
}()
func setupViews() {
backgroundColor = UIColor.clear
addSubview(recentCollectionView)
contentView.isUserInteractionEnabled = true
recentCollectionView.dataSource = self
recentCollectionView.delegate = self
recentCollectionView.isUserInteractionEnabled = true
recentCollectionView.backgroundColor = UIColor.blue
recentCollectionView.register(recentCell.self, forCellWithReuseIdentifier: cellID)
recentCollectionView.layer.zPosition = 1
recentCollectionView.topAnchor.constraint(equalTo: topAnchor, constant: 40).isActive = true
recentCollectionView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 5).isActive = true
recentCollectionView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -5).isActive = true
recentCollectionView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -40).isActive = true
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return reviews.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellID, for: indexPath) as! recentCell
cell.configureCell(reviews[indexPath.row])
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 100, height: frame.height - 5)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
return UIEdgeInsets(top: 100, left: 14, bottom: 0, right: 14)
}
}
class recentCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
let imageView: UIImageView = {
let iv = UIImageView()
iv.image = UIImage(named: "rake")
iv.contentMode = .scaleAspectFill
iv.layer.cornerRadius = 16
iv.layer.masksToBounds = true
return iv
}()
let nameLabel: UILabel = {
let label = UILabel()
label.text = "Zach Wilcox"
label.font = UIFont.systemFont(ofSize: 14)
label.numberOfLines = 2
return label
}()
let categoryLabel: UILabel = {
let label = UILabel()
label.text = "Yard Work"
label.font = UIFont.systemFont(ofSize: 13)
label.textColor = UIColor.darkGray
return label
}()
let starControls = starStackView()
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews() {
addSubview(imageView)
addSubview(nameLabel)
addSubview(categoryLabel)
addSubview(starControls)
starControls.translatesAutoresizingMaskIntoConstraints = false
starControls.distribution = .fillEqually
imageView.frame = CGRect(x:0, y: 0, width: frame.width, height: frame.width)
nameLabel.anchors(top: imageView.bottomAnchor, topPad: 1, bottom: nil, bottomPad: 0, left: imageView.leftAnchor, leftPad: 0, right: nil, rightPad: 0, height: 20, width: 100)
categoryLabel.anchors(top: nameLabel.bottomAnchor, topPad: 1, bottom: nil, bottomPad: 0, left: imageView.leftAnchor, leftPad: 0, right: nil, rightPad: 0, height: 20, width: 100)
starControls.anchors(top: categoryLabel.bottomAnchor, topPad: 1, bottom: nil, bottomPad: 0, left: imageView.leftAnchor, leftPad: 0, right: nil, rightPad: 0, height: 20, width: 100)
}
In my console, I see
the item height must be less than the height of the UICollectionView minus the section insets top and bottom values, minus the content insets top and bottom values.
I have tried to set the background colors to blue in the recentCollectionView and the collectionView itself to see if the if the height of the cell is exceeding the height of the collectionView but it is not.
images below,
the first image, is the size of the entire contentView.
and this image is the size of the recentCollectionView
as we can see with the images, the recentCollectionView is not larger than the collectionView. Why am I seeing this error and why will my collectionViewFlowLayout not scroll?
I have found an answer shortly after posting my question but did not want to delete just in case some other newbie had the same problem. All I had to do was add the recentCollectionView to the contentView's subview not simply just addSubview.
contentView.addSubview(recentCollectionView)
super simple fix.

UICollectionView x3 Within each other creating a collection view slider within a header collection view

I was wondering if anyone can show/help me.
As you can see in image 2 that I am trying to create a card slider, within my UICOLLECTIONVIEW at the top.
I am aware that to create a UICollectionView slider you need to first create the collectionview to hold the slider then another within it. So all together I have 3 UICOLLECTIONVIEWS within each other.
I have been following tutorials to get this far but I can’t figure this one out. Image one is where I am currently.
But currently, all I seem to be doing is overlaying the current UICollection not making it go within it, as you can see in image 1.
[
import UIKit
class MyFeedsHeader: UICollectionViewCell, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
private let cellId = "appCellId"
let profileImageView: UIImageView = {
let iv = UIImageView()
iv.contentMode = .scaleAspectFill
iv.clipsToBounds = true
iv.backgroundColor = .lightGray
return iv
}()
let feedsTitle: UILabel = {
let title = UILabel()
title.text = "Feeds"
title.font = UIFont.boldSystemFont(ofSize: 30)
return title
}()
let followingLabel: UILabel = {
let title = UILabel()
title.text = "00 Following"
title.font = UIFont.boldSystemFont(ofSize: 16)
title.textColor = .lightGray
return title
}()
// --------------------
let appsCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
// layout.scrollDirection = .horizontal
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.backgroundColor = UIColor.clear
collectionView.translatesAutoresizingMaskIntoConstraints = false
return collectionView
}()
//--------------------
override init(frame: CGRect) {
super.init(frame: frame)
addSubview(profileImageView)
profileImageView.anchor(top: self.topAnchor, left: nil, bottom: nil, right: self.rightAnchor, paddingTop: 16, paddingLeft: 0, paddingBottom: 0, paddingRight: 20, width: 50, height: 50)
profileImageView.layer.cornerRadius = 5 / 1
addSubview(feedsTitle)
feedsTitle.anchor(top: self.topAnchor, left: self.leftAnchor, bottom: nil, right: nil, paddingTop: 20, paddingLeft: 20, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
addSubview(followingLabel)
followingLabel.anchor(top: feedsTitle.bottomAnchor, left: self.leftAnchor, bottom: nil, right: nil, paddingTop: 20, paddingLeft: 20, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
setupViews()
self.backgroundColor = .white
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// ---------------------------------- remove below if can't figure out
func setupViews() {
// --------
appsCollectionView.dataSource = self
appsCollectionView.delegate = self
appsCollectionView.register(AppCell.self, forCellWithReuseIdentifier: cellId)
addSubview(appsCollectionView)
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-8-[v0]-8-|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": appsCollectionView]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": appsCollectionView]))
//--------
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
return collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath)
}
class AppCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews() {
backgroundColor = UIColor.red
}
}
}
I recommend starting with the outermost UICollectionView first, and as you get each one working you can move on to the next.
To get more detail on exactly what is going on with the app currently you can use the View Debugger to see if everything is nested correctly and any constraints are doing what they should.
To get the effect you are looking for your first stop should be implementing the methods coming from UICollectionViewDelegateFlowLayoutlike sizeForItemAt, insetForSectionAt, & minimumLineSpacingForSectionAt. These will define spacing and layout for the cells to interact with.
These delegate methods are all part of the protocol UICollectionViewDelegateFlowLayout which means that your collection view (who's delegate you set to self AKA MyFeedsHeader) will ask your class MyFeedsHeader for information about how to layout the cells if MyFeedsHeader has the functions on it. The is the same thing you did with the func collectionView:numberOfItemsInSection.
Hope that points you in the right direction! Best of luck!

UIStackViews Autolayout throws when either spacing or contentEdgeInsets of UIButton is enabled

I got a UIStackView ParticipateButtonStackView managing three buttons of the same class: ParticipateButton
These buttons only contain an image. To have some padding at the top and bottom, I set UIEdgeInsets. But this and the .spacing = 1 property seem to not work simultaneously. Why?
Stackview:
class ParticipateButtonStackView: UIStackView {
//MARK: - Properties & Variables
var delegate: participateButtonStackViewDelegate?
//MARK: - GUI Objects
var buttons: [ParticipateButton]!
let sureButton = ParticipateButton(type: .sure)
let maybeButton = ParticipateButton(type: .maybe)
let nopeButton = ParticipateButton(type: .nope)
//MARK: - Init & View Loading
override init(frame: CGRect) {
super.init(frame: frame)
self.addBackground(color: UIColor.gray)
buttons = [sureButton, maybeButton, nopeButton]
setupStackView()
setupButtons()
}
//MARK: - Setup
func setupStackView() {
self.axis = .horizontal
self.spacing = 1
self.alignment = .leading
self.distribution = .fillEqually
}
func setupButtons() {
for button in buttons {
addArrangedSubview(button)
button.addTarget(self, action: #selector (self.buttonClick(sender:)), for: .touchUpInside)
}
}
}
ParticipateButton
class ParticipateButton: UIButton {
var typeOfButton: participateLists!
override init(frame: CGRect) {
super.init(frame: frame)
self.backgroundColor = LebensfitSettings.Colors.buttonBG
self.tintColor = LebensfitSettings.Colors.basicTintColor
self.imageView?.contentMode = .scaleAspectFit
self.contentEdgeInsets = UIEdgeInsets(top: 7, left: 0, bottom: 7, right: 0)
}
convenience init(type: participateLists) {
self.init()
self.typeOfButton = type
setImage(type: type)
}
func setImage(type: participateLists) {
var buttonImage: UIImage?
switch type {
case .sure:
buttonImage = UIImage(named: "pb_sure")?.withRenderingMode(.alwaysTemplate)
[...]
}
self.setImage(buttonImage, for: .normal)
}
}
This is the error that gets thrown:
Will attempt to recover by breaking constraint
NSLayoutConstraint:0x600001adb020 'UISV-spacing' H: [LebensfitFirebase.ParticipateButton:0x7f9899c5eaa0]-(1)-[LebensfitFirebase.ParticipateButton:0x7f9899c5fad0] (active)>
Edit:
participateButtonStackView.leftAnchor = view.leftAnchor
participateButtonStackView.rightAnchor = view.rightAnchor
participateButtonStackView.bottomAnchor = view.bottomAnchor
participateButtonStackView.heightAnchor = equalToConstant(50)
I was not able to solve this problem so i built this workaround:
ParticipateButton
func setBordersLeftRight() {
let borderLeft = UIView()
let borderRight = UIView()
borderLeft.backgroundColor = .gray
borderRight.backgroundColor = .gray
addSubview(borderLeft)
addSubview(borderRight)
borderLeft.anchor(top: topAnchor, left: leftAnchor, bottom: bottomAnchor, right: nil, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0.5, height: 0)
borderRight.anchor(top: topAnchor, left: nil, bottom: bottomAnchor, right: rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0.5, height: 0)
}

Get frame size in updateConstraint function of Custom UIView

I'm setting constraints for views (UILabel, UIImageView) in custom UIView inside UpdateConstraint functions like below. As seen, I'm getting views' height and use it inside auto layout. I know I can get frame size in layoutSubviews function. If I call updateConstraint() function inside layoutSubViews , everything works fine but I don't know If It is the best approach.
In addition when I try to set frame in layoutSubViews() with label.frame = CGRect.. (without auto layout) nothing happens and I can't see custom views inside superview.
override func updateConstraints() {
logoImage.anchor(self.topAnchor, left: self.leftAnchor, bottom: self.bottomAnchor, right: self.rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: self.frame.height / 2, rightConstant: 0, widthConstant: 0, heightConstant: 0)
label.anchor(self.logoImage.bottomAnchor, left: self.leftAnchor, bottom: nil, right: self.rightAnchor, topConstant: 12, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 0)
super.updateConstraints()
}
override func layoutSubviews() {
print(self.frame.height)
updateConstraints()
}
I searched below posts but can't find any solution;
Where to get frame size of custom UIView in its subclass
Subview of Custom UIView has wrong x frame position
No need to handle that in layoutSubviews if your current constraint create extension sets isActive = true then it will have the correct frame
//
correct way of creating a customView
class CustomView : UIView {
var imageV = UIImageView()
var once = true
override init(frame: CGRect) {
super.init(frame: frame)
sharedLayout()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
sharedLayout()
}
func sharedLayout() {
// set constraints here
self.addSubview(imageV)
}
override func layoutSubviews() {
if once {
self.imageV.translatesAutoresizingMaskIntoConstraints = false
self.imageV.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
self.imageV.trailingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
self.imageV.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
self.imageV.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
once = false
}
}
}

Inaccuracy addSubview in UICollectionViewCell

There was a big problem that I can not solve for a couple of days.
I have a UIViewController with UICollectionView in which there will be 3 cells with different content. Here is my class:
class PostView: AppViewAddMenu, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
var homeController: FeedController?
var contentArray = [PostContentModel]()
var postInfo: PostModel?
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.minimumLineSpacing = 3
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.delegate = self
cv.dataSource = self
cv.backgroundColor = .white
return cv
}()
override func setupViewController() {
collectionView.register(PostViewCell.self, forCellWithReuseIdentifier: "cellId")
view.addSubview(collectionView)
view.addConstraintsWithFormat("H:|[v0]|", views: collectionView)
view.addConstraintsWithFormat("V:|-60-[v0]|", views: collectionView)
fetchPost(id: postInfo?.id)
}
func fetchPost(id: Int?){
guard let ID = id else {
print("ID faild")
return
}
let url: String = "https://FTP.ru/wp-json/mobileApi/v1/post/\(ID)"
ApiService.sharedInstance.fetchContent(url: url, completion: { (Posts: [PostContentModel]) in
self.contentArray = Posts
self.collectionView.reloadData()
})
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! PostViewCell
cell.contentArray = contentArray
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: 1000)
}
}
The idea of the first cell is to take json from a site that looks like this: [switch, content]. From the switch value in UICollectionViewCell, different functions are called, which add an element in UICollectionViewCell via addSubview (). Here's the code:
class PostViewCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
anchor = self.topAnchor
}
var anchor: NSLayoutYAxisAnchor?
var contentArray: [PostContentModel]?{
didSet{
for number in contentArray! {
if(number.switcher == 1) {
anchor = addTextContent(content: number.content!, bottomAnchor: anchor!)
}
if(number.switcher == 2){
anchor = addImageContent(content: number.content!, bottomAnchor: anchor!)
}
if(number.switcher == 3){
anchor = addCaptionFirst(content: number.content!, bottomAnchor: anchor!)
}
if(number.switcher == 4){
anchor = addButtonLink(content: number.content!, link: number.link!, bottomAnchor: anchor!)
}
}
}
}
func addTextContent(content: String, bottomAnchor: NSLayoutYAxisAnchor) -> NSLayoutYAxisAnchor{
let shortContentPost: UILabel = {
let label = UILabel()
label.text = content
label.numberOfLines = 0
label.font = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight.regular)
return label
}()
addSubview(shortContentPost)
shortContentPost.anchor(bottomAnchor, left: self.leftAnchor, bottom: nil, right: self.rightAnchor, topConstant: 15, leftConstant: 15, bottomConstant: 0, rightConstant: 15, widthConstant: 0, heightConstant: 0)
return shortContentPost.bottomAnchor
}
func addImageContent(content: String, bottomAnchor: NSLayoutYAxisAnchor) -> NSLayoutYAxisAnchor {
let image: CustomImageView = {
let image = CustomImageView()
image.image = UIImage(named: content)
image.contentMode = .scaleAspectFill
image.clipsToBounds = true
return image
}()
let imageURL = "https://brodude.ru/wp-content/uploads/" + content.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!
image.loadImageUsingUrlString(urlString: imageURL)
addSubview(image)
image.anchor(bottomAnchor, left: self.leftAnchor, bottom: nil, right: self.rightAnchor, topConstant: 15, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 250)
return image.bottomAnchor
}
func addCaptionFirst(content: String, bottomAnchor: NSLayoutYAxisAnchor) -> NSLayoutYAxisAnchor {
let Caption: UILabel = {
let lb = UILabel()
lb.text = content
lb.numberOfLines = 0
lb.font = UIFont.systemFont(ofSize: 20, weight: UIFont.Weight.semibold)
return lb
}()
addSubview(Caption)
Caption.anchor(bottomAnchor, left: self.leftAnchor, bottom: nil, right: self.rightAnchor, topConstant: 30, leftConstant: 15, bottomConstant: 0, rightConstant: 15, widthConstant: 0, heightConstant: 0)
return Caption.bottomAnchor
}
func addButtonLink(content: String, link: String, bottomAnchor: NSLayoutYAxisAnchor) -> NSLayoutYAxisAnchor {
let button: LinkButton = {
let bt = LinkButton()
bt.LinkString = link
bt.titleLabel?.font = UIFont.systemFont(ofSize: 18, weight: UIFont.Weight.semibold)
bt.setTitle(content, for: UIControlState.normal)
bt.sizeToFit()
bt.titleLabel?.numberOfLines = 0
bt.contentHorizontalAlignment = .left
bt.setTitleColor(UIColor(red: 0.07, green: 0.32, blue: 0.89, alpha: 1.0), for: UIControlState.normal)
bt.addTarget(self, action: #selector(linkOut), for: .touchUpInside)
return bt
}()
addSubview(button)
button.anchor(bottomAnchor, left: self.leftAnchor, bottom: nil, right: self.rightAnchor, topConstant: 20, leftConstant: 15, bottomConstant: 0, rightConstant: 15, widthConstant: 0, heightConstant: 0)
return button.bottomAnchor
}
The algorithm works satisfactorily, but the problem begins when the cell is updated. When scrolling, with collectionView.reloadData (). New subview layered on the past, the text becomes fatter and clogged device memory. The process continues indefinitely until it gives an error.
Example of a problem:, ,
Sorry for my English.
First of all, instead of:
addSubview(shortContentPost)
use:
contentView.addSubview(shortContentPost)
Do this for all the subviews that you add. contentView is supposed to hold your content.
Implement this prepareForReuse in your cell:
override func prepareForReuse() {
super.prepareForReuse()
let subviews = contentView.subviews
for subview in subviews {
subview.removeFromSuperview()
}
}
This will clean your cell's content before reusing the cell.
Although I would STRONGLY recommend NOT to add/remove those subviews dynamically, because then you lose much of the reuse mechanism. I would add all the views (labels/imageViews) to the cell by default, and then use their isHidden property to hide/unhide them based on the content (e.g., if an image should be show, set the isHidden to true on all the others). This would be performance-wise better for reusing, because then the UI objects will not have to be recreated everytime a cell is reused, you would just reconfigure the content of the labels/imageViews.

Resources