swift tableview with sections cannot use searchbar - ios

i have created a tableview with searchbar. My dataset looks like the following :
var data : [[ContactObject]] = []
Everything is working well but if i'm trying to search it doesnt really work.
Here is my search method:
func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
filteredGroups = self.data[1].filter({(bo: ContactObject ) -> Bool in
return bo.name!.lowercased().contains(searchText.lowercased())
})
filteredUsers = self.data[2].filter({(bo: ContactObject ) -> Bool in
return bo.name!.lowercased().contains(searchText.lowercased())
})
self.filteredData.append(self.myStories)
self.filteredData.append(self.filteredGroups )
self.filteredData.append(self.filteredUsers)
collectionView.reloadData()
}
i'm adding self.myStories always because its static content in my tableview. To show the suitable data i have extended my cell for item at like the following:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if !isFiltering(){
if data[indexPath.section][indexPath.row].name == "Freunde" || data[indexPath.section][indexPath.row].name == "Interessen (öffentlich)"{
var cell1 = tableView.dequeueReusableCell(withIdentifier: "selectStory", for: indexPath) as! StorySelectionTableViewCell
cell1.label.text = data[indexPath.section][indexPath.row].name
cell1.select.setOn(false, animated: true)
cell1.select.tag = indexPath.row
cell1.select.addTarget(self, action: #selector(handleSwitch), for: .valueChanged)
return cell1
}
var cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath) as! ContactsTableViewCell
cell.select.tag = indexPath.row
cell.thumb.layer.masksToBounds = false
cell.thumb.layer.cornerRadius = cell.thumb.frame.height/2
cell.thumb.clipsToBounds = true
cell.name.text = data[indexPath.section][indexPath.row].name
cell.select.addTarget(self, action: #selector(handleButtonPress), for: .touchDown)
if data[indexPath.section][indexPath.row].imageUrl != "" && data[indexPath.section][indexPath.row].imageUrl != nil{
let url = URL(string: data[indexPath.section][indexPath.row].imageUrl!)
cell.thumb.kf.setImage(with: url)
}
return cell
}else{
if filteredData[indexPath.section][indexPath.row].name == "Freunde" || filteredData[indexPath.section][indexPath.row].name == "Interessen (öffentlich)"{
var cell1 = tableView.dequeueReusableCell(withIdentifier: "selectStory", for: indexPath) as! StorySelectionTableViewCell
cell1.label.text = filteredData[indexPath.section][indexPath.row].name
cell1.select.setOn(false, animated: true)
cell1.select.tag = indexPath.row
cell1.select.addTarget(self, action: #selector(handleSwitch), for: .valueChanged)
return cell1
}
var cell = tableView.dequeueReusableCell(withIdentifier: "contactCell", for: indexPath) as! ContactsTableViewCell
cell.select.tag = indexPath.row
cell.thumb.layer.masksToBounds = false
cell.thumb.layer.cornerRadius = cell.thumb.frame.height/2
cell.thumb.clipsToBounds = true
cell.name.text = filteredData[indexPath.section][indexPath.row].name
cell.select.addTarget(self, action: #selector(handleButtonPress), for: .touchDown)
if data[indexPath.section][indexPath.row].imageUrl != "" && data[indexPath.section][indexPath.row].imageUrl != nil{
let url = URL(string: filteredData[indexPath.section][indexPath.row].imageUrl!)
cell.thumb.kf.setImage(with: url)
}
return cell
}
}
and my numbersOfRowsInSection like this:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if isFiltering(){
return filteredData[section].count
}
return data[section].count
}
the result is no matter which word i'm typing in, my third section (self.filteredUsers) is always empty and self.filteredGroups always complete.

This is just a guess, but I think you should not append to filteredData here:
self.filteredData.append(self.myStories)
self.filteredData.append(self.filteredGroups )
self.filteredData.append(self.filteredUsers)
This will make filteredData longer and longer, and the cellForRowAt only makes use of the first three items. You should instead replace the whole array with the three subarrays:
filteredData = [myStories, filteredGroups, filteredUsers]
The other thing I noticed is that you are reloading a collection view after the three lines above, but the search bar seems to be installed on a table view. Maybe you should be reloading the table view instead, or this is a mere typo.

Related

Swift 5 UITableViewCell : Expand one section and collapse the expanded section

