Swift UICollectionView in UITableViewCell indexPath error - swift

I am implementing a collection view cell inside a table view cell but strange things are happening with the collection view indexPath.
The numberOfItemsinSection gets fired 3 times and then cellForItemAt only once when numberOfitemsInSection is 2. I expect one section and 2 cells for the collection view.
Here is the source data:
[["myDomain.jpg1", "myDomain.jpg2"]]
Here is the console output from the following code:
"number of items in section: 2"
"number of items in section: 2"
"number of items in section: 2"
"cell for item at [0, 0]"
"indexPath.section: 0"
"indexPath.row: 0"
"myDomain.jpg1"
Here is my view controller:
class WishListsViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var tableView: UITableView = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
tableView.register(WishListsCell.self, forCellReuseIdentifier: cellId)
self.view.addSubview(tableView)
}
func numberOfSections(in tableView: UITableView) -> Int {
return wishLists.count // 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! WishListsCell
return cell
}
Here is my table view cell:
class WishListsCell: UITableViewCell {
var collectionView: UICollectionView!
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
layout.itemSize = CGSize(width: screenWidth, height: (screenWidth / 4))
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 0
layout.estimatedItemSize.height = (screenWidth / 4)
layout.estimatedItemSize.width = screenWidth
collectionView = UICollectionView(frame: contentView.frame, collectionViewLayout: layout)
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(WishListsCollectionViewCell.self, forCellWithReuseIdentifier: cellId)
self.contentView.addSubview(collectionView)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension WishListsCell: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
let items = wishListUrls[section]
debugPrint("number of items in section: \(items.count)")
return items.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! WishListsCollectionViewCell
debugPrint("cell for item at \(indexPath)")
debugPrint("indexPath.section: \(indexPath.section)")
debugPrint("indexPath.row: \(indexPath.row)")
if let imageUrl = wishListUrls[indexPath.section][indexPath.row] as String! {
debugPrint(imageUrl)

I don't see an implementation of numberOfSections(in collectionView) in your WishListsCell extension.
I can't be certain based on the snippets you've posted, but it might look something like.
func numberOfSections(in collectionView: UICollectionView) -> Int {
return wishListUrls.count
}

Ultimately the chief problem came down to loading my data from 5 Alamofire requests as the master and detail is not yet available to me as single request from the API. tableView.reloadData() seems to fire repeatedly until I explicitly fire it in the first Alamofire completion. When I fake the detail data as a local dictionary it seems to work much better.
Apart from that, I implemented it like this Swift - how to open another viewcontroller with CollectionViewCell inside UITableViewCell
The only change was that I have multiple sections each with one row in my table cell so I made collectionView.tag use indexPath.section instead of indexPath.row.
I also used https://ashfurrow.com/blog/putting-a-uicollectionview-in-a-uitableviewcell-in-swift/
and this
https://www.thorntech.com/2015/08/want-your-swift-app-to-scroll-in-two-directions-like-netflix-heres-how/

Related

didSelectItemAt from collectionView not getting called when the collectionView is inside a UITableView row

I have a tableView to feature searches. The second row (indexPath.row = 1) has a UICollectionView inside to display elements horizontally.
As these UICollectionView cells will be users, I want to detect clicks on them, which I cannot achieve. I guess there might be something I don't cover since the collectionView is inside a row of a UITableView. I attach an image where the red squares are the collectionView cells inside a row of a table.
Inside my tableView I have:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! RecentUserCell
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: recentTextReuseIdentifier, for: indexPath) as! RecentTextCell
cell.viewModel = RecentTextCellViewModel(recentText: recentSearchedText[indexPath.row - 1])
cell.selectionStyle = .none
return cell
}
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! RecentUserCell
return cell
}
}
And the RecentUserCell, has a collectionView inside. The last method, didSelectItemAt, is not getting called, which means I cannot access to a particular user
private let identifier = "collectionCell"
class RecentUserCell: UITableViewCell {
//MARK: - Properties
private var users = [User]()
public let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let collectionView = UICollectionView(frame: CGRect(), collectionViewLayout: layout)
return collectionView
}()
//MARK: - Lifecycle
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
fetchUsers()
collectionView.delegate = self
collectionView.dataSource = self
collectionView.isUserInteractionEnabled = true
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: identifier)
collectionView.showsHorizontalScrollIndicator = false
addSubview(collectionView)
collectionView.anchor(top: topAnchor, left: leftAnchor, bottom: bottomAnchor, right: rightAnchor)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//MARK: - API
func fetchUsers() {
UserService.fetchUsers { users in
self.users = users
self.collectionView.reloadData()
}
}
}
//MARK: - UICollectionViewDataSource
extension RecentUserCell: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return users.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: identifier, for: indexPath) //as! UserCollectionViewCell
//cell.delegate = self
cell.backgroundColor = .red
//cell.viewModel = UserCellViewModel(user: users[indexPath.row])
return cell
}
}
//MARK: - UICollectionViewDelegateFlowLayout
extension RecentUserCell: UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 70, height: 80)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Selected item at \(indexPath.row)")
}
}
Anyone has an idea of how I can get this method called or what strategy I could use to detect clicks on this UICollectionViewCells?
Your issue is related to adding subviews directly to UITableViewCell and not using contentView. You can read more about UITableViewCell internals here

