Custom cell for UICollection view cell unable clear old data - ios

I created a custom UICollection cell but the data sometimes appear in the wrong cell and no matter how much I refresh the UICollection view it refuses to change. I have done a print out to see if the data gotten from the array is wrong but it's not. Is there a way to clear the old data from the cell before inputting the next one. Any suggestion will be appreciated.
custom cell
class customAppointmentViewCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
let thumbnailImageView: UIImageView = {
let tniv = UIImageView()
tniv.translatesAutoresizingMaskIntoConstraints = false
tniv.backgroundColor = UIColor.clear
tniv.contentMode = .scaleAspectFit
return tniv
}()
let seperatorView: UIView = {
let sv = UIView()
sv.translatesAutoresizingMaskIntoConstraints = false
sv.backgroundColor = UIColor(r: 11, g: 49, b: 68)
return sv
}()
let clientNamePlaceHolder: UILabel = {
let fnhp = UILabel()
fnhp.translatesAutoresizingMaskIntoConstraints = false
fnhp.font = UIFont(name: "HelveticaNeue-Medium", size: 17)
fnhp.textColor = UIColor.white
fnhp.textAlignment = .left
return fnhp
}()
let openingTimePlaceHolder: UILabel = {
let fnhp = UILabel()
fnhp.translatesAutoresizingMaskIntoConstraints = false
fnhp.font = UIFont(name: "HelveticaNeue-Medium", size: 12)
fnhp.textColor = UIColor.white
fnhp.textAlignment = .left
return fnhp
}()
let closingTimePlaceHolder: UILabel = {
let fnhp = UILabel()
fnhp.translatesAutoresizingMaskIntoConstraints = false
fnhp.font = UIFont(name: "HelveticaNeue-Medium", size: 12)
fnhp.textColor = UIColor.white
fnhp.textAlignment = .left
return fnhp
}()
let bookedBarberNamePlaceHolder: UILabel = {
let fnhp = UILabel()
fnhp.translatesAutoresizingMaskIntoConstraints = false
fnhp.font = UIFont(name: "HelveticaNeue-Medium", size: 12)
fnhp.textColor = UIColor.white
fnhp.textAlignment = .left
return fnhp
}()
let servicePricePlaceHolder: UILabel = {
let fnhp = UILabel()
fnhp.translatesAutoresizingMaskIntoConstraints = false
fnhp.font = UIFont(name: "HelveticaNeue-Medium", size: 10)
fnhp.textColor = UIColor.white
fnhp.textAlignment = .right
return fnhp
}()
func setupViews(){
addSubview(thumbnailImageView)
addSubview(clientNamePlaceHolder)
addSubview(openingTimePlaceHolder)
addSubview(closingTimePlaceHolder)
addSubview(bookedBarberNamePlaceHolder)
addSubview(servicePricePlaceHolder)
addSubview(seperatorView)
backgroundColor = UIColor(r: 23, g: 69, b: 90)
addContraintsWithFormat(format: "H:|-16-[v0(90)]|", views: thumbnailImageView)
addContraintsWithFormat(format: "H:|-116-[v0][v1(50)]-10-|", views: clientNamePlaceHolder, servicePricePlaceHolder)
addContraintsWithFormat(format: "H:|-116-[v0]-60-|", views: openingTimePlaceHolder)
addContraintsWithFormat(format: "H:|-116-[v0]-60-|", views: closingTimePlaceHolder)
addContraintsWithFormat(format: "H:|-116-[v0]-60-|", views: bookedBarberNamePlaceHolder)
addContraintsWithFormat(format: "V:|-10-[v0(20)][v1(20)][v2(20)][v3(20)]-10-|", views: clientNamePlaceHolder, openingTimePlaceHolder,closingTimePlaceHolder, bookedBarberNamePlaceHolder)
addContraintsWithFormat(format: "V:|-10-[v0(20)]|", views: servicePricePlaceHolder)
addContraintsWithFormat(format: "V:|-10-[v0]-10-[v1(5)]|", views: thumbnailImageView,seperatorView)
addContraintsWithFormat(format: "H:|[v0]|", views: seperatorView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
collection view
extension AppointmentsViewController: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.appointments.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! customAppointmentViewCell
//empty cell data
//real data
cell.openingTimePlaceHolder.text = ""
if let opentime = self.appointments[safe: indexPath.row]?.bookingStartTimeString {
cell.openingTimePlaceHolder.text = opentime
} else {
cell.openingTimePlaceHolder.text = ""
}
cell.closingTimePlaceHolder.text = ""
if let closetime = self.appointments[safe: indexPath.row]?.bookingEndTimeString {
cell.closingTimePlaceHolder.text = closetime
} else {
cell.closingTimePlaceHolder.text = ""
}
cell.bookedBarberNamePlaceHolder.text = ""
if let barberName = self.appointments[safe: indexPath.row]?.bookedBarberName {
cell.bookedBarberNamePlaceHolder.text = barberName
} else {
cell.bookedBarberNamePlaceHolder.text = ""
}
cell.servicePricePlaceHolder.text = ""
if let servicepricee = self.appointments[safe: indexPath.row]?.bookedServicePrice {
cell.servicePricePlaceHolder.text = servicepricee
} else {
cell.servicePricePlaceHolder.text = ""
}
cell.thumbnailImageView.image = UIImage()
if let profileimagess = self.appointments[safe: indexPath.row]?.profileImage {
cell.thumbnailImageView.image = profileimagess
} else {
cell.thumbnailImageView.image = UIImage()
}
cell.clientNamePlaceHolder.text = ""
if let clientnamess = self.appointments[safe: indexPath.row]?.clientName {
cell.clientNamePlaceHolder.text = clientnamess
} else {
cell.clientNamePlaceHolder.text = ""
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectView.frame.width, height: 100)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let uuidAvail = UserDefaults.standard.object(forKey: "theOriginalBarberShopUUID") as? String{
if let bookIDDD = self.appointments[safe: indexPath.row]?.bookingUniqueID {
let orderDetail = OrderDetailViewController()
orderDetail.specificAppintment = self.appointments[indexPath.row]
orderDetail.barberShopID = uuidAvail
orderDetail.bookingUniqueIDDD = bookIDDD
orderDetail.bookedBarberUUIDAX = self.appointments[indexPath.row].bookedBarberUUID
orderDetail.appointmentsviewhold = self
orderDetail.indexPathSelected = indexPath.row
navigationController?.pushViewController(orderDetail, animated: true)
}
}
}
}
thanks

