I'm just starting swift and I'm making a calendar app. Right now I'm showing a list on events if you click on a date. All questions here are about hiding cells that are at the end of a tablieview, but mine are not so eventsTableView.tableFooterView = UIView() doesn't work.
override func viewDidLoad() {
super.viewDidLoad()
eventsTableView.register(UITableViewCell.self, forCellReuseIdentifier: "theCell")
self.eventsTableView.rowHeight = 80
}
func tableView(_ eventsTableView: UITableView,
cellForRowAt indexPath: IndexPath)->UITableViewCell{
let event = model.events[indexPath.row]
let theItem = eventsTableView.dequeueReusableCell(
withIdentifier: "theCell",for: indexPath)
let what = event.value(forKeyPath:"what") as? String
let location = event.value(forKeyPath:"location") as? String
let when = event.value(forKeyPath:"when") as? Date
if model.checkDay(date: when!) == model.givendate && model.checkMonth(date: when!) == model.displayedMonth {
theItem.textLabel?.numberOfLines = 3
let labelText = what! + "\n" + "time: " + model.getTime(date: when!) + "\n" + "location: " + location!
theItem.textLabel?.text = labelText
} else {
theItem.textLabel?.numberOfLines = 0
}
print(theItem)
return theItem
}
This is what my output looks like
Try this code :
You can put a check for empty data in a model and hide that cell completely like this:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
//Check if model is empty
if shouldHideCell {
return 0
} else {
return UITableViewAutomaticDimension
}
}
Please refer to this SO Post. Happy coding.
What you can do here is just customise your dataSource, like if the Data corresponding to that row is empty then it's better to not to add that row in your datasource array.
Example while customising your dataSource
if hasEvent{
dataSource.append(day)
}else{
// No need to show in UI
}
I want to Display current location Address on a TableViewCell. I got the latitude and longitude but i can't understand how to show address string on cell.
i wrote the below code in ViewDidLoad()
it display the address in label.
let manager: CLLocationManager = locationManager
CLGeocoder().reverseGeocodeLocation(manager.location!, completionHandler: {(placemarks, error)->Void in
let placemark = placemarks?[0]
let lines = placemark?.addressDictionary?["FormattedAddressLines"]
let addressString = (lines as! NSArray).componentsJoined(by: "\n")
self.lblAddress.text = addressString
print(addressString)
})
but i want to show the address on tableview Cell.
//return cell for perticular row withing section
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
if indexPath.section <= 1
{
let cell = tableView.dequeueReusableCell(withIdentifier: "CellRID", for: indexPath)
cell.textLabel?.text = "\(self.batteryLevel() * 100) %"
return cell
}
else
{
//create reusable cell object by dequeueReusableCellWithIdentifier
//identifier must register with cell
let cell = tableView.dequeueReusableCell(withIdentifier: "LocationTableViewCellRID", for: indexPath) as! LocationTableViewCell
let personName = txtFieldName.text
let a = LocationVC()
cell.lblName?.text = "\(personName) \(self.batteryLevel() * 100) %"
cell.lblAddress?.text =
return cell
}
}
I want to show the address on lblAddress. I am new to iOS. Thanks in Advance for you help.
You should have declared a property for addressString above the viewDidLoad method. Not inside the viewDidLoad method.
Add this above the viewDidLoad method
let addressString = String()
Then in the viewDidLoad method change this line
let addressString = (lines as! NSArray).componentsJoined(by: "\n")
to
self.addressString = (lines as! NSArray).componentsJoined(by: "\n")
If you make your addressString a property, you would have access to it in cellRowForAtIndexPath.
I am working on this app, and I am new to Swift. Only two weeks of knowledge. I am supposed to create a table view with 12 cells - 3 of which are supposed to be text fields and user can type what they want. I have made two prototype cells with two different identifiers. I am using an array called "items" which has strings to be represented in the cells. If the string is blank, that cell is supposed to be a text field, which I have done. Problem occurs after that when I try to type in those fields and scroll the cells.
Please help me in understanding and solving the following issues:
How can I delegate the text field which I added as a subview to my tableview cell?
How can I make sure that whatever I type in the textfield remains there, even after I scroll the cells up and down as I wish?
How can I make sure user can edit whatever they type in the text field?
Here is my code:
var items = ["Apple", "Fish", "Dates", "Cereal", "Ice cream", "Lamb", "Potatoes", "Chicken", "Bread", " ", " "," "]
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var iD = "normal"
if (items[indexPath.row] == " ") {
iD = "textField"
let cell = tableView.dequeueReusableCellWithIdentifier(iD, forIndexPath: indexPath)
cell.textLabel?.text = items[indexPath.row]
let textField = UITextField(frame: CGRect(x: 20, y: 10, width: 150, height: 30))
textField.backgroundColor = UIColor.brownColor()
textField.placeholder = ""
cell.contentView.addSubview(textField)
return cell
}
else {
let cell = tableView.dequeueReusableCellWithIdentifier(iD, forIndexPath: indexPath)
cell.textLabel?.text = items[indexPath.row]
return cell
}
////
func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) {
if (sourceIndexPath.row != destinationIndexPath.row){
let temp = items[sourceIndexPath.row]
items.removeAtIndex(sourceIndexPath.row)
items.insert(temp, atIndex: destinationIndexPath.row)
}
tableView.reloadData()
}
I would rather create a subclass of UITableviewCell and add a textfield there as a subview. Then you set the delegate of the textfield to the cell itself.
Here is some sample code. I did not try to run it, but i think it should work:
class InputCell: UITableViewCell, UITextFieldDelegate {
private let textField = UITextField()
private var resultBlock: ((changedText: String) -> ())? = nil
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.textField.delegate = self
self.contentView.addSubview(self.textField)
// additional setup for the textfield like setting the textstyle and so on
}
func setup(initalText: String, resultBlock: (changedText: String) -> ()) {
self.textField.text = initalText
self.resultBlock = resultBlock
}
func textFieldDidEndEditing(textField: UITextField) {
if let block = self.resultBlock, let text = textField.text {
block(changedText: text)
}
}
}
In your view controller i would change the items to be a dictionary, so you can directly link them to the indexpaths of the tableview. And you need to let the tableview register your custom cell class.
var items = [0: "Apple", 1: "Fish", 2: "Dates", 3: "Cereal", 4: "Ice cream", 5: "Lamb", 6: "Potatoes", 7: "Chicken", 8: "Bread", 9: " ", 10: " ", 11: " "]
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// the position of the cell with a textfield is fixed right? Just put the row number here then
if indexPath.row > 8 {
let cell = tableView.dequeueReusableCellWithIdentifier("CellWithTextField", forIndexPath: indexPath) as! InputCell
if let initialText = items[indexPath.row] {
cell.setup(initialText) { [weak self] text in
self?.items[indexPath.row] = text
}
}
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("NormalCell", forIndexPath: indexPath)
cell.textLabel?.text = items[indexPath.row]
return cell
}
}
first, add the textfield protocol UITextFielDelegate, and in cell for row atindex write textfield.delegate = self.
And add delegate method to manage the text.
Hope this help you.
You have to save the textfield data in some object. As UITableView reuses same cells your textfield text will be lost on scroll as the cell will be reused. I would suggest creating some array and storing the data in that for each indexPath.
You should implement the UITextField delegate methods inside cell class and whenever some text changes, you should call another delegate method of yours (CellDelegate) which should be implemented in ViewController to update data.
This delegate method will pass text and indexPath of cell.
In the UITableViewCell add the UItextfield delegate for textChange.
You can alter your items array to contain model objects having the real value and the editing value.
let apple = Item()
apple.realValue = "Apple"
apple.editedValue = ""
var item = [0: apple, .............
Pass the model object in the tableview cell and update the edited value on text change delegate call. In cellForRow add the editedValue in the textfield text property
let item = items[indexPath.row]
cell.textLabel?.text = item.realValue
if item.editedValue{
// add the textFieldText
}
Inherit UITextFieldDelegate to your controller
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var iD = "normal"
if (items[indexPath.row] == " ") {
iD = "textField"
let cell = tableView.dequeueReusableCellWithIdentifier(iD, forIndexPath: indexPath)
cell.textLabel?.text = items[indexPath.row]
let textField = UITextField(frame: CGRect(x: 20, y: 10, width: 150, height: 30))
textField.backgroundColor = UIColor.brownColor()
textField.placeholder = ""
cell.contentView.addSubview(textField)
textField.delegate = self // set delegate
textField.tag= indexPath.row
return cell
}
else {
let cell = tableView.dequeueReusableCellWithIdentifier(iD, forIndexPath: indexPath)
cell.textLabel?.text = items[indexPath.row]
return cell
}
}
//delegate methods
func textFieldDidBeginEditing(textField: UITextField!) { //delegate method
print(textField.tag)//you will get the row. items[textField.tag] will get the object
}
func textFieldShouldEndEditing(textField: UITextField!) -> Bool { //delegate method
print(textField.tag)//you will get the row. items[textField.tag] will get the object
items[textField.tag]= textField.text
return false
}
func textFieldShouldReturn(textField: UITextField!) -> Bool { //delegate method
textField.resignFirstResponder()
return true
}
How can I add multiple objects in the same cell?
func getNowPlayingItem() {
if let nowPlaying = musicPlayer.nowPlayingItem {
let title = nowPlaying[MPMediaItemPropertyTitle] as? String
let artist = nowPlaying[MPMediaItemPropertyArtist] as? String
let album = nowPlaying[MPMediaItemPropertyAlbumTitle] as? String
println("Song: \(title)")
println("Artist: \(artist)")
println("Album: \(album)")
println("\n")
self.add = [Play(name: title!)]
self.table.rowHeight = UITableViewAutomaticDimension
self.table.estimatedRowHeight = 44.0
}
}
I tried modifying [Play(name: title!)] to [Play(name: title! + artist! + album!)], but only the title shows up, I'm guessing that only the first object will appear. How can I get all three to show up on three separate lines, but in the same cell?
You can use string substitution i.e "\(title!) \(artist!) \(album !)" instead.
In tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell set following property for your UITableViewCell.
cell.textLabel?.numberOfLines = 3;
cell.textLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
By default, your UITableViewCell only display the first line of text. So, you need to set numberOfLines to 3.
Then:
self.add = [Play(name: "\(title!)\n\(artist!)\n\(album !)")]
Notice the newline "\n" character.
I'm trying to create tableView which is suppose to auto resize the height according to the messageLabel. IOS8 has made this a lot of easier, however i can't seem to achieve this. So far i've created tableViewCell custom class with a xib file looking like below:
and then set the messageLabel.numberOfLines = 0
in the viewController i've set following in viewDidLoad
tableView.estimatedRowHeight = 80.0
tableView.rowHeight = UITableViewAutomaticDimension
and in the end the delegate methods
func tableView(tableView:UITableView, numberOfRowsInSection section:Int)->Int
{
return 1
}
func numberOfSectionsInTableView(tableView:UITableView)->Int
{
return 1
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var cell = tableView.dequeueReusableCellWithIdentifier("TwitterPlainCell", forIndexPath: indexPath) as! TwitterPlainCell
let url = NSURL(string: "https://pbs.twimg.com/profile_images/507493048062713856/KaWKfdgW.jpeg")
let data = NSData(contentsOfURL: url!) //make sure your image in this url does exist, otherwise unwrap in a if let check
cell.selectionStyle = UITableViewCellSelectionStyle.None
// cell.backgroundColor = UIColor(rgba: "#f6f7f9")
var name = "Olof Kajbjer"
var userName = "#olofmCS"
var topText = "\(name) \(userName)"
var topCount = count(topText)
var userCount = count(userName)
var userNameLocation = topCount - userCount
cell.profileImage.image = UIImage(data: data!)
cell.dateLabel.text = "55m"
var myMutableString = NSMutableAttributedString(string: topText, attributes: [NSFontAttributeName:UIFont(name: "PT Sans", size: 18.0)!])
myMutableString.addAttribute(NSForegroundColorAttributeName, value: UIColor(rgba: "#A6B0B5"), range: NSRange(location:userNameLocation,length:count(userName)))
myMutableString.addAttribute(NSFontAttributeName, value: UIFont(name: "PT Sans", size: 13)!, range: NSRange(location:userNameLocation,length:count(userName)))
// set label Attribute
cell.topLabel.attributedText = myMutableString
cell.messageLabel.text = "I FUCKING LOST AGAINST #olofmCS ON AIM AWP IN OVERTIME... GGgg"
cell.setNeedsUpdateConstraints()
cell.updateConstraintsIfNeeded()
return cell
}
The result of this can seen below, why is it not resizing the cell height?
The issue was related to the bottom constraint i had to set it to >= or another value