I have a tableView where I want to display different Cells depending on what a variable seguedDisplayMonth is set to. Is this possible and if so can I get any hint on how to do this? I've tried the following but it doesn't seem to work.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Income Cell", forIndexPath: indexPath)
let income = myIncomeArray[indexPath.row]
if seguedDisplayMonth == "All" {
var text = "\(income.money) kr"
cell.textLabel?.text = text
cell.detailTextLabel?.text = income.name
}
return cell
}
I also thought that maybe I need to reload the data after changing the seguedDisplayMonth which gets changed from a different tableView and through a segue.
Call mcTableSwag.reloadData() once seguedDisplayMonth is changed. (Likely call it in the function that actually changes seguedDisplayMonth.
Alternatively you could reload certian cells with some method like reloadVisibleCellsAtIndexPath(...) (Im not sure what it is called exactly, but it should be on the Apple UITableView documentation.
I managed to fix it finally. I will explain how I did it incase anyone runs into the same problem.
I implemented another array myVisibleIncomeArray.
In viewDidLoad() I called a function which does the following:
for inc in myIncomeArray {
if self.monthLabel.text == "All" {
self.myVisibleIncomeArray.append(inc)
totalSum += inc.money
print("Added to myVisible")
}
}
Then I reloadData() and use myVisibleIncomeArray for the other functions.
Not sure if it was the smartest fix, but it's a fix nonetheless.
Related
I am trying to make a list of contacts, and programmatically putting a star near each name where the family name is equal to a certain string, exactly like the picture below.
But in fact, the problem is that when this star appears on a certain cell, when scrolling down or up, nearly the other cells will also have the star appearing. (It's like coronavirus, spreading everywhere).
Is anyone able to help me fix this problem?
This is my code for the TableView:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item = self.tableArray[indexPath.row]
let cell:SLF_LabelIconCell = tableView.dequeueReusableCell(withIdentifier: SLF_LabelIconCell.className) as? SLF_LabelIconCell ?? SLF_LabelIconCell()
//Add a star near favorite contacts
if item.familyName == "Zaghrini"{
cell.favoriteIcon.isHidden=false
}
return cell
}
At first glace, it appears correctly
But after scrolling up and down, more stars appears:
Try this:
if item.familyName == "Zaghrini" {
cell.favoriteIcon.isHidden = false
} else {
cell.favoriteIcon.isHidden = true
}
Why are you putting that in the cellForRowAt? Get it out of there. That should be for data only.
Use willDisplay instead.
After any row is deleted by deleteRows(at:with:) from my Table View, I cannot get textfield in a reusable custom cell to get focus by becomeFirstResponder() (which is called after insertRows(at:with:) is called). becomeFirstResponder() is always called within cellForRow(at:).
This problem always starts occuring after a row is deleted from the table view by deleteRows(at:with:). Before any row is deleted there is no problem, becomeFirstResponder() can give focus to the textfield as intended.
I made some tests to understand why this problem occurs after a row is deleted... My tests showed an interesting difference:
Case 1: After any row is deleted (i.e. while becomeFirstResponder() returns false), textFieldShouldBeginEditing(_:) is called BEFORE cellForRow(at:) returns. textFieldDidBeginEditing(_:) is never called.
Case 2: On the other hand, before any row is deleted (i.e. while becomeFirstResponder() returns true), textFieldShouldBeginEditing(_:) is called AFTER cellForRow(at:) returns. textFieldDidBeginEditing(_:) is called immediately after textFieldShouldBeginEditing(_:), as expected.
The problem might be related to this difference, but I couldn't solve this mystery after trying & researching for many hours.
In a related Q&A, it is suggested not to reload tableView from within textFieldDidEndEditing(). In my case, deleteRows(at:with:) method are sometimes called from within textFieldDidEndEditing() and sometimes called from tableView(_:commit:forRowAt:) (i.e. by swiping to left). So this does not explain my problem. Another related Q&A might be this one.
getFocus() in CustomCell's class, called from cellForRow(at:) in TableViewController:
func getFocus() {
if let itemTextField = itemTextField {
itemTextField.delegate = self
itemTextField.isUserInteractionEnabled = true
itemTextField.becomeFirstResponder()
}
}
cellForRow(at:):
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let item = items[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCell", for: indexPath) as! CustomCell
cell.setCell(item: item)
cell.delegate = self
if insertingRow == true {
if isTempItem(item: item, indexPath: indexPath) {
cell.getFocus()
} else {
print("isTempItem returned false, no need to give focus.")
}
}
return cell
}
Don't call getFocus in cellForRowAt, Insteed of when you insert new row, You can scroll to new row and call getFocus in willDisplayCell.
Hope to help you.
I've sought answers for this simple question for four hours all over the Internet and yet I am still lost. I am a beginner in Xcode which might explain all the confusion for me.
As you see from the image, I want to add a button in the tableview that directs to the home screen of my app. So I added an additional tableviewcell and put the following code into the tableviewcontroller.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if (indexPath.row == 0){
let cell: UITableViewCell = HomeButtonTableViewCell(style: UITableViewCellStyle.Default,
reuseIdentifier: "LetsGoHome")
return cell
}
else{
let cell = self.tableView.dequeueReusableCellWithIdentifier("WordListTableCell", forIndexPath: indexPath) as! WordListTableViewCell
let row = indexPath.row - 1
cell.formulaLabel.font = UIFont.preferredFontForTextStyle(UIFontTextStyleHeadline)
cell.formulaLabel.text = wordListObject.quizList[row]
cell.formulaImage.image = UIImage(named: formulaImages[row])
return cell
}
}
Perhaps I'm not telling you enough about what I did, but what I know for sure is that (although most answers related to this question suggest doing this) bringSubviewToFront doesn't work no matter in what way I try it.
Please give suggestions as to what other area I could have made a mistake and if there's a better way for me to navigate from the tableview screen to my home screen. I would also like suggestions.
It would better to use a Navigation Controller for this.
Storyboard example
I'm trying to create an autocompleter using iOS 8, Swift and Xcode 6.3
I have a problem that I'm trying to solve, but I gave up... I hope someone can help here. The problem is that (custom) UITableViewCell's are not displaying when the initial dataSource is empty. When adding data to datasource and reloading the tableView, the cells SHOULD display, but they don't... At least, the first time they don't... A second time, they DO... When I initialize the table with non-empty data, the problem doesn't occur. I guess something goes wrong with dequeueReusableCellWithIdentifier. In beginning, no reusable cells are found, or something. But I don't know why...
Relevant code, in ViewController.swift:
// filteredWords is a [String] with zero or more items
#IBAction func editingChanged(sender: UITextField) {
autocompleteTableView.hidden = sender.text.isEmpty
filteredWords = dataManager.getFilteredWords(sender.text)
refreshUI()
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! AutocompleteTableViewCell
cell.title.text = filteredWords[indexPath.row]
return cell
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return filteredWords.count
}
func refreshUI() {
self.autocompleteTableView.reloadData()
}
I created a sample project on github:
https://github.com/dirkpostma/swift-autocomplete
And a movie on YoutTube to show what goes wrong:
https://www.youtube.com/watch?v=ByMsy4AaHYI
Can anyone look at it and spot the bug...?
Thanks in advance!
You've accidentally hidden your cell.
Open Main.storyboard
Select Cell
Uncheck Hidden
Side note: As for why it's displaying the second time around with the cell hidden? It appears to be a bug. It should still be hidden (print cell.hidden, notice it's always true despite showing the text on the screen).
I think you need to change your code. Check out below code. It is because if you remember in Objective C you needed to check if the Cell was nil and then initialise it. The reuse identifier is usually reusing an already created cell, but on the first launch this does not work because there is no Cell to use. Your current code assumes always that the cell is created (re-used) because you are using ! in the declaration, so if you use the optional (?) it can be null and you then can create the cell
var cell = tableView.dequeueReusableCellWithIdentifier("Cell") as? AutocompleteTableViewCell
if cell == nil
{
//You should replace this with your initialisation of custom cell
cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: "CELL")
}
cell.title.text = filteredWords[indexPath.row]
return cell
I'm trying to make an app for iOS 8, using swift. The goal here is to make a kind of news feed. This feed displays posts from users, which follows a certain pattern.
I thought of using the UITableView where each cell follows a custom layout. The problem appears when I try to access a text label inside it. I try to access it by its tag, but when I do it, the whole app crashes. The error reported is "Swift dynamic cast failed", and I'm using the following code to access the view:
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cellId: String = "cell"
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier(cellId) as UITableViewCell
if let ip = indexPath{
cell.textLabel.text = myData[ip.row] as String
var lbl = cell.contentView.viewWithTag(0) as UILabel
lbl.text = "ola"
}
return cell
}
Am I doing something wrong? Thanks in advance!
i think the Problem is the Tag 0. All Views are on default value 0. So try another tag value.
Just faced the same issue. The solution was to change tag to 10 and 20. I used 1 and 2 before. Is anybody aware of a range of tags that is used by the system?
So my 'cellForRowAtIndexPath' for a table with an image and a label per row looks like this now:
internal func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCellWithIdentifier("cellIdentifier") as? UITableViewCell {
(cell.contentView.viewWithTag(10) as UIImageView).image = IMAGES[indexPath.row]
(cell.contentView.viewWithTag(20) as UILabel).text = LABELS[indexPath.row]
return cell
} else {
NSLog("Prototype did not work")
return UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "errorIdentifier")
}
}
Change the 0 to 1 or another tag, it work for me.
0 is overlapping to another cell label's tag.