Do this in customAppointmentViewCell
override func prepareForReuse() {
self. thumbnailImageView.image = UIImage()
//add here other variable and set default value for all.
}
prepareForReuse is called when a new cell will show on screen.
And Remove default value set code from your cellForRow as guided by Nikhil Manapure.
Hope this helps you.

Try this -
Implement the method prepareForReuse in your customAppointmentViewCell and in this method remove all the data and reset everything. If you are adding some subView to cell in cellForRow, remove that too.
By doing this you will be able to reduce this-
cell.clientNamePlaceHolder.text = ""
if let clientnamess = self.appointments[safe: indexPath.row]?.clientName {
cell.clientNamePlaceHolder.text = clientnamess
} else {
cell.clientNamePlaceHolder.text = ""
}
to this-
if let clientnamess = self.appointments[safe: indexPath.row]?.clientName {
cell.clientNamePlaceHolder.text = clientnamess
}
After doing this, check if the issue is still there.
Hope this helps :)

Try Passing the model object to the UICollectionViewCell class by assigning a property in cell
example:
UICollectionViewCell:
var object: Model? {
didSet{
// here do your assignment of text to various labels
}
}
CellForRow:
let cell = ...
cell.object = self.appointments[indexPath.item]
return cell
I hope this works.

Related

CollectionView in TableView Cell Swift mix card type reuse issue