How can l put TableView inside CollectionViewCell?

I have a tableView with several cells (created by MVVM-architecture).
In ViewController I fill my tableView like this:
tbv.registerCells(
withModels:
FirstViewModel.self,
SecondViewModel.self,
ThirdViewModel.self)
My task is to put my TableView in one cell of CollectionView. I thought l have to create CollectionView in my ViewController, after it create CollectionViewCell and CollectionCellViewModel, but how to do it exactly I don't understand.
If you know, how to make it, help.
How I have several tableviews in collection views in one of my apps. First I have a view controller in which I build my collection view. As usually proposed in the new design guidelines, I have the Collection View delegate and data source in an extension of this view controller.
In your view controller you define a delegate and data source for your table view. Preferably, this is a different class. I would not have the tableview data source and delegate also in the same view controller as your collection view.
class WorkoutSettingsViewController: UIViewController, LoadWorkoutSettings {
//MARK: - Properties
//Used variables
//Used constants
private let settingsDelegate = SettingsTableViewDelegate()
The extension would then look like this.
extension WorkoutSettingsViewController: UICollectionViewDataSource, UICollectionViewDelegate {
func numberOfSections(in collectionView: UICollectionView) -> Int {
//Whatever sets your sections
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
//Whatever sets your rows per section
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Workout Settings", for: indexPath) as! SettingsCollectionViewCell
settingsDelegate.workoutTitleLabel = [countdown, mainView, spokenMessage]
settingsDelegate.mainContentLabel = getSettingsContent()
cell.settingsTableView.delegate = settingsDelegate
cell.settingsTableView.dataSource = settingsDelegate
cell.settingsTableView.reloadData()
return cell
}
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
//Whatever you need as header or footer
}
The delegate does exactly what you would like the table view data source and delegate to do.
class SettingsTableViewDelegate: NSObject, UITableViewDataSource, UITableViewDelegate {
//MARK: - Properties
//Used variables
var workoutTitleLabel = [String]()
var mainContentLabel = [String]()
var selectedSetting: ((Int) -> ())? = .none
private var secondaryContentLabel = [String]()
//Used constants
private let onTitle = NSLocalizedString("ON", comment: "Localized on title")
private let offTitle = NSLocalizedString("OFF", comment: "Localized off title")
private let fontColorBlack = UIColor(red: 20.0/255.0, green: 20.0/255.0, blue: 19.0/255.0, alpha: 1.0)
private let fontColorRed = UIColor(red: 255.0/255.0, green: 96.0/255.0, blue: 89.0/255.0, alpha: 1.0)
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
workoutTitleLabel.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Settings Cell") as! WorkoutTableViewCell
cell.workoutTitle.text = workoutTitleLabel[indexPath.row]
cell.mainContent.text = mainContentLabel[indexPath.row]
cell.secondaryContent.text = ""
(mainContentLabel[indexPath.row] == offTitle) ? (cell.mainContent.textColor = fontColorRed) : (cell.mainContent.textColor = fontColorBlack)
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
selectedSetting?(indexPath.row)
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
61
}
}
Your collection view cell should look like this.
class SettingsCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var settingsTableView: UITableView!
}
This should then work. If you need to have a callback from the table view delegate / data source to your view controller managing your collection view, you can use a closure. In the example table view delegate the closure is called selectedSettings. In your view controller in viewDidLoad you define the call back for instance like this:
override func viewDidLoad() {
super.viewDidLoad()
settingsDelegate.selectedSetting = { [unowned self] selection in
startSettingsMenu(for: selection)
}
}
The result looks like this.
Kind regards,
MacUserT
In Tableview each row you can load UITableViewCell with pass collectionviewdata
//View Controller
var collectionView1Data = ["cell1", "cell2"]
var collectionView2Data = ["cell1", "cell2"]
//UITableviewDelegate Datasource
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//.....
if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellID") as? TableviewCell
cell.collectionData = collectionView1Data /// Collectionviewdata
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "CellID") as? TableviewCell
cell.collectionData = collectionView2Data
return cell
}
}
==============================
Each Tableviewcell contains CollectionView
//UITableViewCell
class TableviewCell: UITableViewCell {
#IBOutlet weak var collectionView: UICollectionView!
var collectionData: [String]? {
didSet {
guard collectionData != nil else {
return
}
collectionView.reloadData()
}
}
override func awakeFromNib() {
super.awakeFromNib()
collectionView.register(UINib(nibName: "collectionViewCell", bundle: nil), forCellWithReuseIdentifier: "collectionViewCell")
collectionView.dataSource = self
collectionView.delegate = self
}
}
extension TableviewCell: UICollectionViewDataSource, UICollectionViewDelegate,UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
collectionData.count ?? 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as? collectionViewCell
cell...
return cell
}
}

