I have a TableView Cell and inside that I have an ImageView and Label. But when I connect to them using:
#IBOutlet weak var menuListLabel: UILabel!
#IBOutlet weak var menuListImage: UIImageView!
Illegal Configuration:
The menuListImage outlet from the ViewController to the UIImageView is
invalid. Outlets cannot be connected to repeating content.
You need to create a custom class that inherits from UITableViewCell, and configure the outlets there.
class MyCustomTableViewCell: UITableViewCell {
#IBOutlet weak var menuListLabel: UILabel!
#IBOutlet weak var menuListImage: UIImageView!
}
Next, you need to configure the cell in your storyboard. Select your cell. Open the Identity inspector and set the Custom Class to "MyCustomTableViewCell".
Then, with the cell still selected, go to the Attributes inspector, and set the Reuse Identifier to "MyCustomTableViewCell". (This identifier can be whatever you want, you just need to use this exact value when calling 'dequeueReusableCellWithIdentifier'. I like to use my cell's class name as the identifier so it's easy to remember.)
In your table view controller, implement the necessary methods to build your table using your custom cell.
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1 // however many sections you need
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1 // however many rows you need
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// get an instance of your cell
let cell = tableView.dequeueReusableCellWithIdentifier("MyCustomTableViewCell", forIndexPath: indexPath) as MyCustomTableViewCell
// populate the data in your cell as desired
cell.menuListLabel.text = "some text"
cell.menuListImage.image = UIImage(named: "some image")
return cell
}
Related
I have 2 tableViews in one ViewController class.
In first tableView I have UITextField in custom cell with it's own UITableViewCell class.
I show textField in cell inside of cellForRowAt but i couldn't connect it like Outlet to VC and use it in ViewDidLoad.
How could I use textField Outlet from cell inside VC?
You can Not directly Connect outlet of Any Thing Embedded In TableCell
Follow Steps To Perform Code operation with Outlets Connected
Step 1- Create a new tableViewCell Class as Below ScreenSHot
Step 2- Now Assign Created Class to TableView cell in Storyboard as Below
Step 3- Time to connect outlets in Cell class created by normally dragging the TF to be Connected in cell class
output will be as Below
Step 4- Required Coding
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CustomTableCell
cell.fileNameLabel.text = coreClassObject.audioFileName
cell.durationLabel.text = coreClassObject.audioDuration
cell.uploadedStatusLabel.text = coreClassObject.audioUploadStatus
cell.playButton.addTarget(self, action: #selector(playSoundAtSelectedIndex(sender:)), for: .touchUpInside)
return cell
}
Re-Update Answer to Access TF in ViewDidLoad
----> my ViewController class
import UIKit
class tableViewVC: UIViewController
{
let staticArrayy = ["1","1","1","1","1","1","1","1","1","1"]
#IBOutlet weak var myDemoTableView: UITableView!
override func viewDidLoad()
{
super.viewDidLoad()
// Do any additional setup after loading the view.
///Set Delegates
myDemoTableView.delegate = self
myDemoTableView.dataSource = self
///Async operation
///To make sure cells are loaded
DispatchQueue.main.async
{
///Create a Reference TF
let MyTf : UITextField!
///Get Index Path of Which TF is to be Accessed
let indexPath = IndexPath(row: 0, section: 0)
///Create A new cell Reference
let newCell = self.myDemoTableView.cellForRow(at: indexPath)! as! CustomTableViewCell
///Assign Cell TF to our created TF
MyTf = newCell.cellTF
///Perform Changes
MyTf.text = "Changes text"
}
}
}
extension tableViewVC : UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return staticArrayy.count
}
//Setting cells data
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = self.myDemoTableView.dequeueReusableCell(withIdentifier: "Cell") as! CustomTableViewCell
cell.cellTF.placeholder = staticArrayy[indexPath.row]
return cell
}
//Setting height of cells
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 60
}
}
---> My cell class
import UIKit
class CustomTableViewCell: UITableViewCell
{
#IBOutlet weak var cellTF: UITextField!
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
}
}
----> My StoryBoard
---> Simulator Output
First of all it is bad idea to connect TextField with ViewController.
But if you want to, then first you need to check if you table consists of static cells and desired cell with textfield is among them. Then you can connect textField with viewcontroller's outlet and use it in viewDidLoad
TableView with dynamic cells will reload after viewDidLoad called so you cannot use textfield var in that method
You aren't supposed to link TableViewCell outlets in the ViewController – you should have a separate MyTableViewCell class where you link all of the outlets, such as:
class MyTableViewCell: UITableViewCell {
// MARK: Outlets
#IBOutlet weak var myTextField: UITextField!
}
You reference this table view in the view controller via the function tableView:cellForRowAtIndexPath and there you can handle all actions performed on the cell and by default, the TextField.
func tableView(_ tableView: UITableView, cellForItemAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withReuseIdentifier: "myCell", for: indexPath) as! MyTableViewCell
// Customize the cell and the TextField
return cell
}
Put your outlet inside your Cell class, and when you want to access it’s text from vc
U will do let cell = tableview.cellforrow(at indexpath) as! YourCellClass
Then access the textfield easily
let text = cell.yourTextField.text
But i advice you to remove the tableview and instead use scrollview if its simple viewcontroller
I'm trying to make a UITableView that can support having different objects/elements inside it. Specifically, these elements are a UITextField and UISwitch.
The first problem:
The elements do not show up. They are placed in the prototype cell, which is then constructed inside the class I have set up. I have verified that the cell setup is working because I can change the words on each cell, but there are no elements within the cell.
Here is the code that constructs my cells right now:
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return 1
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "EmailCell")
return cell
}
Second problem (which might be solved along with the first):
I have no way of accessing the information in each UITextField or each UISwitch. How can I get this information from all cells that exist?
Thanks in advance for the help!
There are multiple things wrong with your code.
For custom cells you need to implement a custom UITableViewCell subclass. Here is an example:
import UIKit
class EmailCell: UITableViewCell {
#IBOutlet var customTextField: UITextField!
#IBOutlet var customSwitch: UISwitch!
}
After that, open your Storyboard and select the prototype cell. Change it's class to EmailCell in the Identity Inspector.
Also make sure to connect your ui elements to the #IBOutlets created earlier. See this StackOverflow post if you need help with #IBOutlet.
In the next step, change your tableView(_:, cellForRowAt:) implementation like this:
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "EmailCell", for: indexPath) as! EmailCell
// Configure your custom ui elements however you want
cell.customTextField.text = "somestring"
cell.customSwitch.isOn = true
return cell
}
Make sure your cells have reuse identifiers and you're using
tableView.dequeueReusableCell(withIdentifier: -Your cell Id- , for: indexPath) as? -Your Cell Class-
in your cell for row at index datasource method
next you can add targets to your cell text field / switch by doing this in your cell for row at index datasource method
cell.-your switch / text field-.addTarget(self, action: #selector(valueChanged(_:)), for: .valueChanged)
and you should subclass a uitableview cell to add the property / iboutlets
class YourTableViewCell: UITableViewCell {
#IBOutlet weak var yourSwitch: UISwitch!
}
I need to add cell identifier to make ReusableCell for tableView. However I don't see any cell in the tableView properties and table view hierarchical. how to add a cell in the table view .
note : basically i want to create a Xib file which should contain a tableView and that tableView should have custom UiTableViewCell
code here :
class SuggestNearTableViewCollectionViewCell: UICollectionViewCell , UITableViewDataSource,UITableViewDelegate{
#IBOutlet weak var suggestTableView : UITableView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.suggestTableView.dataSource = self
self.suggestTableView.delegate = self
suggestTableView.register(UINib(nibName: "SuggestNearTableViewCell", bundle: nil), forCellReuseIdentifier: "SuggestNearTableViewCell")
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SuggestNearTableViewCell", for: indexPath) as! SuggestNearTableViewCell
return cell
}
}
First of all go to File-> new -> Cocoa Touch Class and create class of UIViewCOntroller. Name your class accordingly.
Now you will have a Xib file and a Swift file. Xib would look something like this.
Now drag and drop a UITableView on the Xib and give it 4-pin constraints as top=0, bottom=0, leadin=0, and trailing=0. Now create an outlet of your tableView in your newly created swift file. Connect data Source and delegate as well.
Now again go to File->New-> Coucoa Touch Class and create a class for UItableViewCell also create a Xib file like below.
Now you will have a Xib for your cell and a swift file for your cell. Just design your cell as your need in this Xib. Lets say If you want to put an imageView or a label etc. Then create outlets of all components in swift file of your custom cell. Now add this function in swift file of your custom cell.
class func cellForTableView(tableView: UITableView, atIndexPath indexPath: NSIndexPath) -> YourCustomTableViewCell {
let kYourCustomTableViewCellIdentifier = "kYourCustomTableViewCellIdentifier"
tableView.registerNib(UINib(nibName: "YourCustomTableViewCell", bundle: NSBundle.mainBundle()), forCellReuseIdentifier: kYourCustomTableViewCellIdentifier)
let cell = tableView.dequeueReusableCellWithIdentifier(kYourCustomTableViewCellIdentifier, forIndexPath: indexPath) as! YourCustomTableViewCell
return cell
}
Your custom cell is ready to use.
Now go to the swift file of your tableView and in your cellForRowAtIndexPath just use use this cell like below.
let cell = YourCustomTableViewCell.cellForTableView(tableView, atIndexPath: indexPath)
cell.myImageView.image = "something"
// Do something with your cell
I hope it would be helpfull. Let me know if you find any difficulty.
Inside tableViewController in viewDidLoad you should register it like this:
tableView.registerNib(UINib(nibName: "CustomOneCell", bundle: nil), forCellReuseIdentifier: "CustomCellOne")
And inside cellForRowAtIndexPath just declare cell:
let cell: CustomOneCell = tableView.dequeueReusableCellWithIdentifier("CustomCellOne", forIndexPath: indexPath) as! CustomOneCell
If you are not doing it inside tableViewController then you gotta connect your tableView and delegate:
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableView: UITableView!
...
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
// Table view delegate
self.tableView.delegate = self
self.tableView.dataSource = self
...
Hi I want to have different layouts in different sections of UITableView, I want to do it using dynamic prototype cells and not using static cells.
I don't know how to create it, Please help. Any links or something. I want to achieve like this, please see the picture
pls download the pic
Please give your code if any in swift.
According to your details, it seems like, you want a grouped tableView where your different section will have different types of cell. That is pretty easy.
So let's start. I explained the whole walk through from the scratch through the screen shots. If you just follow this, you will understand the concept and the process.
(I am assuming, you know how to add necessary constraints)
Firstly, Go to the Storyboard and drag a tableView in your Controller.
Then create 2 Custom UITableViewCell classes-
Now drag and drop 2 TableView Cells inside your TableView in storyboard.
So, you have 2 tableView Cells inside your TableView for which you have already created two Custom Cells.
Now, we need to assign the cell classes, so that it can understand which class it should corresponds to. Select the First cell in the storyboard, click on the class inspector and assign its class-
Do the Same for the second cell -
We also need to give them unique identifiers. Select the first cell and assign an identifier like -
Do the same for the second cell -
We are almost done setting up the UI. The last piece is to tell the UITableView that it is going to be a "Group" type.
Again select the TableView and assign its type to "Group" like-
Now, we are good to go.
Let's declare some IBOutlets in our custom TableViewCells that we created earlier.
TypeOneTableViewCell.swift class-
import UIKit
class TypeOneTableViewCell: UITableViewCell {
#IBOutlet weak var cellImageView: UIImageView!
#IBOutlet weak var cellTitleLabel: UILabel!
#IBOutlet weak var cellSubtitleLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
}
and TypeTwoTableViewCell.swift class-
import UIKit
class TypeTwoTableViewCell: UITableViewCell {
#IBOutlet weak var cellTitleLabel: UILabel!
#IBOutlet weak var cellSubtitleLabel: UILabel!
#IBOutlet weak var cellButton: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
}
}
Go to the Storyboard and add an image and two labels in the First prototype cell and attach them with the outlets.
Now in the second cell, add a button and two labels and connect the outlets the same as before-
Enough with the setting up. Let's jump into doing some real stuff. Go to your controller class and first create an IBOutlet for your tableView like-
#IBOutlet weak var groupedTableView :UITableView!
Don't forget to attach the TableView's outlet in storyboard.
Now, we need the TableView Delegate and Datasource. So, let's include them in the protocol list like-
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
Right now, you may be getting an error because you haven't implement the required delegate methods which is in the UITableViewDatasource protocol, but it's okay, it will be resolved soon.
First thing first. Specify who is going implement the delegate and datasource methods. Go to your viewDidLoad method and add this -
override func viewDidLoad() {
super.viewDidLoad()
self.groupedTableView.dataSource! = self
self.groupedTableView.delegate! = self
}
then tell your tableView that you will have 2 sections through the numberOfSectionsInTableView method like-
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
and then specify how many of the cells, each section is going to held. Let's assume the 1st section contains 4 rows and the 2nd one contains 3 rows. To do so, use the numberOfRowsInSection method.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
if section == 0{
return 4
}
else{
return 3
}
}
and the last part, defining the cell and it's data-
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
if indexPath.section == 0{
let cell : TypeOneTableViewCell = tableView.dequeueReusableCellWithIdentifier("typeOneCell", forIndexPath: indexPath) as! TypeOneTableViewCell
cell.imageView!.image = UIImage(named: "noImage.png")
cell.cellTitleLabel.text = "Header " + "\(indexPath.section)" + "-" + "\(indexPath.row)"
cell.cellSubtitleLabel.text = "Details " + "\(indexPath.section)" + "-" + "\(indexPath.row)"
return cell
}
else{
let cell : TypeTwoTableViewCell = tableView.dequeueReusableCellWithIdentifier("TypeTwoCell", forIndexPath: indexPath) as! TypeTwoTableViewCell
cell.cellTitleLabel.text = "Header " + "\(indexPath.section)" + "-" + "\(indexPath.row)"
cell.cellSubtitleLabel.text = "Details " + "\(indexPath.section)" + "-" + "\(indexPath.row)"
return cell
}
}
There you GO! TableView have many delegate methods like heightForRowAtIndexPath to specify the heights of custom cells. In my case I specified it as 80.0 like-
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 80.0
}
You can do a lot more customization with those delegate methods. Check apple's guide for UITableView.
P.S. : for beautification, I added an image here. If you implement the same way, I did, you should see the output like-
Hope this helps.
For cells to be dynamic, do this:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if (indexPath.row==0 && indexPath.section==0){
//static cell
return 120 //static height
}
return UITableViewAutomaticDimension //for dynamic cell height
}
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Also, you need to make sure that your elements in the cell are bound with autolayout for the correct placements of the elements with dynamic height.
Numerous tutorials I've been through say the only code I need to display the array I want it to is:
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var chatListTableView: UITableView!
var friends = ["Anthony", "Antonio", "Andy"]
override func viewDidLoad() {
super.viewDidLoad()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return friends.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : UITableViewCell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "ChatListCell")
cell.textLabel.text = self.friends[indexPath.row]
return cell
}
}
However, when I run the app, the tableView is still blank. What am I doing wrong? I feel that I am missing something.
All I want to do is display the array in the tableView.
Check if the ViewController is the datasource and delegate of the tableview
As Aci says in his answer, you have to set the data source and delegate of the table view to your view controller. The easiest way to do that is in Interface Builder.