A collection view is contained in a table view cell.
Collection view cells are drawn for each card type.
In indexPath 0 and 1, the card is of a single type.
indexPath 2 is a mix type.
There are three card types, live reserved vod, and playLayer is added when it is a vod type.
When drawing collection view cells in mix type, playLayer is added to reserved type, and playLayer is added to all cells when scrolling up and down.
class TableViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
lazy private var homeManager = HomeManager()
var sections: [Section]?
var liveData: [Item]?
var vodData: [Item]?
var mixData: [Item]?
var table: UITableView = {
let tableView = UITableView()
tableView.register(CardCollectionTableViewCell.self, forCellReuseIdentifier: CardCollectionTableViewCell.identifier)
return tableView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .black
view.addSubview(table)
homeManager.getdata{ [weak self] response in
self?.sections = response.sections ?? []
self?.liveData = self?.sections?[1].items ?? []
self?.vodData = self?.sections?[2].items ?? []
self?.mixData = self?.sections?[3].items ?? []
self?.table.reloadData()
}
table.delegate = self
table.dataSource = self
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
table.frame = view.bounds
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 && liveData != nil {
let cell = table.dequeueReusableCell(withIdentifier: CardCollectionTableViewCell.identifier, for: indexPath) as! CardCollectionTableViewCell
cell.configure(with: liveData)
cell.titleLabel.text = sections![1].title!
return cell
} else if indexPath.row == 1 && vodData != nil {
let cell = table.dequeueReusableCell(withIdentifier: CardCollectionTableViewCell.identifier, for: indexPath) as! CardCollectionTableViewCell
cell.configure(with: vodData)
cell.titleLabel.text = sections![2].title!
return cell
} else if indexPath.row == 2 && mixData != nil {
let cell = table.dequeueReusableCell(withIdentifier: CardCollectionTableViewCell.identifier, for: indexPath) as! CardCollectionTableViewCell
cell.configure(with: mixData)
cell.titleLabel.text = sections![3].title!
return cell
}
else {
return UITableViewCell()
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 400
}
CardCollection TableViewCell
static let identifier = "CardCollectionTableViewCell"
var titleLabel: UILabel = {
let label = UILabel()
label.font = Fonts.text16()
label.textColor = .white
return label
}()
var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
layout.scrollDirection = .horizontal
collectionView.register(MyCollectionViewCell.self, forCellWithReuseIdentifier: MyCollectionViewCell.identifier)
collectionView.backgroundColor = .black
return collectionView
}()
var models:[Item]?
func configure(with models: [Item]?) {
self.models = models
titleLabel.snp.makeConstraints { make in
make.top.equalToSuperview()
make.leading.equalToSuperview().offset(20)
make.width.equalTo(300)
make.height.equalTo(24)
}
collectionView.snp.makeConstraints { make in
make.top.equalToSuperview().offset(44)
make.leading.equalToSuperview().offset(20)
make.trailing.bottom.equalToSuperview()
}
collectionView.reloadData()
}
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(collectionView)
contentView.addSubview(titleLabel)
collectionView.delegate = self
collectionView.dataSource = self
contentView.backgroundColor = .black
//guard models != nil else { return }
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
// Collectionview
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return models?.count ?? 5
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: MyCollectionViewCell.identifier, for: indexPath) as! MyCollectionViewCell
cell.setupViews(with: models![indexPath.item])
cell.setupConstraints(with: models![indexPath.item])
cell.configure(with: models![indexPath.item])
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 140, height: 350)
}
CollectionViewCell
class MyCollectionViewCell: UICollectionViewCell {
static let identifier = "MyCollectionViewCell"
var player: AVPlayer?
private lazy var imageView: UIImageView = {
let image = UIImageView()
image.contentMode = .scaleAspectFill
image.clipsToBounds = true
image.backgroundColor = .blue
image.layer.cornerRadius = 8
return image
}()
private lazy var typeLabelBackgroud: UIImageView = {
let image = UIImageView()
image.clipsToBounds = true
image.layer.cornerRadius = 8
return image
}()
private lazy var playerView: AVPlayerLayer? = {
let url = URL(string: "https://1303309272.vod2.myqcloud.com/7e895809vodkr1303309272/8155555e3701925920462082823/f0.mp4")
player = AVPlayer(url: url!)
let playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = CGRect(x: 0, y: 0, width: 140, height: 210)
playerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
self.player?.play()
}
return playerLayer
}()
private lazy var typeLabel: UILabel = {
let label = UILabel()
label.font = Fonts.text10()
label.textColor = .white
return label
}()
private lazy var timeLabel: UILabel? = {
let label = UILabel()
label.font = Fonts.text11()
label.textColor = .white
label.frame.size.width = 42
label.frame.size.height = 16
return label
}()
private lazy var titleLabel: UILabel = {
let label = UILabel()
label.numberOfLines = 0
label.font = Fonts.text14()
label.textColor = .white
return label
}()
private lazy var storeName: UILabel = {
let label = UILabel()
label.font = Fonts.text11()
label.textColor = .gray
return label
}()
private lazy var heartImage: UIImageView = {
let image = UIImageView()
image.image = UIImage(named: "Vector")
image.contentMode = .scaleAspectFit
return image
}()
private lazy var heartCountLabel: UILabel = {
let label = UILabel()
label.font = Fonts.text11()
label.textColor = .gray
label.frame.size.width = 27
label.frame.size.height = 16
label.textAlignment = .left
return label
}()
private lazy var eyeImage: UIImageView = {
let image = UIImageView()
image.image = UIImage(named: "Eye")
image.contentMode = .scaleAspectFit
return image
}()
private lazy var eyeCountLabel: UILabel = {
let label = UILabel()
label.font = Fonts.text11()
label.textColor = .gray
label.frame.size.width = 27
label.frame.size.height = 16
label.textAlignment = .left
return label
}()
private override init(frame: CGRect) {
super.init(frame: frame)
}
public convenience init() {
self.init(frame:. zero)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupViews(with model: Item?) {
guard model != nil else {return}
print("CollectionViewCell의 model! data: \(model)")
if model!.type == "LIVE" {
addSubview(imageView)
addSubview(typeLabelBackgroud)
addSubview(typeLabel)
addSubview(titleLabel)
addSubview(storeName)
addSubview(heartImage)
addSubview(heartCountLabel)
addSubview(eyeImage)
addSubview(eyeCountLabel)
} else if model!.type == "RESERVED"{
addSubview(imageView)
addSubview(typeLabelBackgroud)
addSubview(typeLabel)
addSubview(titleLabel)
addSubview(storeName)
addSubview(heartImage)
addSubview(heartCountLabel)
addSubview(eyeImage)
addSubview(eyeCountLabel)
} else if model!.type == "VOD" {
addSubview(imageView)
addSubview(typeLabelBackgroud)
addSubview(typeLabel)
addSubview(titleLabel)
addSubview(storeName)
addSubview(heartImage)
addSubview(heartCountLabel)
addSubview(eyeImage)
addSubview(eyeCountLabel)
addSubview(timeLabel!)
imageView.layer.addSublayer(playerView!)
}
}
func setupConstraints(with model: Item?) {
guard model != nil else {return}
if model!.type == "LIVE" {
imageView.snp.makeConstraints { make in
make.width.equalTo(140)
make.height.equalTo(210)
}
typeLabelBackgroud.snp.makeConstraints { make in
make.leading.equalTo(imageView).inset(8)
make.top.equalTo(imageView).inset(10)
make.width.equalTo(33)
make.height.equalTo(20)
}
typeLabel.snp.makeConstraints { make in
make.leading.equalTo(typeLabelBackgroud).inset(6)
make.top.equalTo(typeLabelBackgroud).inset(2)
make.width.equalTo(21)
make.height.equalTo(16)
}
titleLabel.snp.makeConstraints { make in
make.top.equalTo(imageView.snp.bottom).offset(8)
make.width.equalTo(140)
make.height.equalTo(42)
}
storeName.snp.makeConstraints { make in
make.top.equalTo(titleLabel.snp.bottom).offset(4)
make.width.equalTo(140)
make.height.equalTo(16)
}
heartImage.snp.makeConstraints { make in
make.top.equalTo(storeName.snp.bottom).offset(3)
make.width.height.equalTo(16)
}
heartCountLabel.snp.makeConstraints { make in
make.top.equalTo(storeName.snp.bottom).offset(3)
make.leading.equalTo(heartImage.snp.trailing).offset(5)
}
eyeImage.snp.makeConstraints { make in
make.leading.equalTo(heartCountLabel.snp.trailing).offset(13)
make.top.equalTo(storeName.snp.bottom).offset(3)
make.width.height.equalTo(16)
}
eyeCountLabel.snp.makeConstraints { make in
make.top.equalTo(storeName.snp.bottom).offset(3)
make.leading.equalTo(eyeImage.snp.trailing).offset(5)
}
} else if model!.type == "RESERVED" {
imageView.snp.makeConstraints { make in
make.width.equalTo(140)
make.height.equalTo(210)
}
typeLabelBackgroud.snp.makeConstraints { make in
make.leading.equalTo(imageView).inset(8)
make.top.equalTo(imageView).inset(10)
make.width.equalTo(33)
make.height.equalTo(20)
}
typeLabel.snp.makeConstraints { make in
make.leading.equalTo(typeLabelBackgroud).inset(6)
make.top.equalTo(typeLabelBackgroud).inset(2)
make.width.equalTo(21)
make.height.equalTo(16)
}
titleLabel.snp.makeConstraints { make in
make.top.equalTo(imageView.snp.bottom).offset(8)
make.width.equalTo(140)
make.height.equalTo(42)
}
storeName.snp.makeConstraints { make in
make.top.equalTo(titleLabel.snp.bottom).offset(4)
make.width.equalTo(140)
make.height.equalTo(16)
}
heartImage.snp.makeConstraints { make in
make.top.equalTo(storeName.snp.bottom).offset(3)
make.width.height.equalTo(16)
}
heartCountLabel.snp.makeConstraints { make in
make.top.equalTo(storeName.snp.bottom).offset(3)
make.leading.equalTo(heartImage.snp.trailing).offset(5)
}
eyeImage.snp.makeConstraints { make in
make.leading.equalTo(heartCountLabel.snp.trailing).offset(13)
make.top.equalTo(storeName.snp.bottom).offset(3)
make.width.height.equalTo(16)
}
eyeCountLabel.snp.makeConstraints { make in
make.top.equalTo(storeName.snp.bottom).offset(3)
make.leading.equalTo(eyeImage.snp.trailing).offset(5)
}
} else if model!.type == "VOD" {
imageView.snp.makeConstraints { make in
make.width.equalTo(140)
make.height.equalTo(210)
}
typeLabelBackgroud.snp.makeConstraints { make in
make.leading.equalTo(imageView).inset(8)
make.top.equalTo(imageView).inset(10)
make.width.equalTo(33)
make.height.equalTo(20)
}
typeLabel.snp.makeConstraints { make in
make.leading.equalTo(typeLabelBackgroud).inset(6)
make.top.equalTo(typeLabelBackgroud).inset(2)
make.width.equalTo(21)
make.height.equalTo(16)
}
timeLabel!.snp.makeConstraints { make in
make.top.equalTo(imageView).inset(8)
make.trailing.equalTo(imageView).inset(10)
}
titleLabel.snp.makeConstraints { make in
make.top.equalTo(imageView.snp.bottom).offset(8)
make.width.equalTo(140)
make.height.equalTo(42)
}
storeName.snp.makeConstraints { make in
make.top.equalTo(titleLabel.snp.bottom).offset(4)
make.width.equalTo(140)
make.height.equalTo(16)
}
heartImage.snp.makeConstraints { make in
make.top.equalTo(storeName.snp.bottom).offset(3)
make.width.height.equalTo(16)
}
heartCountLabel.snp.makeConstraints { make in
make.top.equalTo(storeName.snp.bottom).offset(3)
make.leading.equalTo(heartImage.snp.trailing).offset(5)
}
eyeImage.snp.makeConstraints { make in
make.leading.equalTo(heartCountLabel.snp.trailing).offset(13)
make.top.equalTo(storeName.snp.bottom).offset(3)
make.width.height.equalTo(16)
}
eyeCountLabel.snp.makeConstraints { make in
make.top.equalTo(storeName.snp.bottom).offset(3)
make.leading.equalTo(eyeImage.snp.trailing).offset(5)
}
}
}
public func configure(with model: Item?) {
//self.model! = model!
guard model != nil else {return}
if model!.type == "LIVE" {
imageView.kf.setImage(with: URL(string: model!.image!))
typeLabel.text = "LIVE"
typeLabelBackgroud.backgroundColor = .orange
titleLabel.text = String(model!.title!)
storeName.text = String(model!.store!)
heartCountLabel.text = String(model!.likeCount!)
eyeCountLabel.text = String(model!.playedCount!)
} else if model!.type == "RESERVED" {
imageView.kf.setImage(with: URL(string: model!.image!))
typeLabel.text = "예정"
typeLabelBackgroud.backgroundColor = Colors.primary()
titleLabel.text = String(model!.title!)
storeName.text = String(model!.store!)
heartCountLabel.text = String(model!.likeCount!)
eyeCountLabel.text = String(model!.playedCount!)
} else if model!.type == "VOD" {
imageView.kf.setImage(with: URL(string: model!.image!))
typeLabel.text = "VOD"
titleLabel.text = String(model!.title!)
typeLabelBackgroud.backgroundColor = Colors.vodBackgroud()
storeName.text = String(model!.store!)
heartCountLabel.text = String(model!.likeCount!)
eyeCountLabel.text = String(model!.playedCount!)
timeLabel?.text = "01:35:40"
}
}
}
The way I tried is let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout) ->
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: collectionViewFlowLayout.init()) .
The reuse problem did not occur, but it cannot be used because the scroll direction is changed.
You could solve your problem in two ways:
1 - reset your cell in cellForItemAt
Currently you call cell.setupViews(with: models![indexPath.item]) for each cell, which adds subviews to the cells. Since collectionView reuses cells, when scrolling you are getting cells which where used as all types (live, reserved, vod), that is why you see that "playLayer is added to all cells when scrolling up and down".
With this code you also add subviews each time the cell is reused, which is also not the best practice.
You could add an additional function to reset the cell and remove all subviews before adding new ones:
cell.subviews.forEach { $0.removeFromSuperview() }
(it is also better to add views to the cell.contentView)
2 - Create separate classes for different cell types
In cellFroItemAtyou could check for the type of the cell and return the required on. Each type will have a different ReuseIdentifier and playLayer will be added only to the type you need

