nomrally i have one view controller and i add outlets to it. and inside view did load i can change the font of the text view or i can add images to the ui image. but now i have a custom cell like this:
class NumberOfPeopleTableViewCell: UITableViewCell {
#IBOutlet weak var numberOfPeopleLabel: UILabel!
as you see, i have outlet in that cell, how can i interact with that outlet? there is no view did load function inside the table view cell
You could set the font of the label in your storyboard.
Or you could set the font of the label in awakeFromNib (a method you can override in your cell class).
Or you could set the font of the label in tableView(_:cellForRowAtIndexPath:) (in your table view controller).
From what I can gather, the "standard" approach would be, inside your UITableViewController subclass:
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("<Your Id Here>", forIndexPath: indexPath) as! NumberOfPeopleTableViewCell
let foo = cell.numberOfPeopleLabel // DO STUFF WITH IT
// Do more stuff here
return cell
}
OR --
If you want to keep your View Controller code clean of graphics layout-ing / appearance logic (which you should) consider, inside NumberOfPeopleTableViewCell to override func layoutSubviews().
OR (my favourite) --
You could subclass the UITextView (e.g. MYCellTextView) and change the appearance for all of your subclass instances in your app delegate using UIApparence. Like this should work:
MyCellTextView.appearance().font = UIFont(name: "<myFont>", size: 10.0)
You can put the above, for example, in your app delegate. This has the advantage of keeping appearance code in one place and away from view controllers (and generic, for all instances of your custom view).
You can override the function layoutSubviews
override func layoutSubviews() {
//do whatever here for your outlets
}
take a look at awakeFromNib. as the documentation states:
When an object receives an awakeFromNib message, it is guaranteed to have all its outlet instance variables set.
so you can do:
override func awakeFromNib() {
super.awakeFromNib()
numberOfPeopleLabel.font = UIFont.systemFontOfSize(15.0) // or whatever font you want to assign
}
Related
I have a Xib with a table view in it (I'm using a Xib and not a regular storyboard because I'm inserting the Xib into a UIPageViewController). In the Xib's class, I register a custom table view cell. Though the cell inserts into the table view, it doesn't resize properly based on it's constraints nor does it change the display of the table view.
Here's my xib:
Here's my custom cell:
And here's the setup code I have in the view controller that has the table view Xib:class
YearbookPageViewController: UIViewController {
var signatures: [Signature] = []
var pageNumber: Int = 0
convenience init(signatures: [Signature], pageNumber: Int) {
self.init(nibName: "YearbookPageViewController", bundle: nil)
self.signatures = signatures
self.pageNumber = pageNumber
}
// MARK: Properties
#IBOutlet var pageTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.pageTableView.delegate = self
self.pageTableView.dataSource = self
let nib = UINib(nibName: "SignatureTableViewCell", bundle: nil)
self.pageTableView.register(nib, forCellReuseIdentifier: SignatureTableViewCell.identifier)
}
}
When I run the app, this is what it looks like:
So basically the custom cell is added to the table view from the xib file, but they aren't sized properly even though the cell has constraints on everything? And, the rest of the tableview is still white with table view lines? I'm not sure if the table view isn't responding correctly because it's in a Xib or if I'm missing something that I'm supposed to add.
Would appreciate any pointers or help on how to get things displaying properly!
By default, tableView displays default height of UITableViewCell. If we want custom height, there can be two ways.
1. Using heightForRow method
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 200
}
2. Using AutoLayout
In this case, your tableView cell must apply all required constraints that completes a top to bottom constraint ladder, so that autoLayout can calculate the height of cell at RunTime.
For the second problem, you can remove extra separator. by executing following code in viewDidLoad
tableView.tableFooterView = UIView()
You should use this;
tableView.separatorStyle = .none
for the empty tableView view.
Currently I have a few of custom cell's prototypes created in Storyboard with text fields embedded in them. To access these text fields, I use nameTextField = cell.viewWithTag:(1) in cellForRowAtIndexPath:. But viewDidLoad: and viewWillAppear: methods get called before cellForRowAtIndexPath, so at that time nameTextField is nil. To populate text fields when table view shows on screen, I use viewDidAppear:, but it results in a noticeable delay. Also, when I scroll table view up and down, cellForRowAtIndexPath: gets called again and again, resetting already entered data in text fields.
Are there more efficient ways to populate text fields embedded in custom cells' prototypes with data just before the view shows up, and to prevent resetting of entered data in each cellForRowAtIndexPath: call?
I guess you're creating profile screen (or something with many textField to get input data from user). Am I right?
If I'm right, you can use a static tableView (when you have a few textFields)
Hope this can help.
I'm not sure I understand completely what you're trying to do, but cells are normally configured in the cellForRowAtIndexPath: method, not in viewDidLoad. You can also try connecting the textfield to an outlet on your custom cell class. Then you can do:
// in view controller
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
as! CustomCell
let object = myDataSource[indexPath.row]
cell.textField.text = object.description
cell.shouldBecomeFirstResponder = indexPath.row == 0
return cell
}
// then in the cell
class CustomCell: UITableViewCell {
#IBOutlet weak var textField: UITextField!
var shouldBecomeFirstResponder: Bool = false
override func awakeFromNib() {
if shouldBecomeFirstResponder {
textField.becomeFirstResponder()
}
}
}
Then when users input text into the textfield, it would make sense to update your data source.
In viewDidLoad try to run something like self.tableView.reloadData before you do this line "nameTextField = cell.viewWithTag:(1)".
I want to implement a simple tableView in my Viewcontroller but the output is not complete. The content is just visible in one sometimes in two rows.
The classic things:
The class use this:
class MealOfWeekView: UIViewController, UITableViewDelegate, UITableViewDataSource {...}
I set the delegates
override func viewDidLoad() {
super.viewDidLoad()
self.tableViewFood.delegate = self
self.tableViewFood.dataSource = self
self.tableViewFood.reloadData()
}
I use the right identifier:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("foodIdent", forIndexPath: indexPath) as! FoodTableViewCell
cell.dayLabel?.text = "\(day[indexPath.row])"
return cell
}
return 1 section and return 7 rows
=> I use the first time the Tab Bar Controller, in my first tab there is already a tableView. This one works perfect.
The tableView shows as far as I know the days tuesday, saturday or sunday... don't know, whether the info is important :)
EDIT
So with your help I figured out, that my daylabel is nil.
My FoodTableViewCell
class FoodTableViewCell: UITableViewCell {
#IBOutlet weak var dayLbl: UILabel!
}
I add to my viewDidLoad this line:
self.tableViewFood.registerClass(FoodTableViewCell.self, forCellReuseIdentifier: "foodIdent")
But it doesn't work.
If you need more code, give a sign.
Thank you!
Looks like this:
Your issue is with your custom class FoodTableViewCell, but I would verify the following first.
Confirm that the label is being set with the day of the week for the row index. You can do this by setting a breakpoint or printing out statements such as where you create your cells.
print("dayLabel: (cell.dayLabel?.text)")
print("day[indexPath.row]: (day[indexPath.row]")
Confirm you are registering the FoodTableViewCell with the table view.
Confirm that your subclass FoodTableViewCell's dayLabel property is setup correctly. Try changing the background color so you know it is least being displayed in the UI.
Check that your subclass of UITableViewCell is overriding and setting up the dayLabel for reuse correctly.prepareForReuse()
Background information for working with table views
SOLUTION
I found my answer here
When you use Tab Bar Controller you have to use viewDidAppear or viewWillAppear
this lines worked for me:
override func viewWillAppear(animated: Bool) {
self.tableViewFood.delegate = self
self.tableViewFood.dataSource = self
dispatch_async(dispatch_get_main_queue(), {
self.tableViewFood.reloadData()
})
}
I have been stuck for hours on this issue. I have created a custom cell inside a tableview which is inside a UIVC. The custom cell has it's own class file and is all linked up as well as having the buttons inside it connected to the UIVC via delegates.
Inside the custom cell there consists of a UITextView as well as some buttons.
Tapping the tableview adds a new custom cell. The user can type whatever their beautiful heart desires, eventually resigning the first responder of the textview. Here is my issue(s).
MAIN. First off. Overtime, the cells start mixing up the text that was typed in by the user, and starts reusing it. It becomes a mess.
Due to the fact I have a custom cell, I do not need to register the class in the viewDidLoad of the UIVC. A stack overflow answer stated.
Optional. Second. Eventually, after a certain point the keyboard blocks the cell view. I have no idea how to scroll the cell to the top of the tableview.
Optional. Third. This is just a bonus. How would one be able to save the data from a cell with a decent storage method. I heard NSUserDefaults is only good for small memory storage files. Basically. Transferring the data in the textview inside the custom cell, into another area (UIVC?) where the data can be saved. Most likely using an array and saving the data on that array.
Code. As requested.
UIVC
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let reminderCell = reminder_tableView.dequeueReusableCellWithIdentifier("cellReminder", forIndexPath:indexPath) as! addReminderCell
reminderCell.selectionStyle = .None
reminderCell.heightForReminderTextDelegate = self
reminderCell.delegate = self
reminderCell.reminder_textview.becomeFirstResponder()
return reminderCell
}
Custom Cell Code. Not all of it though.
import UIKit
import AVFoundation
//MARK: Height For Reminder Delegate
protocol HeightForReminderTextView
{
func heightOfTextView(height: CGFloat)
}
//MARK: Beginning of Class
class addReminderCell: UITableViewCell, UITextViewDelegate {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: nil)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
//MARK: Delegate Declarations
var heightForReminderTextDelegate :HeightForReminderTextView?
//MARK: Element IBOutlets
#IBOutlet var reminder_textview: UITextView!
#IBOutlet var reminder_cell_uiview: UIView!
//MARK: Button
#IBAction func non_priority_button(sender: AnyObject) {
println("pressed")
}
//MARK: Awake From Nib Starts Here
override func awakeFromNib() {
super.awakeFromNib()
reminder_textview.delegate = self
}
MAIN: When you dequeue a cell it means that cell may be reused it does not create a new cell everytime. For that UITableViewCell has a method named prepareForReuse() which you can override, where you can reset all your cell content. Ex:
override func prepareForReuse() {
myTextView.text = ""
}
Due to the fact I have a custom cell...
If you have only *.swift file for your custom cell you must registerClass(:forCellReuseIdentifier:)
If you also have *.xib file you should registerNib(:forCellReuseIdentifier:) in the viewDidLoad
Optional
You can use scrollToRowAtIndexPath(_:atScrollPosition:animated:) to scroll desired cell to top of tableView
Optional
You can use CoreData, JSON, some SQLite wrappers to save data. In NSUserDefaults you can use small amount of data, like some settings.
I recommend to use NSJSONSerialization for now. You can create NSData from a Dictionary and write data as *.json to Documents directory using NSFileManager. In your app you should keep an array or dictionary with all the data and pass to another view controller that data.
when user types text, you should save it to some array or dictionary accoding to your requirment and that would helpyou with resusing problem.
Now, second problem of yours is scrolling I answered this question hope this will help. this is in objective C although.
and third for transferring data from OneVc to another you can use Segues
Hope this helps
I am trying to create a custom cell for my UITableView but I am having some difficulty.
First off I cannot use the Interface Builder, as I am experiencing a variation on this bug in Xcode. Every time I click on an element in the Interface Builder everything in that view gets a height and width of zero and gets repositioned outside of the view. Besides, I would like to learn how to do this programmatically.
Secondly I am using the Swift language for my project. I have been trying to follow this demonstration, and doing my best to convert the Objective C code over to Swift, but whenever I run into problems I end up being stuck. I presume this is because I am not converting the code over correctly.
Thirdly I found this video but despite being fairly difficult to follow (lots of the code is just copied and pasted without much explanation to what it does or why), it still ends up using the Interface Builder to change various parts.
I have a basic UITableView set up fine. I just want to be able to add a custom cell to that table view.
Can this be done using pure programming, or do I need to use the Interface Builder?
Can anyone point me in the right direction or help me out in creating a custom cell programmatically in Swift?
Many thanks.
In general: Everything is possible in pure programming ;-)
Create a custom class for your tableView cell and there setup all the elements, properties and the visual layout. Implement the required methods init(style,reuseidentifier)
In your custom class for the UITableViewController register the custom cell class using registerClass(forCellReuseIdentifier)
Setup your delegate and datasource for the custom tableViewController
Finally, you create the cells in cellForRowAtIndexPath:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myReuseIdentifier", forIndexPath: indexPath) as MyCustomTableViewCell
// configure the cell using its properties
return cell
}
This should be the basic steps.
If you're looking for more code, here is an example of a custom cell that I created:
// File: vDataEntryCell.swift
import UIKit
class vDataEntryCell: UITableViewCell
{
//-----------------
// MARK: PROPERTIES
//-----------------
//Locals
var textField : UITextField = UITextField()
//-----------------
// MARK: VIEW FUNCTIONS
//-----------------
///------------
//Method: Init with Style
//Purpose:
//Notes: This will NOT get called unless you call "registerClass, forCellReuseIdentifier" on your tableview
///------------
override init(style: UITableViewCellStyle, reuseIdentifier: String!)
{
//First Call Super
super.init(style: style, reuseIdentifier: reuseIdentifier)
//Initialize Text Field
self.textField = UITextField(frame: CGRect(x: 119.00, y: 9, width: 216.00, height: 31.00));
//Add TextField to SubView
self.addSubview(self.textField)
}
///------------
//Method: Init with Coder
//Purpose:
//Notes: This function is apparently required; gets called by default if you don't call "registerClass, forCellReuseIdentifier" on your tableview
///------------
required init(coder aDecoder: NSCoder)
{
//Just Call Super
super.init(coder: aDecoder)
}
}
Then in my UITableViewController class I did the following:
// File: vcESDEnterCityState.swift
import UIKit
class vcESDEnterCityState: UITableViewController
{
//-----------------
// MARK: VC FUNCTIONS
//-----------------
///------------
//Method: View Will Appear
//Purpose:
//Notes:
///------------
override func viewWillAppear(animated: Bool)
{
//First Call Super
super.viewWillAppear(animated)
//Register the Custom DataCell
tvCityStateForm.registerClass(vDataEntryCell.classForCoder(), forCellReuseIdentifier: "cell")
}
//-----------------
// MARK: UITABLEVIEW DELEGATES
//-----------------
///------------
//Method: Cell for Row at Index Path of TableView
//Purpose:
//Notes:
///------------
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
//Get Reference to Cell
var cell : vDataEntryCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as vDataEntryCell
//...Do Stuff
//Return Cell
return cell
}
}