TableView inside a CollectionView crashes the app

I am building a multi screen app which uses a UICollection view to navigate between UIViewControllers. The left one is green and the right is red. Swiping left or right brings you to the ViewController. It works, but when I add a TableViewController to the green one, the app crashes. I added all outlets. It says:
SwipeViewController[11639:3937203] Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value: file SwipeViewController/GreenViewController.swift, line 21
which points to tableViewI.delegate = self.
Here is the CollectionView code:
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
#IBOutlet var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
collectionView.backgroundColor = .yellow
collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "collectionViewCell")
collectionView.isPagingEnabled = true
collectionView.scrollToItem(at: IndexPath(item: 1, section: 0), at: .centeredVertically, animated: false)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath)
//cell.backgroundColor = indexPath.item % 2 == 0 ? .purple : cell.backgroundColor
switch indexPath.row {
case 0:
self.addChild(GreenViewController())
cell.contentView.addSubview(GreenViewController().view)
case 1:
self.addChild(RedViewController())
cell.contentView.addSubview(RedViewController().view)
default:
print("nothing")
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: self.view.frame.width, height: self.view.frame.height)
}
And here the green ViewController containing the tableView:
class GreenViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableViewI: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = .green
tableViewI.delegate = self
tableViewI.dataSource = self
tableViewI.register(UINib.init(nibName: "cellID", bundle: nil), forCellReuseIdentifier: "cellID")
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellID") as! TableViewCell
cell.backgroundColor = .blue
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
The problem is how you are creating the object of GreenViewController class.
You must load it from the storyboard instead of just creating it from the init method of GreenViewController. Otherwise, outlet properties will be nil.
let vc = storyboard?.instantiateViewController(withIdentifier: "yourIdentifier") as! GreenViewController
I think the problem is in reference to GreenViewController
try to save viewController as property before adding it as a child.
possible problem is that your greenViewController could be deallocated before you access it.
let greenViewController = GreenViewController()
let redViewController = RedViewController()
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath)
//cell.backgroundColor = indexPath.item % 2 == 0 ? .purple : cell.backgroundColor
switch indexPath.row {
case 0:
self.addChild(greenViewController)
cell.contentView.addSubview(greenViewController.view)
case 1:
self.addChild(redViewController)
cell.contentView.addSubview(redViewController.view)
default:
print("nothing")
}
return cell
}

Swift UICollectionView with Horizontal Scrolling and Layout Each Section Left to Right on Own Row