Crashing: Thread 1: EXC_BAD_ACCESS when I set custom cell imageView

I tried a lot but I am not able to solve it. Following is the code that I have tried. Getting issue at
cell.userImageView.image = self.selectedPhotos[0] // Thread 1: EXC_BAD_ACCESS (code=2, address=0x1208e5520)
Line above are inside
func convertAssetsToImage(cell: UserProfilePhotosCell)
I use BSImagePicker to pick images from the gallery.
Here is the full code:
import UIKit
import BSImagePicker
import Photos
class UserProfileVC: BaseCollectionViewController {
// MARK: Properties
let userPhotoId = "userPhotoId"
var SelectedAssets = [PHAsset]()
var selectedPhotos = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
collectionView.backgroundColor = .white
collectionView.register(UserProfilePhotosCell.self, forCellWithReuseIdentifier: userPhotoId)
print("Did load once")
}
#objc func showCustomImagePicker(cell1: UserProfilePhotosCell) {
let imagePicker = ImagePickerController()
imagePicker.settings.selection.max = 1
imagePicker.settings.selection.unselectOnReachingMax = true
imagePicker.settings.fetch.assets.supportedMediaTypes = [.image]
imagePicker.albumButton.tintColor = UIColor.green
imagePicker.cancelButton.tintColor = UIColor.red
imagePicker.doneButton.tintColor = UIColor.purple
imagePicker.navigationBar.barTintColor = .black
imagePicker.settings.theme.backgroundColor = .black
imagePicker.settings.theme.selectionFillColor = UIColor.gray
imagePicker.settings.theme.selectionStrokeColor = UIColor.yellow
imagePicker.settings.theme.selectionShadowColor = UIColor.red
imagePicker.settings.theme.previewTitleAttributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 16),NSAttributedString.Key.foregroundColor: UIColor.white]
imagePicker.settings.theme.previewSubtitleAttributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 12),NSAttributedString.Key.foregroundColor: UIColor.white]
imagePicker.settings.theme.albumTitleAttributes = [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 18),NSAttributedString.Key.foregroundColor: UIColor.white]
imagePicker.settings.list.cellsPerRow = {(verticalSize: UIUserInterfaceSizeClass, horizontalSize: UIUserInterfaceSizeClass) -> Int in
switch (verticalSize, horizontalSize) {
case (.compact, .regular): // iPhone5-6 portrait
return 2
case (.compact, .compact): // iPhone5-6 landscape
return 2
case (.regular, .regular): // iPad portrait/landscape
return 3
default:
return 2
}
}
self.presentImagePicker(imagePicker, select: { (asset) in
print("Selected: \(asset)")
}, deselect: { (asset) in
print("Deselected: \(asset)")
}, cancel: { (assets) in
print("Canceled with selections: \(assets)")
}, finish: { (assets) in
print("Finished with selections: \(assets)")
print("Count of Assets: \(assets.count)")
self.SelectedAssets = assets
self.convertAssetsToImage(cell: cell1)
})
}
func convertAssetsToImage(cell: UserProfilePhotosCell) {
for asset in SelectedAssets {
let manager = PHImageManager.default()
let option = PHImageRequestOptions()
var thumbnail = UIImage()
option.isSynchronous = true
manager.requestImage(for: asset, targetSize: CGSize(width: 340, height: 365), contentMode: .aspectFit, options: option, resultHandler: {(result, info) -> Void in
thumbnail = result!
})
self.selectedPhotos.append(thumbnail)
}
DispatchQueue.main.async {
cell.userImageView.image = self.selectedPhotos[0]
print("Dispatch")
}
}
}
extension UserProfileVC: UICollectionViewDelegateFlowLayout {
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: userPhotoId, for: indexPath) as! UserProfilePhotosCell
cell.backgroundColor = .yellow
cell.userImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(showCustomImagePicker(cell1:))))
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return .init(width: view.frame.width, height: 500)
}
}
Custom Cell Code:
import UIKit
import BSImagePicker
import Photos
class UserProfilePhotosCell: UICollectionViewCell {
var userImageView: UIImageView = {
let iv = UIImageView()
iv.image = UIImage(named: "megan")
iv.contentMode = .scaleAspectFill
iv.layer.cornerRadius = 8
iv.clipsToBounds = true
iv.constrainHeight(constant: 200)
iv.backgroundColor = .red
iv.isUserInteractionEnabled = true
iv.translatesAutoresizingMaskIntoConstraints = false
return iv
}()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = .white
setupUI()
print("Did init once")
}
fileprivate func setupUI() {
addSubview(userImageView)
userImageView.topAnchor.constraint(equalTo: topAnchor).isActive = true
// userImageView.bottomAnchor.constraint(equalTo: bottomAnchor).isActive = true
userImageView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
userImageView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
I have tried also to pass array with images to UserProfilePhotosCell, and update userImageView.image inside didSet method, no luck, same error.
Thank you in advance for any help.

collectionviewcell pass data to relevant collectionview

I am using collectionview. In this collectionview I have a button and I have 2 different cells in it which is 2 different collectionviewcell. When I press the button I need to get text from its second cells. the second cell is register cell which contains username, email and password fields.
Here is code snippets.
This is LoginController
class LoginController: UIViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate, UICollectionViewDataSource {
******* I am taking of cell; If I do not do that then TextField returns nil *******
var registerController: RegisterControllerCell?
override func viewDidLoad() {
super.viewDidLoad()
UIApplication.shared.statusBarStyle = .lightContent
view.backgroundColor = UIColor.rgb(61, 91, 151)
******* and here is making cell is accessible *******
registerController = RegisterControllerCell()
setupComponents()
}
final func setupComponents() -> Void {
.... components set up here
}
******* this is the collectionview that should hold cells in it *******
lazy var collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let view = UICollectionView(frame: .zero, collectionViewLayout: layout)
view.register(LoginControllerCell.self, forCellWithReuseIdentifier: loginCellId)
view.register(RegisterControllerCell.self, forCellWithReuseIdentifier: registerCellId)
view.translatesAutoresizingMaskIntoConstraints = false
view.bounces = false
view.showsHorizontalScrollIndicator = false
view.isPagingEnabled = true
view.layer.cornerRadius = 8
view.layer.masksToBounds = true
view.backgroundColor = .white
view.delegate = self
view.dataSource = self
return view
}()
#objc func hideKeyboard(){
self.view.endEditing(true)
}
********* HERE IS PROBLEM STARTS... this is the button that should return text of textfield when clicking occurs. *********
let rlButton: UIButton = {
let btn = UIButton()
btn.translatesAutoresizingMaskIntoConstraints = false
btn.setTitle("LOGIN", for: .normal)
btn.layer.cornerRadius = 5
btn.layer.masksToBounds = true
btn.backgroundColor = UIColor.brown
btn.addTarget(self, action: #selector(handleClick), for: .touchUpInside)
return btn
}()
#objc func handleClick(){
switch buttonState {
case .register?:
registerUser()
break
case .login?:
print("login")
break
case .none:
print("none of them")
break
}
}
********* here is should return the value *********
func registerUser() -> Void {
******** this should return a text but it is nil every time ********
let username = registerController?.username.text
print(username)
}
// collectionView stuff
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
// let colors: [UIColor] = [.black, .green]
let colors: [colorEnumerations] = [.white, .white]
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: loginCellId, for: indexPath) as? LoginControllerCell else {
fatalError("unresolved cell id")
}
if indexPath.item == 1 {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: registerCellId, for: indexPath) as? RegisterControllerCell else {
fatalError("unresolved cell id")
}
return cell
}
cell.backgroundColor = colors[indexPath.item].value
return cell
}
}
and this is the RegisterCell
class RegisterControllerCell: BaseCell {
override func setupComponents() {
registerComponents()
}
final func registerComponents() {
.... components set up
}
let holder: UIView = {
let vw = UIView()
vw.backgroundColor = .white
vw.translatesAutoresizingMaskIntoConstraints = false
return vw
}()
let seperator: UIView = {
let spr = UIView()
spr.translatesAutoresizingMaskIntoConstraints = false
spr.layer.borderWidth = 0.5
spr.layer.borderColor = UIColor.gray.cgColor
spr.backgroundColor = UIColor.gray
return spr
}()
let seperator2: UIView = {
let spr = UIView()
spr.translatesAutoresizingMaskIntoConstraints = false
spr.layer.borderWidth = 0.5
spr.layer.borderColor = UIColor.gray.cgColor
spr.backgroundColor = UIColor.gray
return spr
}()
let seperator3: UIView = {
let spr = UIView()
spr.translatesAutoresizingMaskIntoConstraints = false
spr.layer.borderWidth = 0.5
spr.layer.borderColor = UIColor.gray.cgColor
spr.backgroundColor = UIColor.gray
return spr
}()
******** I need to get its and others texts ********
let username: UITextField = {
let input = UITextField()
input.translatesAutoresizingMaskIntoConstraints = false
input.placeholder = "Username"
return input
}()
let email: UITextField = {
let input = UITextField()
input.translatesAutoresizingMaskIntoConstraints = false
input.placeholder = "Email"
return input
}()
let password: UITextField = {
let input = UITextField()
input.translatesAutoresizingMaskIntoConstraints = false
input.placeholder = "Password"
input.isSecureTextEntry = true
return input
}()
}
Thanks for your helps guys, I really need that.
A little not: Textfield is not nil by the way, the nil thing is its text, it is every time returns nil.

