so i have a question regarding instantiating a new vc when i click on a tableviewcell. Since i have separated my delegate and datasource into separate classes i no longer inherit from ViewController. What are my alternatives to creating a new VC from my delegate class? The other potential problem is that my show array is created in my other separate myDataSource class. How would i pass that to MyDelegate class?
class ViewController: UITableViewController {
let aDataSource = MyDataSource()
let aDelegate = MyDelegate()
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = aDataSource
tableView.delegate = aDelegate
}
}
class MyDelegate: NSObject, UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// i want to do the following but it doesn't work since i'm not inheriting from viewcontroller i guess.
guard let vc = storyboard?.instantiateViewController(withIdentifier: "detailedShowViewController") as? DetailedShowViewController else {
fatalError("Unable to instantiate view controller.")
}
let item = shows[indexPath.row]
vc.show = item
navigationController?.pushViewController(vc, animated: true)
}
}
You can create a delegate and let your view controller inherit this delegate to handle the callback:
protocol MyViewControllerDelegate {
func didSelectItemAt(_ indexPath: IndexPath)
}
Create a new property such as weak var myVCDelegate: MyViewControllerDelegate? in your MyDelegate class.
Let your view controller inherit it and assign itself to the delegate from MyDelegate (or inject it into the class)
// In ViewController
aDelegate.myVCDelegate = self
// In MyDelegate class
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// Do some stuff
// Pass the position of the item.
myVCDelegate?.didSelectItemAt(indexPath)
}
So, when you select a cell, just call the function to pass the indexPath to the view controller then you will be able to get the item by the indexPath from your data source.
I have a table view that its cells have a button in themselves and these buttons should open a view with an unique id. So I need to passing an argument to my buttons but with addTarget property I just can call function without any parameter.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
...
cell.editButton.addTarget(self, action: #selector(goToEdit(id:)), for: .touchUpInside)
}
func goToEdit(id: String) {
let edit = EditAdViewController(editingAdId: id)
self.navigationController?.pushViewController(edit, animated: true)
}
Is there any way to refer an action with some parameters to a button? Thanks everyone :)
You can try adding delegate functions to your custom UITableViewCell.
For example, I have a button inside this custom tableViewCell:
PickupTableViewCell.swift
import UIKit
protocol PickupTableViewCellDelegate: NSObjectProtocol {
func pickupTableViewCell(userDidTapPickup pickup: Pickup, pickupTableViewCell: PickupTableViewCell)
}
class PickupTableViewCell: UITableViewCell {
// MARK: - Properties
#IBOutlet private weak var label_UserFullName: UILabel!
....
// MARK: - Functions
// MARK: IBAction
#IBAction func pickup(_ sender: Any) {
self.delegate?.pickupTableViewCell(userDidTapPickup: self.pickup, pickupTableViewCell: self)
}
}
Then in I conform my controller via the UITableViewDataSource (cellForRow) and of course implement the delegate function of my tableViewCell.
HomeViewController.swift
// MARK: - UITableViewDataSource
extension HomeViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let pickupTVC = tableView.dequeueReusableCell(withIdentifier: R.reuseIdentifier.pickupTableViewCell)!
pickupTVC.delegate = self
pickupTVC.pickup = self.pickups[indexPath.section]
return pickupTVC
}
}
// MARK: - PickupTableViewCellDelegate
extension HomeViewController: PickupTableViewCellDelegate {
func pickupTableViewCell(userDidTapPickup pickup: Pickup, pickupTableViewCell: PickupTableViewCell) {
// Do something
}
}
Maybe you can try to link your button to a #IBAction and use params[indexPath.row].
To get the indexPath:
var cell = sender.superview() as? UITableViewCell
var indexPath: IndexPath? = yourTableView.indexPath(for: cell!)
How i can to create heir of UITableView class that will contain delegate and dataSource methods? I don't want to have dataSource and delegate methods in my ViewController.
You need to create another class for the purpose but first let's see how the ViewController will be.
As you can see the code is sort of self explanatory, I have created a custom class called TableViewDelegate that will be set as a delegate and dataSource of the tableView.
We are passing to TableViewDelegate, the data to be shown in the tableView, and function named didSelectRow that will be called by TableViewDelegate once a row is selected.
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
// data source
var data = [1, 2, 3, 4]
// delegate
var tableViewDelegate: TableViewDelegate?
override func viewDidLoad() {
super.viewDidLoad()
// creating the delegate object and passing the data
tableViewDelegate = TableViewDelegate(data: data)
// passing a function to the delegate object
tableViewDelegate?.didSelectRow = didSelectRow
// setting the delegate object to tableView
tableView.delegate = tableViewDelegate
tableView.dataSource = tableViewDelegate
}
// a function that will be called by the delegate object
// when a row is selected
func didSelectRow(dataItem: Int, cell: UITableViewCell) {
let alert = UIAlertController(title: "Info", message: "\(dataItem) was selected.", preferredStyle: .Alert)
alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))
presentViewController(alert, animated: true, completion: nil)
}
}
The TableViewDelegate that is in charged of everything related of UITableViewDelegate, and UITableViewDataSource protocols.
class TableViewDelegate: NSObject, UITableViewDelegate, UITableViewDataSource {
var data = [Int]()
// variable that holds a stores a function
// which return Void but accept an Int and a UITableViewCell as arguments.
var didSelectRow: ((dataItem: Int, cell: UITableViewCell) -> Void)?
init(data: [Int]) {
self.data = data
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return data.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
let text = String(data[indexPath.row])
cell.textLabel?.text = text
return cell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath)!
let dataItem = data[indexPath.row]
if let didSelectRow = didSelectRow {
// Calling didSelectRow that was set in ViewController.
didSelectRow(dataItem: dataItem, cell: cell)
}
}
}
Result:
I did this to avoid a long ViewController with a UIPickerViewDelegate/DS. You can simply make a class that conforms to UITableViewDelegate and UITableViewDataSource, instantiate this object in your view controller and assign it as the dataSource and delegate of the table view. For this class to send stuff back to your ViewController, you will have to make a protocol for the VC to conform to and give the class a delegate as well.
I read that this class must inherit from NSObject as the protocols are NSObject protocols, and it throws and error if they don't.
class MyCustomTableViewDel: NSObject, UITableViewDataSource, UITableViewDelegate {
weak var secondaryDelegate: TableViewSecondaryDelegate?
let rowData: [String]
init(dataForRows: [String]) {
rowData = dataForRows
super.init()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return rowData.count
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
secondaryDelegate?.doSomething(indexPath.row)
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
....
return SomeCellForTheTableView
}
}
then make the secondary protocol:
protocol TableViewSecondaryDelegate {
func doSomething(row: Int)
}
then in your ViewController:
class myTableViewSceneController: UIViewController, TableViewSecondaryDelegate {
override func viewDidLoad() {
....
let tableViewDelAndDS = MyCustomTableViewDel(dataForRows: ["row0", "row1"])
tableViewDelAndDS.secondaryDelegate = self
tableView.delegate = tableViewDelAndDS
tableView.dataSource = tableViewDelAndDS
}
func doSomething(row: Int) { ... }
}
I want to use a UITableview with different custom tableViewCells. My 3 cells are as such:
Cell1: should have an image and a label.
Cell2: should have two labels.
Cell3: should have a dayPicker.
I don't want to code a tag for the cells. How can I manage this in Swift. Do I have to code my own class for every cell? Can I use one tableviewController? How can I populate data in different cells?
I would like to generate a tableView, like a contact app of an iOS device.
Let me start with answering your questions first.
Do I have to code an own class for every cell?=> Yes, I believe so. At least, I would do that way.
Can I use one tableviewController?=> Yes, you can. However, you can also have a table view inside your View Controller.
How can I populate data in different cells? => Depending on the conditions, you can populate data in different cells. For example, let's assume that you want your first two rows to be like the first type of cells. So, you just create/reuse first type of cells and set it's data. It will be more clear, when I show you the screen shots, I guess.
Let me give you an example with a TableView inside a ViewController. Once you understand the main concept, then you can try and modify anyway you want.
Step 1: Create 3 Custom TableViewCells. I named it, FirstCustomTableViewCell, SecondCustomTableViewCell, ThirdCustomTableViewCell. You should use more meaningful names.
Step 2: Go the Main.storyboard and drag and drop a TableView inside your View Controller. Now, select the table view and go to the identity inspector. Set the "Prototype Cells" to 3. Here, you just told your TableView that you may have 3 different kinds of cells.
Step 3:
Now, select the 1st cell in your TableView and in the identity inspector, put "FirstCustomTableViewCell" in the Custom class field and then set the identifier as "firstCustomCell" in the attribute inspector.
Do the same for all others- Set their Custom Classes as "SecondCustomTableViewCell" and "ThirdCustomTableViewCell" respectively. Also set the identifiers as secondCustomCell and thirdCustomCell consecutively.
Step 4: Edit the Custom Cell Classes and add outlets according to your need. I edited it based on your question.
P.S: You need to put the outlets under the class definition.
So, In the FirstCustomTableViewCell.swift, under the
class FirstCustomTableViewCell: UITableViewCell {
you would put your label and image view outlets.
#IBOutlet weak var myImageView: UIImageView!
#IBOutlet weak var myLabel: UILabel!
and in the SecondCustomTableViewCell.swift, add the two labels like-
import UIKit
class SecondCustomTableViewCell: UITableViewCell {
#IBOutlet weak var myLabel_1: UILabel!
#IBOutlet weak var myLabel_2: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
and the ThirdCustomTableViewCell.swift should look like-
import UIKit
class ThirdCustomTableViewCell: UITableViewCell {
#IBOutlet weak var dayPicker: UIDatePicker!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
Step 5: In your ViewController, create an Outlet for your TableView and set the connection from storyboard. Also, you need to add the UITableViewDelegate and UITableViewDataSource in the class definition as the protocol list.
So, your class definition should look like-
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
After that attach the UITableViewDelegate and UITableViewDatasource of your table view to your controller. At This point your viewController.swift should look like-
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
P.S: If you were to use a TableViewController rather than a TableView inside a ViewController, you could have skipped this step.
Step 6: Drag and drop the image views and labels in your cell according to the Cell class. and then provide connection to their outlets from storyboard.
Step 7: Now, write the UITableViewDatasource's required methods in the view controller.
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "firstCustomCell")
//set the data here
return cell
}
else if indexPath.row == 1 {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "secondCustomCell")
//set the data here
return cell
}
else {
let cell: UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "thirdCustomCell")
//set the data here
return cell
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
Swift 3.0 + update with minimum code
Basic concept:
Create a table view with dynamic cell prototypes. Assign identifier and create custom table view cell class for each cell prototype. Initiate and show custom cells in table view's delegate method.
1. Create cells on storyboard
Drag a tableView to your view controller, add prototype cells to it, and then drop UI element to your table view cells, add constraint properly if needed.
2. Create custom UITableViewCell classes
Add the following code to your project. I am putting it right above the view controller class.
class FirstTableCell: UITableViewCell {
}
class SecondTableCell: UITableViewCell {
}
class ThirdTableCell: UITableViewCell {
}
3. Assign custom class and identifier to cell prototypes
For each of the cell prototypes in storyboard, assign the custom class created from step 2, and then enter an unique identifier.
4. Connect UI elements to swift code
Control drag the table view and connect to the view controller class. Control drag the UI elements that get added to cell prototypes on step 1, and connect to the corresponding table view cell class.
5. Add code to view controller and control the table view
Make your view controller conform to table view delegate
class YourViewController: UIViewController, UITableViewDataSource, UITableViewDelegate
In viewDidLoad, set up table view's delegate and data source.
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.dataSource = self
self.tableView.delegate = self
}
Finally, add two delegate methods to control your table view, as per minimum requirement.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "firstTableCell") as! FirstTableCell
// Set up cell.label
return cell
} else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "secondTableCell") as! SecondTableCell
// Set up cell.button
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "thirdTableCell") as! ThirdTableCell
// Set up cell.textField
return cell
}
}
6. Give it a try :)
I recommend to use this simple and easy to use library, I made for Table and Collection views. You can add as many types of cells as you want and achieve more clean ViewControllers without boilerplate code.
https://github.com/deniskakacka/DKDataSources
For UI on first picture, all your code in ViewController is this:
lazy var dataSource = DKTableDataSource<CellType>(
models: [
DisclosureCellModel(title: "Disclosure 1", action: .action1),
TextFieldCellModel(title: "TextField 1", placeholder: "Placeholder 1"),
SwitchCellModel(title: "Switch 1", isOn: true),
BannerCellModel(imageName: "placeholder"),
SwitchCellModel(title: "Switch 2", isOn: false),
BannerCellModel(imageName: "placeholder"),
DisclosureCellModel(title: "Disclosure 2", action: .action2),
TextFieldCellModel(title: "TextField 2", placeholder: "Placeholder 2"),
BannerCellModel(imageName: "placeholder")
]
)
// in `viewDidLoad`
dataSource.registerCells(for: tableView)
tableView.dataSource = dataSource
Swift 5
Create 3 Custom TableViewCells. I named it,
FirstTableViewCell, SecondTableViewCell,
ThirdTableViewCell
Add All 3 Custom Cell Classes and add outlets according to your need.
I have added in below code.
class FirstTableViewCell: UITableViewCell {
#IBOutlet weak var myImageView: UIImageView!
#IBOutlet weak var myLabel: UILabel!
static let cellIdentifier = "FirstTableViewCell"
static let cellNib = UINib(nibName: "FirstTableViewCell", bundle: Bundle.main)
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
3: In your ViewController, create an Outlet for your TableView. Also, you need to add the UITableViewDelegate and UITableViewDataSource in the class definition.
#IBOutlet weak var tableView: UITableView! {
didSet {
tableView.delegate = self
tableView.dataSource = self
tableView.register(FirstTableViewCell.cellNib, forCellReuseIdentifier: FirstTableViewCell.cellIdentifier)
tableView.register(SecondTableViewCell.cellNib, forCellReuseIdentifier: SecondTableViewCell.cellIdentifier)
tableView.register(ThirdTableViewCell.cellNib, forCellReuseIdentifier: ThirdTableViewCell.cellIdentifier)
}
}
4.Now, write the UITableViewDatasource's required methods in the view controller.
extension ViewController: UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
guard let cell = tableView.dequeueReusableCell(withIdentifier: FirstTableViewCell.cellIdentifier, for: indexPath) as? FirstTableViewCell else { return UITableViewCell() }
return cell
}else if indexPath.row == 1 {
guard let cell = tableView.dequeueReusableCell(withIdentifier: SecondTableViewCell.cellIdentifier, for: indexPath) as? SecondTableViewCell else { return UITableViewCell() }
return cell
}else {
guard let cell = tableView.dequeueReusableCell(withIdentifier: ThirdTableViewCell.cellIdentifier, for: indexPath) as? ThirdTableViewCell else { return UITableViewCell() }
return cell
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50 //According requirement
}
}
Your code will look like below(View Controller Code)
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView! {
didSet {
tableView.delegate = self
tableView.dataSource = self
tableView.register(FirstTableViewCell.cellNib, forCellReuseIdentifier: FirstTableViewCell.cellIdentifier)
tableView.register(SecondTableViewCell.cellNib, forCellReuseIdentifier: SecondTableViewCell.cellIdentifier)
tableView.register(ThirdTableViewCell.cellNib, forCellReuseIdentifier: ThirdTableViewCell.cellIdentifier)
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
extension ViewController: UITableViewDelegate,UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
guard let cell = tableView.dequeueReusableCell(withIdentifier: FirstTableViewCell.cellIdentifier, for: indexPath) as? FirstTableViewCell else { return UITableViewCell() }
return cell
}else if indexPath.row == 1 {
guard let cell = tableView.dequeueReusableCell(withIdentifier: SecondTableViewCell.cellIdentifier, for: indexPath) as? SecondTableViewCell else { return UITableViewCell() }
return cell
}else {
guard let cell = tableView.dequeueReusableCell(withIdentifier: ThirdTableViewCell.cellIdentifier, for: indexPath) as? ThirdTableViewCell else { return UITableViewCell() }
return cell
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50 //According requirement
}
}
The above answers are the best answers, but there are TONS of reasons to get this issue. Here is another potential solution for anyone with this problem:
My problem was that I was segueing to the ViewController class and not the storyboard view. So my reference to the storyboard cell was meaningless, since the storyboard wasn't being used.
I was doing this:
let viewControllerB = SubViewController()
viewControllerB.passedData = diseases[indexPath.row].name
navigationController?.pushViewController(viewControllerB, animated: true)
And I needed to do something like this:
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let nextViewController = storyBoard.instantiateViewController(withIdentifier: "SubViewStoryboardController") as! SubViewController
nextViewController.passedData = diseases[indexPath.row].name
self.present(nextViewController, animated:true, completion:nil)
Hope this helps someone.
If you're using custom XIBs as TableView Cells then follow the below code
//Write in viewDidLoad()
let nib = UINib(nibName: "PrinterTVC", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "CELL1")
let nib1 = UINib(nibName: "SelectAndEditTVC", bundle: nil)
tableView.register(nib1, forCellReuseIdentifier: "CELL2")
UITableViewController is inheriting UIViewController that already has UITableviewDataSource & UITableviewDelegate mapped on itself.
You might subclass UITableViewController or use a TableView inside your ViewController.
After that you must implement required methods(cellForRowAtIndexPath and numberOfRowsInSection) which are declared in the UITableviewDataSource.
Also in storyboard, you need to create cell prototypes with unique Id.
There are basic types of cell, with (title, subtitle for instance) - you can use them too if you don't need special configuration.
So, for picker, yes, you need to create your own custom cell. Create necessary custom UITableViewCell class holding date picker and make sure to use delegate to send back the desired result back to your ViewController.
Hi I am beginner in Swift programming language and I have problem to implementing two collection view inside of view controller, this is the link of my picture that I want to achieve:
The picture I want to achieve
is it possible? so far I have the codes that doesn't seems work:
class ViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UICollectionViewDataSource, UICollectionViewDelegate{
#IBOutlet weak var collectionView: UICollectionView!
#IBOutlet weak var collectionViewTwo: UICollectionView!
var optionOne = ["Gulsah", "Hurrem", "Mihrimah", "Nilufer"]
override func viewDidLoad() {
super.viewDidLoad()
self.resetFilterThumbnails()
self.collectionView.delegate = self
}
//For the collectionView, number of filters in the section
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if (filters == true){
//do all the stuff here for FILTER_CELL
return self.filters.count}
else{
return self.optionOne.count}
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("FILTER_CELL", forIndexPath: indexPath) as FilterThumbnailCell
let cellTwo = collectionView.dequeueReusableCellWithReuseIdentifier("FILTER_CELL_TWO", forIndexPath: indexPath) as FilterThumbnailCell
var filterThumbnail = self.filterThumbnails[indexPath.row]
println("filter cell two")
if (indexPath.item == 0){
//do all the stuff here for FILTER_CELL
if filterThumbnail.filteredThumbnail != nil {
cell.imageView.image = filterThumbnail.filteredThumbnail
} else {
cell.imageView.image = filterThumbnail.originalThumbnail
//filterThumbnail is a class instance
filterThumbnail.generateThumbnail({ (image) -> Void in
if let cell = collectionView.cellForItemAtIndexPath(indexPath) as? FilterThumbnailCell {
cell.imageView.image = image
}
})
}
return cell
}else{
//FILTER_CELL_TWO
var button = cellTwo.viewWithTag(1) as UILabel
button.text = optionOne[indexPath.row]
cellTwo.backgroundColor = UIColor.redColor()
return cellTwo
}
}
}
This is very Possible. You could do this in several ways.
1:
You could implement two contained view controllers. This might be the cleanest since you could handle interaction in separate controllers. In this case you may need to also implement some delegate/protocols to pass information back to the parentViewController.
2:
You could create a separate datasource/delegate class to handle the associated functions for each view controller and assign them in viewDidLoad. This case may also need to have delegates/protocols implemented to pass information from the collectionView dataSource/Delegate class.
Here is an example, taken from the Master-Detail starting class Create your class like this (add conform to the UITableViewDelegate if needed):
import UIKit
class MyDataSource: NSObject, UITableViewDataSource {
var objects = [AnyObject]()
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return objects.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let object = objects[indexPath.row] as NSDate
cell.textLabel!.text = object.description
return cell
}
}
Then in your UIViewController you create a variable of type MyDataSource:
var dataSource1 = MyDataSource()
var dataSource2 = MyDataSource()
Inside of viewDidLoad you can assign the dataSource its objects and assign the datasource to the tableviews:
dataSource1.objects = objects1;
dataSource2.objects = objects2;
tableView1.dataSource = dataSource1
tableView2.dataSource = dataSource2
Now each of the tableviews will use a different instance of this DataSource, with its own set of model objects. If you need to further customize you datasource (as it looks like you do) Simply create another data source class and assign it to the appropriate object. If you conform to the delegate of the tableview inside these data source objects, you should implement a standard protocol for the data source, and conform to that protocol inside of your view controller:
Above the datasource object:
protocol DataSourceDelegate{
func didSelectCellAtIndexPath(indexPath:NSIndexPath)
}
Inside of the data source object:
var dataSourceDelegate:DataSourceDelegate?
Inside of the view controller:
dataSource.dataSourceDelegate = self
Make sure to conform to the delegate in the class definition. Then instantiate the method in the view controller:
func didSelectCellAtIndexPath(indexPath:NSIndexPath){
// Your code here
}
Make sure to call the delegate inside the datasource
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
dataSourceDelegate?.didSelectCellAtIndexPath(indexPath)
}
To register cells, if you are using storyboard, just make sure that the cell identifiers are the correct ones, and you will not need to register anything else. If not, you could register the cell inside the dataSource (probably a good idea, since it would keep all the info contained)
3:
You could use one viewController and differentiate between the cases by comparing the collectionView passed into the dataSource/Delegate functions to an outlet connected to the corresponding collectionViews in the view. While this case will not need any delegates implemented, it will fill the viewController up with a lot of if/else statements, perhaps making the code more difficult to maintain/read.