I would like to have UICollectionView with Horizontal Scrolling and Layout each section on it's own row from left to right.
Currently my CollectionView with Horizontal Scrolling has a vertical layout for each section.
Ideally I would like the following layout with horizontal scrolling:
So my question is how can I have horizontal scrolling on my UICollectionView where each horizontal row from left to right is laid out in one row. (see second diagram) Each section would occupy a different row.
Also each row should scroll horizontally at the same time (like a spreadsheet).
You have to combine Collection-view and Tableview for having horizontal scrolling on UICollectionView where each horizontal row from left to right is laid out in one row. Each section would occupy a different row.
class DesignCollectionViewCell: UICollectionViewCell {
#IBOutlet weak var lbltext: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
}
class DesignTableViewCell: UITableViewCell {
#IBOutlet weak var designCollectionView: UICollectionView!
var numberofScection = Int()
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.designCollectionView.register(UINib(nibName: "DesignCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "DesignCollectionViewCell")
self.designCollectionView.dataSource = self
self.designCollectionView.delegate = self
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
self.designCollectionView.collectionViewLayout = layout
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
extension DesignTableViewCell: UICollectionViewDataSource,UICollectionViewDelegate,UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 7
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DesignCollectionViewCell", for: indexPath) as! DesignCollectionViewCell
cell.lbltext.text = "section \(self.numberofScection) indexpath \(indexPath.row)"
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: 170, height: 100.0)
}
}
class ViewController: UIViewController {
#IBOutlet weak var designTableViewCell: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.designTableViewCell.register(UINib(nibName: "DesignTableViewCell", bundle: nil), forCellReuseIdentifier: "DesignTableViewCell")
self.designTableViewCell.dataSource = self
self.designTableViewCell.delegate = self
}
}
extension ViewController: UITableViewDataSource,UITableViewDelegate{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "DesignTableViewCell") as! DesignTableViewCell
cell.designCollectionView.reloadData()
cell.numberofScection = indexPath.row
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 110
}
}

Reliably using UICollectionView indexPath to access dictionary keys?

I'm trying to use the current CollectionViewcell's IndexPath to access data from a dictionary. The dictionary's keys are of type Int.
This CollectionView has "full page" cells, meaning that each cell takes up the full view area where I am using horizontal scrolling (paging enabled) to navigate between cells.
The dictionary is :
var dataFromServer: [Int: [VillageFestival]]?
Each CollectionViewCell has a TableView inside it, where I plan to have a variable number of rows, depending on how many items there are in [VillageFestival]
However, in CollectionView cellForItemAt indexPath the behaviour of the method is causing some trouble, as printing indexPath.item or setting it as my navigationController's title, returns odd but "understandable" results given how I think dequeueReusableCell works?...
Example: the current index is 0. When I scroll to the right, the current index is now 2. If I navigate to page 6 and then one page back, the current index indicates 3.
I have changed my dictionary keys from Date to String and now to Int, in an attempt to simplify logic.. But the problem persists.
I am using a global pageIndex: Int that is being updated inside CollectionView cellForItemAt
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
pageIndex = indexPath.item
self.navigationController?.navigationBar.topItem?.title = String(pageIndex)
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! CollectionViewCell
// CollectionViewCell resize to CollectionView Bounds
cell.tableViewCellOffsets = (UIApplication.shared.statusBarFrame.size.height + (self.navigationController?.navigationBar.frame.height ?? 0.0) , self.tabBarController?.tabBar.frame.height ?? 0)
return cell
}
In Tableview numberOfRowsInSection, I'm using pageIndex to access the dictionary values.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let festivals = dataFromServer?[pageIndex] else {return 0}
return festivals.count
}
With my current code, the app displays 0 rows for some pages and 1 row for others. My guess is that the collectionView's cellForItemAt is called before (also possibly after?) the tableView's methods and this makes using a global pageIndex unreliable...
Thanks!
Try this playground, it might help you:
import UIKit
import PlaygroundSupport
class Cell: UICollectionViewCell, UITableViewDataSource {
var data: [Int]! = [] {
didSet {
tableView.reloadData()
}
}
private let tableView: UITableView
override init(frame: CGRect) {
tableView = UITableView(frame: .zero, style: .plain)
super.init(frame: frame)
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
tableView.dataSource = self
tableView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(tableView)
NSLayoutConstraint.activate([
tableView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
tableView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
tableView.topAnchor.constraint(equalTo: contentView.topAnchor),
tableView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor)
])
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = String(data[indexPath.item])
return cell
}
}
class VC: UICollectionViewController {
let data = [
0: [1, 2, 3, 4, 5],
1: [6, 4],
2: [5, 5, 5, 5, 6],
3: [9, 9, 8, 4, 5, 5, 5]
]
override init(collectionViewLayout layout: UICollectionViewLayout) {
super.init(collectionViewLayout: layout)
collectionView.isPagingEnabled = true
collectionView.register(Cell.self, forCellWithReuseIdentifier: "Cell")
}
required init?(coder aDecoder: NSCoder) {
fatalError()
}
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
override func viewDidLayoutSubviews() {
(collectionViewLayout as? UICollectionViewFlowLayout)?.itemSize = collectionView.bounds.size
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! Cell
cell.data = data[indexPath.item]
return cell
}
}
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
PlaygroundPage.current.liveView = VC(collectionViewLayout: layout)