UICollectionViewCell's UiTextField, overlapping in UICollectionViewController

I am trying to design a multistep sign-up menu. For this purpose I am using UICollectionViewController with screen size cells. In these cells, I have a UITextView to ask questions and a UITextField to collect the answers. I also have a Page object for passing in information from uicollectionviewcontroller upon setting.
The problem I'm having now is that after every 3rd page my textField input from 3 pages ago repeats, instead of showing the placeholder. I have noticed yet another problem, the cells seem to be instantiating just 3 times, and not 6 times for how many pages I have. The instantiation order is very odd too. At first it does it once, then upon button click, twice more, then never again.
How can fix this, I am really struggling with this and I have no idea what's going wrong.
This is my code:
import UIKit
class OnboardingPageViewCell: UICollectionViewCell{
override init(frame: CGRect) {
super.init(frame: frame)
print("made a page")
setupView()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var oboardingPage = NewOnboardingPage() {
didSet{
reload()
}
}
private var questionTextField: UITextView = {
var q = UITextView()
q.textColor = UIColor.white
q.textAlignment = .left
q.font = UIFont(name: "Avenir-Black", size: 25)
q.isEditable = true
q.isScrollEnabled = false
q.backgroundColor = UIColor.black
q.translatesAutoresizingMaskIntoConstraints = false
print("made aquestion field")
return q
}()
private var answerField : CustomTextField = {
let tf = CustomTextField.nameField
print("made an answer field")
return tf
}()
private func setupView(){
backgroundColor = UIColor.white
addSubview(questionTextField)
questionTextField.topAnchor.constraint(equalTo: topAnchor, constant: 120).isActive = true
questionTextField.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
questionTextField.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.90).isActive = true
questionTextField.heightAnchor.constraint(equalToConstant: 90).isActive = true
addSubview(answerField)
answerField.topAnchor.constraint(equalTo: questionTextField.bottomAnchor, constant: 20).isActive = true
answerField.leftAnchor.constraint(equalTo: leftAnchor).isActive = true
answerField.widthAnchor.constraint(equalTo: widthAnchor, multiplier: 0.90).isActive = true
answerField.heightAnchor.constraint(equalToConstant: 90).isActive = true
}
private func reload(){
questionTextField.text = oboardingPage.question
answerField.placeholder = oboardingPage.answerField
}
}
class NewOnboardingPage {
var question : String?
var answerField : String?
}
import UIKit
class SignUpController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
private let cellId = "cellId"
private var pages = [NewOnboardingPage]()
override func viewDidLoad() {
super .viewDidLoad()
setupSignUpControllerView()
addPages()
}
private func addPages(){
let namePage = NewOnboardingPage()
namePage.question = "What's your name?"
namePage.answerField = "What's your name?"
pages.append(namePage)
let birthDayPage = NewOnboardingPage()
birthDayPage.question = "When's your birthdate?"
birthDayPage.answerField = "When's your birthdate?"
pages.append(birthDayPage)
let userNamePage = NewOnboardingPage()
userNamePage.question = "Choose a user name."
userNamePage.answerField = "Choose a user name."
pages.append(userNamePage)
let passWordPage = NewOnboardingPage()
passWordPage.question = "Set a password"
passWordPage.answerField = "Set a password"
pages.append(passWordPage)
let emailAuthPage = NewOnboardingPage()
emailAuthPage.question = "What's your email?"
emailAuthPage.answerField = "What's your email?"
pages.append(emailAuthPage)
let phoneNumberPage = NewOnboardingPage()
phoneNumberPage.question = "What's your phone number?"
phoneNumberPage.answerField = "What's your phone number?"
pages.append(phoneNumberPage)
}
private func setupSignUpControllerView(){
collectionView?.backgroundColor = .white
collectionView?.register(OnboardingPageViewCell.self, forCellWithReuseIdentifier: cellId)
collectionView?.isPagingEnabled = true
collectionView?.isScrollEnabled = true
if let layout = collectionView?.collectionViewLayout as? UICollectionViewFlowLayout {
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = 0
}
view.addSubview(nextButton)
nextButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 400).isActive = true
nextButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
nextButton.widthAnchor.constraint(equalToConstant: 250).isActive = true
nextButton.heightAnchor.constraint(equalToConstant: 60).isActive = true
}
private let nextButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor.RED
button.setTitle("next", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont(name: "Avenir-Black", size: 25)
button.layer.cornerRadius = 30
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget(self, action: #selector(turnNextPage), for: .touchUpInside)
return button
}()
#objc private func turnNextPage() {
let visibleItems: NSArray = collectionView?.indexPathsForVisibleItems as! NSArray
let currentItem: IndexPath = visibleItems.object(at: 0) as! IndexPath
let nextItem: IndexPath = IndexPath(item: currentItem.item + 1, section: 0)
if nextItem.row < pages.count {
collectionView?.scrollToItem(at: nextItem, at: .left, animated: true)
}
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return pages.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! OnboardingPageViewCell
cell.oboardingPage = pages[indexPath.item]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: view.frame.height)
}
}
import UIKit
class CustomTextField: UITextField, UITextFieldDelegate {
convenience init() {
self.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
self.allowsEditingTextAttributes = false
self.autocorrectionType = .no
self.tintColor = UIColor.RED
self.translatesAutoresizingMaskIntoConstraints = false
}
override func willMove(toSuperview newSuperview: UIView?) {
addTarget(self, action: #selector(editingChanged), for: .editingChanged)
editingChanged(self)
}
#objc func editingChanged(_ textField: UITextField) {
guard let text = textField.text else { return }
textField.text = String(text.prefix(30))
}
override func selectionRects(for range: UITextRange) -> [Any] {
return []
}
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(paste(_:)) ||
action == #selector(cut(_:)) ||
action == #selector(copy(_:)) ||
action == #selector(select(_:)) ||
action == #selector(selectAll(_:)){
return false
}
return super.canPerformAction(action, withSender: sender)
}
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! OnboardingPageViewCell
cell.answerField.text = nil
cell.oboardingPage = pages[indexPath.item]
return cell
}
1- textFeild showing same data instead of placeholder bacause of cell dequeuing so you must hook these properties and clear their content in cellForRowAt
2- Instantiation is 3 not 6 aslo cell dequeuing
Solve:
Add two properties to your model NewOnboardingPage name them currentQuestion and currentAnswer and as the user inputs and scroll to next page save them in the modelarray that you should make global to be accessed indside cell and outside set these values to the textfeild and textView as you scroll in cellForRowAt