I have implemented the following code to add expand/collapse feature to UITableView sections. When user click each section1, it expands and when we click the same section1 it collapses. But, I want the section1 to collapse, if I am expanding section2. How can I implement this feature to my code added below.
struct FaqData{
var faqHead = String()
var faqImage = String()
var questionArray : [(question : String, answer : String, answerurl : String)] = [(String,String,String)]()
var openSection = Bool()
}
var supportArray = [FaqData]()
func numberOfSections(in tableView: UITableView) -> Int {
return supportArray.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0{
return 1
}
else{
if supportArray[section].openSection == true{
return supportArray[section].questionArray.count + 1
}else{
return 1
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
tableView.separatorStyle = UITableViewCell.SeparatorStyle.none
if indexPath.section == 0{
let cell = tableView.dequeueReusableCell(withIdentifier: "SupportCenterID", for: indexPath) as! SupportCenterTableViewCell
cell.selectionStyle = UITableViewCell.SelectionStyle.none
cell.faqCollection.reloadData()
return cell
}
else{
if indexPath.row == 0{
let cell = tableView.dequeueReusableCell(withIdentifier: "SupportFaqID") as! SupportCenterFaqTableViewCell
cell.selectionStyle = UITableViewCell.SelectionStyle.none
let faqHead = supportArray[indexPath.section].faqHead
cell.imageText.text = faqHead.capitalized
cell.imageButton.setImage(UIImage(named: supportArray[indexPath.section].faqImage), for: .normal)
return cell
}
else{
let cell = tableView.dequeueReusableCell(withIdentifier: "QuestionID") as! SupportQuestionTableViewCell
cell.selectionStyle = UITableViewCell.SelectionStyle.none
cell.isSelected = true
cell.questionLabel.text = "Q.\(indexPath.row) " + supportArray[indexPath.section].questionArray[indexPath.row - 1].question
cell.answerLabel.text = supportArray[indexPath.section].questionArray[indexPath.row - 1].answer
print(supportArray[indexPath.section].questionArray[indexPath.row - 1].answerurl)
if supportArray[indexPath.section].questionArray[indexPath.row - 1].answerurl == ""{
cell.urlButton.isHidden = true
}
else{
cell.urlButton.isHidden = false
}
cell.urlButton.isHidden = true
cell.urlButton.tag = indexPath.row
UserDefaults.standard.set(indexPath.section, forKey: "SectionValue")
cell.urlButton.addTarget(self, action: #selector(urlButtonClicked(_:)), for: .touchUpInside)
cell.layoutMargins = UIEdgeInsets.zero
return cell
}
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if supportArray[indexPath.section].openSection == true{
if indexPath.section != 0{
if indexPath.row == 0{
let cell = tableView.cellForRow(at: indexPath) as! SupportCenterFaqTableViewCell
cell.faqView.backgroundColor = .white
cell.imageButton.tintColor = UIColor(hexString: "#D71B61")
cell.imageText.textColor = UIColor(hexString: "#D71B61")
}
}
supportArray[indexPath.section].openSection = false
let sections = IndexSet.init(integer: indexPath.section)
tableView.reloadSections(sections, with: .fade)
}
else{
supportArray[indexPath.section].openSection = true
let sections = IndexSet.init(integer: indexPath.section)
tableView.reloadSections(sections, with: .fade)
if indexPath.section != 0{
if indexPath.row == 0{
let cell = tableView.cellForRow(at: indexPath) as! SupportCenterFaqTableViewCell
cell.faqView.backgroundColor = UIColor(hexString: "#D71B61")
cell.imageButton.tintColor = .white
cell.imageText.textColor = .white
}
}
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
Can anyone provide a solution for this?
do this in didselecterow method. This is the else case of your condition
// You will need to reload multiple sections. So make an array.
var reloadSections = [Int]()
// find already opened array
if let alreadyOpenSection = supportArray.firstIndex(where: { (faq) -> Bool in
return faq.openSection
}) {
// if found, toggle the openSections bit
supportArray[alreadyOpenSection].openSection = false
// add it to reload sections array
reloadSections.append(alreadyOpenSection)
}
supportArray[indexPath.section].openSection = true
reloadSections.append(indexPath.section)
// create index set with reload sections array
let sections = IndexSet.init(reloadSections)
tableView.reloadSections(sections, with: .fade)
// below code is same
if indexPath.section != 0{
if indexPath.row == 0{
let cell = tableView.cellForRow(at: indexPath) as! SupportCenterFaqTableViewCell
cell.faqView.backgroundColor = UIColor(hexString: "#D71B61")
cell.imageButton.tintColor = .white
cell.imageText.textColor = .white
}
}

Table View Data is overridden

I have a UITableView. Its cell contains a label that will display a question, a yes button and a no button. The goal is to view questions one by one.
First I call the API to get the questions in the viewDidLoad method:
override func viewDidLoad() {
super.viewDidLoad()
tableView.allowsSelection = false
getQuestions(baseComplainID: "1") { (questions, error) in
self.questions = questions
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
In the cellForRowAt method I display them one by one:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? TableViewCell else {
fatalError("Fatal Error")
}
cell.yesButton.isHidden = false
cell.noButton.isHidden = false
if indexPath.row + 1 == displayNumber {
cell.questionLabel.text = questions[indexPath.row].question_name
} else {
cell.yesButton.isHidden = true
cell.noButton.isHidden = true
}
cell.yesButton.addTarget(self, action: #selector(action), for: .touchUpInside)
cell.noButton.addTarget(self, action: #selector(action), for: .touchUpInside)
return cell
}
and this is the action being executed on clicking yes or no:
#objc func action(sender: UIButton){
let indexPath = self.tableView.indexPathForRow(at: sender.convert(CGPoint.zero, to: self.tableView))
let cell = tableView.cellForRow(at: indexPath!) as? TableViewCell
cell?.yesButton.isEnabled = false
cell?.noButton.isEnabled = false
if sender == cell?.yesButton {
sender.setTitleColor(.black, for: .normal)
sender.backgroundColor = .green
} else {
sender.setTitleColor(.black, for: .normal)
sender.backgroundColor = .green
}
displayNumber += 1
self.tableView.reloadData()
}
Here I just change the background color of the button and increment the display number to display the next question.
All of this works perfect EXCEPT when I scroll, the data gets overridden and sometimes I find the question label empty and the questions replaces each other. I know this is normal due to the cell reusability but I don't know how to fix it.
Any suggestions please?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? TableViewCell else {
fatalError("Fatal Error")
}
cell.yesButton.isHidden = false
cell.noButton.isHidden = false
if indexPath.row + 1 == displayNumber {
cell.questionLabel.text = questions[indexPath.row].question_name
} else {
cell.yesButton.isHidden = true
cell.noButton.isHidden = true
}
cell.yesButton.addTarget(self, action: #selector(action), for: .touchUpInside)
cell.noButton.addTarget(self, action: #selector(action), for: .touchUpInside)
return cell
}
i feel like your issue lies here in cellForRowAt function.
you have this written
if indexPath.row + 1 == displayNumber { your code here }
but i am unsure as to why you need this.
you should be doing something like this inside cellForRowAt
let data = self.questions
data = data[indexPath.row]
cell.questionLabel.text = data.question_name
you should not be adding 1 to your indexPath.row
You're going to need to keep track of your yes's no's and neither's for each cell. I'd tack an enum onto another data structure along with your questions. Your primary problem was that you were only keeping track of your question. You need to keep track of your answer as well. That way, when you load a cell, you can configure each button with the colors that you want in cellForRow(at:)
struct QuestionAndAnswer {
enum Answer {
case yes
case no
case nada
}
var question: Question
var answer: Answer
}
And try not to reload your whole tableView when a button is pressed. tableView.reloadData() is expensive and distracting to the user. You should only be reloading the row that changed when a button was pressed.
Add callbacks on your cell so that you know which cell the corresponding buttons belong to. Notice how in the onYes and onNo callbacks we keep track of your "yes" or "no" selection then immediately reload the row below. When the row is reloaded, we finally know which color to make the button.
class AnswerCell: UITableViewCell {
#IBOutlet weak var yesButton: UIButton!
#IBOutlet weak var noButton: UIButton!
var onYes: (() -> Void)) = {}
var onNo: (() -> Void)) = {}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// ...
cell.yesButton.backgroundColor = qAndA.answer == .yes ? .green : .white
cell.noButton.backgroundColor = qAndA.answer == .no ? .green : .white
cell.onYes = {
questionsAndAnswers[indexPath.row].answer = .yes
tableView.reloadRows(at: [indexPath], with: .fade)
}
cell.onNo = {
questionsAndAnswers[indexPath.row].answer = .no
tableView.reloadRows(at: [indexPath], with: .fade)
}
// ...
}
Well, assume you have 10 questions, so a very simple and workaround fix is to declare a new array which has 10 elements as follow
var questionIsLoaded = Array(repeating:true , count 10)
the previous line will declare an array with 10 elements each element is bool which in our case will be true
then declare a function that handles if the question is loaded or not as follows, so if the question is loaded thus, the question with its indexPath should be marked as true and as a result, the yes and no buttons should be hidden else, the buttons should be shown
func handleQuestionIfLoaded(cell:yourCellType, indexPath:IndexPath) {
if questionIsLoaded[indexPath.row] , indexPath.row + 1 == displayNumber { {
questionIsLoaded[indexPath.row] = false
cell.questionLabel.text = questions[indexPath.row].question_name
cell.yesButton.isHidden = questionIsLoaded[indexPath.row]
cell.noButton.isHidden = questionIsLoaded[indexPath.row]
} else {
cell.yesButton.isHidden = questionIsLoaded[indexPath.row]
cell.noButton.isHidden = questionIsLoaded[indexPath.row]
}
cell.yesButton.addTarget(self, action: #selector(action), for: .touchUpInside)
cell.noButton.addTarget(self, action: #selector(action), for: .touchUpInside)
}
then replace the body of cellForRowAt with the function above, then your action function will be as follows
#objc func action(sender: UIButton){
let indexPath = self.tableView.indexPathForRow(at: sender.convert(CGPoint.zero, to: self.tableView))
let cell = tableView.cellForRow(at: indexPath!) as? TableViewCell
cell?.yesButton.isEnabled = questionIsLoaded[indexPath.row]
cell?.noButton.isEnabled = questionIsLoaded[indexPath.row]
if sender == cell?.yesButton {
sender.setTitleColor(.black, for: .normal)
sender.backgroundColor = .green
} else {
sender.setTitleColor(.black, for: .normal)
sender.backgroundColor = .green
}
displayNumber += 1
self.tableView.reloadData()
}
Now, your cells depend on an external dependency which is the array you have declared earlier, this means that when the cells are dequeued, they will be reused according to if the question is loaded or not by asking the array's element at the specific indexPath at first if the element is true or false

when I clicked checkbox inside a tableview the amount present inside one label should add to another label in iOS

I have checkbox and label inside a tableview and when we click checkbox the price present in label in each cell of tableview should add to another label which is present in another view
#IBAction func checkUncheckButtonAction(_ sender: UIButton) {
if let cell = sender.superview?.superview as? PrepaidPageTableViewCell
{
let indexPath = tableviewOutlet.indexPath(for: cell)
if cell.checkUncheckButtonOutlet.isSelected == false
{
cell.checkUncheckButtonOutlet.setImage(#imageLiteral(resourceName: "checked_blue"), for: .normal)
cell.checkUncheckButtonOutlet.isSelected = true
viewHeightConstraint.constant = 65
cell.amountOutlet.text = "₹ "+amount_receivable_from_customerArray[indexPath!.row]
isPrepaidOrder = false
tableviewOutlet.reloadData()
} else {
cell.checkUncheckButtonOutlet.setImage(#imageLiteral(resourceName: "unchecked_blue"), for: .normal)
cell.checkUncheckButtonOutlet.isSelected = false
self.viewHeightConstraint.constant = 0
tableviewOutlet.reloadData()
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PrepaidPageTableViewCell") as! PrepaidPageTableViewCell
cell.customerNameOutlet.text = buyer_nameArray[indexPath.row]
cell.deliverydateOutlet.text = "Delivery Date:\(dispatch_dateArray[indexPath.row])"
cell.amountOutlet.text = "₹\(amount_receivable_from_customerArray[indexPath.row])"
cell.dispatchidoutlet.text = "Dispatch ID: \(id_dispatch_summaryArray[indexPath.row])"
cell.dispatchdateOutlet.text = "Dispatch Date:\(dispatch_dateArray[indexPath.row])"
cell.checkUncheckButtonOutlet.setImage(#imageLiteral(resourceName: "unchecked_blue"), for: .normal)
cell.selectionStyle = .none
return cell
}

Issue with multiple selection and select all in UITableview in swift

In my application I have an multiple selection and select all option, I've tried by used below code but am facing an issue with selection.
If I press selectAll it checks and unchecks clearly and If suppose, I choose an single selection it selected but the selected cell is not higlighted.
Can you any one help me to figure out.
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.array.count
}
In cellForRowAtIndexPath ,
let cell = self.multipleSelectionTableview.dequeueReusableCell(withIdentifier:multiSelectionIdentifier , for: indexPath) as! MultipleSelectionCell
if self.selectedRows.contains(indexPath){
cell.checkBoxBtn.isSelected = true
cell.checkBoxBtn.setImage(UIImage.init(named: "check"), for: .normal)
} else {
cell.checkBoxBtn.isSelected = false
cell.checkBoxBtn.setImage(UIImage.init(named: "uncheck"), for: .normal)
}
if self.multipleSelectionStatusBtn.isSelected == true {
self.multipleSelectionStatusBtn.isSelected = true
cell.checkBoxBtn.setImage(UIImage.init(named: "check"), for: .normal)
} else {
self.multipleSelectionStatusBtn.isSelected = false
cell.checkBoxBtn.setImage(UIImage.init(named: "uncheck"), for: .normal)
}
cell.checkBoxBtn.tag = indexPath.row
return cell
In checkbox selection method,
let selectedIndexPath = IndexPath(row: sender.tag, section: 0)
self.multipleSelectionTableview.deselectRow(at: selectedIndexPath, animated: true)
if self.selectedRows.contains(selectedIndexPath)
{
self.selectedRows.remove(at: self.selectedRows.index(of: selectedIndexPath)!)
}
else
{
self.selectedRows.append(selectedIndexPath)
print(self.selectedRows)
}
self.multipleSelectionTableview.reloadData()
In selectAll method,
if (sender.isSelected == true)
{
sender.setImage(UIImage(named: "uncheck"), for: .normal)
sender.isSelected = false;
// isSelecting = false
self.selectedRows = self.getAllIndexpaths()
self.multipleSelectionTableview.reloadData()
}
else
{
// isSelecting = true
sender.setImage(UIImage(named: "check"), for: .normal)
sender.isSelected = true;
self.selectedRows = self.getAllIndexpaths()
self.multipleSelectionTableview.reloadData()
}
For getAllIndexPaths Method,
func getAllIndexpaths() -> [IndexPath] {
var indexPaths: [IndexPath] = []
for j in 0..<self.multipleSelectionTableview.numberOfRows(inSection: 0) {
indexPaths.append(IndexPath(row: j, section: 0))
}
return indexPaths
}
Actually you are reloading data when check box is checked or unchecked. That's the reason the table view doesn't keep the selection.
Solution.
You need to keep track of the selected index paths. And in cellForRowAt: you need to check that if it is the checked index path the you need to make cell highlight by changing its background colour otherwise set cell background colour white or something else.
For eg.
//In cellForRowAtIndexPath
if arrSelectedIndexPath.contains(indexPath) {
// checkbox is checked, change cell bg color
} else {
// checkbox is not checked
}
arrSelectedIndexPath is an [IndexPath] an array of index paths. When check box is selected you need to insert index path in an array and when check box is unchecked then you need to delete that index path from an array.
I am confused with your logic implementation in cellForRowAtIndexpath:
First you are checking if selectedRows array contains selected index path or not and setting the UI of checkBoxBtn:
let cell = self.multipleSelectionTableview.dequeueReusableCell(withIdentifier:multiSelectionIdentifier , for: indexPath) as! MultipleSelectionCell
if self.selectedRows.contains(indexPath){
cell.checkBoxBtn.isSelected = true
cell.checkBoxBtn.setImage(UIImage.init(named: "check"), for: .normal)
} else {
cell.checkBoxBtn.isSelected = false
cell.checkBoxBtn.setImage(UIImage.init(named: "uncheck[enter image description here][1]"), for: .normal)
}
Then again you are checking for multipleSelectionStatusBtn and changing the UI of checkBoxBtn :
if self.multipleSelectionStatusBtn.isSelected == true {
self.multipleSelectionStatusBtn.isSelected = true
cell.checkBoxBtn.setImage(UIImage.init(named: "check_timesheet"), for: .normal)
} else {
self.multipleSelectionStatusBtn.isSelected = false
cell.checkBoxBtn.setImage(UIImage.init(named: "uncheck_timesheet"), for: .normal)
}
cell.checkBoxBtn.tag = indexPath.row
return cell
When tableView will reload obviously this will work in multiple selection and not in single selection.
Change
In selectAll method :
if (sender.isSelected == true)
{
sender.setImage(UIImage(named: "uncheck"), for: .normal)
sender.isSelected = false;
// isSelecting = false
self.selectedRows.removeAll()
self.multipleSelectionTableview.reloadData()
}
else
{
// isSelecting = true
sender.setImage(UIImage(named: "check"), for: .normal)
sender.isSelected = true;
self.selectedRows = self.getAllIndexpaths()
self.multipleSelectionTableview.reloadData()
}
In cellForRowAtIndexPath :
let cell = self.multipleSelectionTableview.dequeueReusableCell(withIdentifier:multiSelectionIdentifier , for: indexPath) as! MultipleSelectionCell
if self.selectedRows.contains(indexPath){
cell.checkBoxBtn.isSelected = true
cell.checkBoxBtn.setImage(UIImage.init(named: "check"), for: .normal)
} else {
cell.checkBoxBtn.isSelected = false
cell.checkBoxBtn.setImage(UIImage.init(named: "uncheck[enter image description here][1]"), for: .normal)
}
if getTimeSheetJSON[indexPath.row]["TaskName"].string == "" {
cell.checkBoxBtn.isHidden = true
} else {
cell.checkBoxBtn.isHidden = false
}
cell.checkBoxBtn.tag = indexPath.row
return cell
Hope this works as I haven't compiled your code in Xcode.
You have to store selected index path in Array Like this Way you can do this easily.
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var selectedRow:[IndexPath] = []
#IBOutlet var tblView:UITableView!
override func viewDidLoad()
{
super.viewDidLoad()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section:
Int) -> Int
{
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
if cell == nil
{
cell = UITableViewCell(style: .subtitle, reuseIdentifier: "Cell")
}
cell?.textLabel?.text = String(format:"%#",indexPath.row)
if selectedRow.contains(indexPath)
{
cell?.accessoryType = .checkmark
}
else
{
cell?.accessoryType = .none
}
return cell!
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
{
if selectedRow.contains(indexPath)
{
// For Remove Row selection
selectedRow.remove(at: selectedRow.index(of: indexPath)!)
}
else
{
selectedRow.append(indexPath)
}
tableView.reloadData()
}
// Call this method for Select All
func selectAllCall()
{
var indexPaths: [IndexPath] = []
for j in 0..<100
{
indexPaths.append(IndexPath(row: j, section: 0))
}
selectedRow.removeAll()
selectedRow.append(contentsOf: indexPaths)
tblView.reloadData()
}
}

Let Cell appear and disappear depending on TextInput

I have 2 prototype cells.
One represents all the comments from the post.
This is initially presented.
If a user writes an "#" sign, a tableview with users he can choose to link appears.
My Problem is that the cells with users never disappear.
I want them to disappear if a cell is touched or if the user deletes the # sign.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if (commentTextField.text?.contains("#"))! {
let cellForUser = tableView.dequeueReusableCell(withIdentifier: "UserCell", for: indexPath) as! SuggestUserTableViewCell
let user = usersSuggestion[indexPath.row]
cellForUser.userSuggested = user
return cellForUser
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "CommentCell", for: indexPath) as! CommentTableViewCell
let comment = comments[indexPath.row]
let user = users[indexPath.row]
cell.tapMore.tag = indexPath.row
cell.comment = comment
cell.postId = postId
cell.user = user
cell.delegate = self
return cell
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let caption = commentTextField.text
let words = caption?.components(separatedBy: CharacterSet.whitespacesAndNewlines)
for var word in words! {
if word.hasPrefix("#") {
word = word.trimmingCharacters(in: CharacterSet.punctuationCharacters)
return usersSuggestion.count
}
}
return comments.count
}
Additionally I would like to have the cell2 with the users at the bottom, currently both start at the very top of the screen.
And I don't want to let the comments ever disappear, just decrease the opaqueness of the cell.
cell2 should disappear as soon as cell touched or # sign deleted.
Thanks in advance
Update Code
#objc func textFieldDidChange() {
doSearch()
if let commentText = commentTextField.text , !commentText.isEmpty {
sendButton.setTitleColor(UIColor.blue, for: UIControlState.normal)
sendButton.isEnabled = true
return
}
sendButton.setTitleColor(UIColor.lightGray, for: UIControlState.normal)
sendButton.isEnabled = false
}
func doSearch() {
let caption = commentTextField.text
let words = caption?.components(separatedBy: CharacterSet.whitespacesAndNewlines)
for var word in words! {
if word.hasPrefix("#") {
word = word.trimmingCharacters(in: CharacterSet.punctuationCharacters)
self.usersSuggestion.removeAll()
API.User.suggestUsers(withText: word, completion: { (user) in
self.usersSuggestion.insert(user, at: 0)
self.tableView.reloadData()
})
self.usersSuggestion.removeAll()
}else {
self.usersSuggestion.removeAll()
}
}
}
Instead of having the check for "#" in CellForRowAt, I think you should add a target to your text field with the action .editingChanged so that the check will fire each time there is a change.
Hope it helps.

Resources