UITableView scroll freezes when scrolling fast

I am using custom tableview cells in a tableview. The data is loaded from the server and height calculation of that particular cell is done inside the cell only.
<iframe width="560" height="315" src="https://www.youtube.com/embed/h-FjYkSBuNM" frameborder="0" allowfullscreen></iframe>
I am attaching the code for tableview cell for row at indexpath, custom cell method and code for get request.
class QuesAnsFeedTableViewCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setup()
}
override func layoutSubviews() {
super.layoutSubviews()
self.questionLabel.preferredMaxLayoutWidth = questionLabel.frame.width
self.answerLabel.preferredMaxLayoutWidth = answerLabel.frame.width
super.layoutSubviews()
}
func setup(){
topLeftLabel = UILabel()
topLeftLabel.font = UIFont(name: regularFont, size: 12)
topLeftLabel.text = "Yesterday"
topLeftLabel.textColor = CommonFunctions.hexStringToUIColor(hex: lightGray)
topRightLabel = UILabel()
topRightLabel.font = UIFont(name: regularFont, size: 12)
topRightLabel.textColor = CommonFunctions.hexStringToUIColor(hex: lightGray)
topRightLabel.text = ""
topRightLabel.textAlignment = .right
questionLabel = UILabel()
questionLabel.font = UIFont(name: mediumFont, size: 14)
questionLabel.text = "First Ques Comes Here and ans will be below this question"
questionLabel.numberOfLines = 0
questionLabel.lineBreakMode = .byWordWrapping
userImageView = UIImageView()
userImageView.backgroundColor = .purple
userImageView.layer.cornerRadius = CGFloat(sidePadding)/2
userImageView.clipsToBounds = true
userNameLabel = UILabel()
userNameLabel.font = UIFont(name: regularFont, size: 12)
userNameLabel.text = ""
answerLabel = UILabel()
answerLabel.font = UIFont(name: regularFont, size: 14)
answerLabel.text = ""
answerLabel.numberOfLines = 0
answerLabel.lineBreakMode = .byWordWrapping
viewOtherAnswerLabel = UILabel()
viewOtherAnswerLabel.font = UIFont(name: mediumFont, size: 12)
viewOtherAnswerLabel.text = ""
viewOtherAnswerLabel.textAlignment = .center
viewOtherAnswerLabel.textColor = CommonFunctions.hexStringToUIColor(hex: lightGray)
writeAnswerLabel = UILabel()
writeAnswerLabel.font = UIFont(name: mediumFont, size: 14)
writeAnswerLabel.backgroundColor = CommonFunctions.hexStringToUIColor(hex: crispBlue)
writeAnswerLabel.text = "Write Answer"
writeAnswerLabel.textAlignment = .center
writeAnswerLabel.textColor = .white
tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tappedCell(sender:)))
tapGesture.numberOfTapsRequired = 1
self.addGestureRecognizer(tapGesture)
// self.addSubview(likeButton)
// self.addSubview(descriptionLabel)
}
func updateData(data:NSDictionary) -> CGFloat{
if let viewCount = data["vc"] {
topRightLabel.text = "\(viewCount) read"
}
if let ques = data["q"] as? String{
topLeftLabel.frame = CGRect(x:sidePadding/2, y: 2*sidePaddingForCollectionCells, width: screenWidth/2-sidePadding, height: Int(CommonFunctions.calculateHeight(inString: topLeftLabel.text!, forFont: topLeftLabel.font, andWidthOfLabel: CGFloat(screenWidth/2))))
topRightLabel.frame = CGRect(x: screenWidth/2, y: 2*sidePaddingForCollectionCells, width: screenWidth/2-sidePadding/2, height: Int(topLeftLabel.frame.height))
let newHeight = CommonFunctions.calculateHeight(inString: ques,forFont:questionLabel.font,andWidthOfLabel:questionLabel.frame.width)
questionLabel.frame = CGRect(x:sidePadding/2 ,y: Int(topLeftLabel.frame.maxY)+sidePaddingForCollectionCells,width: screenWidth - sidePadding, height: Int(ceil(Float(newHeight))))
questionLabel.text = ques
self.addSubview(topLeftLabel)
self.addSubview(topRightLabel)
self.addSubview(questionLabel)
// questionLabel.attributedText = CommonFunctions.justifiedText(string: ques)
}
if let user = data.object(forKey: "user") as? NSDictionary{
if let usrName = user.value(forKey: "name"){
userNameLabel.text = "\(usrName)"
}
if let imgLink = user["image"] as? String{
if let url = URL(string: imgLink){
userImageView.sd_setImage(with: url,placeholderImage:#imageLiteral(resourceName: "placeholderImage"))
}
}
}
if let otherAnswer = data.value(forKey: "cc") {
viewOtherAnswerLabel.text = "View Other Answer \(otherAnswer)"
}
if let ans = data.value(forKey: "comt") as? String{
answered = true
userImageView.frame = CGRect(x: sidePadding/2, y: Int(questionLabel.frame.maxY)+2*sidePaddingForCollectionCells, width: sidePadding, height: sidePadding)
userNameLabel.frame = CGRect(x: 3*sidePadding/2+2*sidePaddingForCollectionCells, y:Int(questionLabel.frame.maxY)+sidePaddingForCollectionCells, width: screenWidth-2*sidePadding, height: Int(topLeftLabel.frame.height))
let newHeight = CommonFunctions.calculateHeight(inString: ans,forFont:answerLabel.font,andWidthOfLabel:answerLabel.frame.width)
let frame = CGRect(x: 3*sidePadding/2+2*sidePaddingForCollectionCells, y:Int(userNameLabel.frame.maxY) + sidePaddingForCollectionCells, width: screenWidth-2*sidePadding-2*sidePaddingForCollectionCells, height: Int(ceil(Float(newHeight))))
answerLabel.frame = frame
answerLabel.text = ans
viewOtherAnswerLabel.frame = CGRect(x: 0, y: Int(answerLabel.frame.maxY)+2*sidePaddingForCollectionCells, width: screenWidth, height: 2*sidePadding/3)
self.addSubview(userImageView)
self.addSubview(userNameLabel)
self.addSubview(answerLabel)
self.addSubview(viewOtherAnswerLabel)
writeAnswerLabel.removeFromSuperview()
return viewOtherAnswerLabel.frame.maxY
}
else{
answered = false
writeAnswerLabel.frame = CGRect(x: 0, y:Int(questionLabel.frame.maxY) + 2*sidePaddingForCollectionCells, width: screenWidth, height: sidePadding)
self.addSubview(writeAnswerLabel)
userImageView.removeFromSuperview()
userNameLabel.removeFromSuperview()
answerLabel.removeFromSuperview()
viewOtherAnswerLabel.removeFromSuperview()
return writeAnswerLabel.frame.maxY
}
}
TableView Code
class GenericView: UIView ,UITableViewDelegate,UITableViewDataSource {
var tableView:UITableView!
var viewFrame = CGRect()
var parentView = ""
var discussViewHeight = [Int:CGFloat]()
var nextUrlPath = ""
var currentUrlPath = ""
private var sliderLabelsText = ["Favourites","Sign In"]
private var tableBlocks = [NSDictionary]()
override init(frame: CGRect) {
super.init(frame: frame)
viewFrame = frame
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
if viewFrame != CGRect() {
setup()
}
}
public func updateView(){
viewFrame = self.frame
tableView.frame = (viewFrame)
getRequest()
}
func getRequest(){
currentUrlPath = baseUrl+nextUrlPath
if parentView == discussView{
// let url = baseUrl + nextUrlPath
Alamofire.request(currentUrlPath).responseJSON { response in
if let dict = response.result.value as? [String:AnyObject]{
if (dict["msc"]) as? String == "700", let blocks = dict["blocks"] as? NSArray{
self.nextUrlPath = (dict["next"] as? String ?? "")
for block in blocks{
if let blk = block as? NSDictionary{
if blk.value(forKey: "ty") as? String == "qa"{
self.tableBlocks.append(blk)
}
appDelegate.tableBlocks.append(blk)
}
}
DispatchQueue.main.async(execute: { () -> Void in
self.refreshControl.endRefreshing()
self.tableView.reloadData()
})
}
else{
DispatchQueue.main.async(execute: { () -> Void in
self.currentUrlPath = ""
self.getRequest()
})
}
}
}
return
}
}
func setup(){
backgroundColor = UIColor.white
tableView = UITableView(frame: viewFrame, style: .grouped)
tableView.delegate = self
tableView.dataSource = self
self.addSubview(tableView)
registerCells()
}
//MARK: TableView DataSource Methods
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if parentView == discussView{
return 1
}
return 0
}
func numberOfSections(in tableView: UITableView) -> Int {
if parentView == discussView{
return tableBlocks.count
}
return 0
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (parentView == discussView){
var cell:QuesAnsFeedTableViewCell? = tableView.dequeueReusableCell(withIdentifier: quesAnsFeedViewCellIdentifier, for: indexPath) as? QuesAnsFeedTableViewCell
if (cell == nil){
cell = QuesAnsFeedTableViewCell(style: .default, reuseIdentifier: quesAnsFeedViewCellIdentifier)
}
cell?.selectionStyle = .none
discussViewHeight[indexPath.section] = (cell?.updateData(data: tableBlocks[indexPath.section]))!
cell?.setNeedsLayout()
cell?.layoutIfNeeded()
return cell!
}
return UITableViewCell()
}
//MARK: TableView Delegate Methods
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if parentView == discussView{
return discussViewHeight[indexPath.section] ?? 0
}
return 0
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if parentView == discussView{
return sectionHeaderView
}
return UIView()
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if parentView == discussView && indexPath.section+5 > tableBlocks.count{
if currentUrlPath != baseUrl + nextUrlPath{
getRequest()
}
}
}
}
I have deleted some code from classes just to keep the size of question small.
The call for next fetch will depend on the indexpath of cell which is currently being displayed and the function which fetches the content from server will be getRequest().
Any help is greatly appreciated

Resources