swift tableview how to select all rows - swift

I have Button in tableview I want when I press that button will select all cell rows, how to do that? I tried alot but I got nothing
I'm so confused how to make the button contact the cell
I've tried to make var like this
var x = false
then I do like
if( x == true ) { //Code }
and when you press the button it will be true
but I don't know in which func I should put this ? and I don't know how to select all rows
Could someone help me how to Select \ Deselect all rows in cell when pressing button in tableview.
Thank you so much!

var selectedUsernameArray : NSMutableArray = []
var username1Array : NSMutableArray = ["hel","dsf","fsdg"]//just a sample
Initially button name should be "Select all"
Button action :
#IBAction func buttonAction(sender: UIButton) {
if(sender.titleLabel?.text == "Select all")
{
selectedUsernameArray .addObjectsFromArray(username1Array as [AnyObject])
sender.titleLabel?.text = "Deselect all"
}
else
{
selectedUsernameArray .removeAllObjects();
sender.titleLabel?.text = "Select all"
}
self.tableView .reloadData()
}
tableview delegate
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! UITableViewCell
var ob: AnyObject = username1Array .objectAtIndex(indexPath.row);
cell.textLabel?.text = ob as? String;
if(selectedUsernameArray .containsObject(ob))
{
cell.backgroundColor = UIColor.blueColor();
}
else
{
cell.backgroundColor = UIColor.whiteColor();
}
return cell
}

var isSelectAll = false; //global variable
isSelectAll = true;//on button action
self.tableView.reloadData()//on button action
in cellForRowAtIndexPath method
if(isSelectAll==true)
{
cell.backgroundColor = UIColor.blueColor();
}
else
{
cell.backgroundColor = UIColor.white();
}

In cellForRowAtIndexPath:
UITableViewCell *cell...
cell.accesoryType = isSelectAll ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;

Related

Select deselect the radio in uitableview section with array in ios swift

In tableview have different section.
Want to add the radio button for all the section.
Each section have individual select and deselect in tableview.
In first section choice1,[show in fig]
Selected cheese means cheese want to select, next if user click bacon means cheese automatically deselect.
[Here using radio button SSRadioButton class for click action. Create a radio button in tableview cell. how to write the button action for radio button. or suggest any new way].
Each radio button want individual select and deselect. The same process for all the section in tableview. how is possible help me. Thanks advance.
my code:
var radioControllerChoice : SSRadioButtonsController = SSRadioButtonsController()
var radioControllerDip : SSRadioButtonsController = SSRadioButtonsController()
func numberOfSections(in tableView: UITableView) -> Int {
return table_data.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of rows in the section.
return table_data[section].menu_id.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell:CustomiseTableViewCell = tableView.dequeueReusableCell(withIdentifier: "Customise") as! CustomiseTableViewCell
cell.name.text?=table_data[indexPath.section].menu_name[indexPath.row]
print(table_data[indexPath.section].customize[indexPath.row])
switch indexPath.section {
case 2:
radioControllerChoice.addButton(cell.radioBtn)
radioControllerChoice.shouldLetDeSelect = false
case 3:
radioControllerDip.addButton(cell.radioBtn)
radioControllerDip.shouldLetDeSelect = false
switch Int(table_data[indexPath.section].customize[indexPath.row]) {
case 1:
cell.radioBtn.isHidden = false
default:
print("Invalid choose")
cell.radioBtn.addTarget(self, action: #selector(ViewController.didSelectButton), for: .touchUpInside)
cell.radioBtn.tag = indexPath.row
}
}
}
func didSelectButton(selectedButton: UIButton?)
{
/// need solution for button action help me..
}
You can use UIButton instead of SSRadioButton, and then you can change the image of button for checked and unchecked radio button.
Swift3.2:
CustomiseTableViewCell
import UIKit
protocol CustomTableViewCellDelegate {
func didToggleRadioButton(_ indexPath: IndexPath)
}
class CustomiseTableViewCell: UITableViewCell {
#IBOutlet weak var itemLabel: UILabel!
#IBOutlet weak var radioButton: UIButton!
var delegate: CustomTableViewCellDelegate?
func initCellItem() {
let deselectedImage = UIImage(named: "ic_radio_button_unchecked_white")?.withRenderingMode(.alwaysTemplate)
let selectedImage = UIImage(named: "ic_radio_button_checked_white")?.withRenderingMode(.alwaysTemplate)
radioButton.setImage(deselectedImage, for: .normal)
radioButton.setImage(selectedImage, for: .selected)
radioButton.addTarget(self, action: #selector(self.radioButtonTapped), for: .touchUpInside)
}
func radioButtonTapped(_ radioButton: UIButton) {
print("radio button tapped")
let isSelected = !self.radioButton.isSelected
self.radioButton.isSelected = isSelected
if isSelected {
deselectOtherButton()
}
let tableView = self.superview as! UITableView
let tappedCellIndexPath = tableView.indexPath(for: self)!
delegate?.didToggleRadioButton(tappedCellIndexPath)
}
func deselectOtherButton() {
let tableView = self.superview?.superview as! UITableView
let tappedCellIndexPath = tableView.indexPath(for: self)!
let indexPaths = tableView.indexPathsForVisibleRows
for indexPath in indexPaths! {
if indexPath.row != tappedCellIndexPath.row && indexPath.section == tappedCellIndexPath.section {
let cell = tableView.cellForRow(at: IndexPath(row: indexPath.row, section: indexPath.section)) as! CustomiseTableViewCell
cell.radioButton.isSelected = false
}
}
}
}
Call initCellItem method from UITableViewDataSource's delegate method:
// Your ViewController
let menuList = [ ["Cheese", "Bacon", "Egg"],
["Fanta", "Lift", "Coke"] ] // Inside your ViewController
var selectedElement = [Int : String]()
func didToggleRadioButton(_ indexPath: IndexPath) {
let section = indexPath.section
let data = menuList[section][indexPath.row]
if let previousItem = selectedElement[section] {
if previousItem == data {
selectedElement.removeValue(forKey: section)
return
}
}
selectedElement.updateValue(data, forKey: section)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell:CustomiseTableViewCell =
tableView.dequeueReusableCell(withIdentifier: "Customise") as! CustomiseTableViewCell
let item = menuList[indexPath.section][indexPath.row]
cell.itemLabel.text = item
if item == selectedElement[indexPath.section] {
cell.radioButton.isSelected = true
} else {
cell.radioButton.isSelected = false
}
cell.initCellItem()
cell.delegate = self
// Your logic....
return cell
}
Alternate way:
You can use simple UIButton instead of any third party library (SSRadioButton) and use it like:
Set the UIButton's image in default state to - circle (as in the screenshot)
Set the UIButton's image in selected state to - filled circle
UIButton's action event can be captured in a normal way like you do in any other case.
Something like this:
Let me know if you want to follow this approach or need any kind of help regarding this.

Why my checkbox in custom cell shows different behaviour while selecting and scrolling in swift?

I have a xib view in which I took a tableView with a customcell xib. In this custom cell I have a checkbox button which behaves like check and uncheck using custom cell. But when ever I click the first cell checkbox as tick the multiple of 9th cell like 9th row cell, 18th row cell, .....also became ticked. and while scrolling the checkbox tick option is changing between cells. I am not able to know why this is happening..??
I have registered cell xib view as:
override func viewDidLoad() {
super.viewDidLoad()
//Register custom cell
let nib = UINib(nibName: "CustomOneCell", bundle: nil)
AddOnTableView.registerNib(nib, forCellReuseIdentifier: "addoncell")
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return ADDONITEMS.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:CustomOneCell = AddOnTableView.dequeueReusableCellWithIdentifier("addoncell") as! CustomOneCell
let item: AddOnItems = ADDONITEMS[indexPath.row]
cell.addOnName.text = item.name
cell.addOnPrice.text = "£\(item.price!)"
return cell
}
For checkbox I have added a custom class as below:
var isCheckedAddOnGlobal = Bool()
class AddOnCheckBox: UIButton {
let checkedImage = UIImage(named: "checkboxredtick.png")! as UIImage
let unCheckedImage = UIImage(named:"checkbox untick.png")!as UIImage
//bool property
var ischecked:Bool = false{
didSet{
//print(ischecked)
if ischecked == true{
self.setImage(checkedImage, forState: .Normal)
}else{
self.setImage(unCheckedImage, forState: .Normal)
}
}
}
override func awakeFromNib() {
self.addTarget(self, action:#selector(CheckBox.buttonClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside)
self.ischecked = false
}
func buttonClicked(sender: UIButton) {
if (sender == self) {
if ischecked == true{
ischecked = false
isCheckedAddOnGlobal = false
}else{
ischecked = true
isCheckedAddOnGlobal = true
}
}
}
}
This is happening because you are reusing the TableViewCell, To solve your problem you can try something like this, first create an array of Int that give you selected row and use that array inside cellForRowAtIndexPath method.
var selectedItems = [Int]()
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell:CustomOneCell = AddO nTableView.dequeueReusableCellWithIdentifier("addoncell") as! CustomOneCell
let item: AddOnItems = ADDONITEMS[indexPath.row]
cell.addOnName.text = item.name
cell.addOnPrice.text = "£\(item.price!)"
cell.checkBoxBtn.tag = indexPath.row
if (selectedItems.contains(indexPath.row)) {
cell.checkBoxBtn.setImage(UIImage(named:"checkbox untick.png"), forState: .Normal)
}
else {
cell.checkBoxBtn.setImage(UIImage(named: "checkboxredtick.png"), forState: .Normal)
}
cell.checkBoxBtn.addTarget(self, action:#selector(self.buttonClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside)
return cell
}
func buttonClicked(sender: UIButton) {
if (self.selectedItems.contains(sender.tag)) {
let index = self.selectedItems.indexOf(sender.tag)
self.selectedItems.removeAtIndex(index)
}
else {
self.selectedItems.append(sender.tag)
}
self.tableView.reloadData()
}
Best way is on selecting cell call
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! CustomOneCell
cell.buttonClicked()
}
and change buttonClicked method to
func buttonClicked() {
...
}
I would make an object, which contains the product information and a boolean, to check if the product has been selected or not.
If you make it this way, the checkmarks will appear correct. When you are scrolling on a tableview, then it loads the data everytime it shows new cells.
Right now, it only knows that the index etc. 9 is selected, and when you scroll down and load new cells, then the index 9 will be selected automatic again.
Try something like this:
Example
class Product {
var productName = "Test"
var isSelected: Bool = false
}
Under your cellForRowAtIndexPath
if product.isSelected == true {
cell.checkBoxBtn.setImage(UIImage(named:"checkbox untick.png"), forState: .Normal)
} else {
cell.checkBoxBtn.setImage(UIImage(named: "checkboxredtick.png"), forState: .Normal)
}

UITableview with custom cells

Hi I am having a problem in my app
I am using UITableView with the custom cell. In each cell, I have a
checkbox, when I check it, it is getting the cell’s element into a
set. Everything is working correctly except a small problem.
The Problem:
2
As in the image when I click on the first row, the 10th row is seeming
like checked. The image changed to checked but in practice, it did
not occur in my set.
Here is the related part of the code
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: TblCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as! TblCell
cell.labelInCell.text = tableData[indexPath.row]//data.myFunc().myset[indexPath.row]
cell.checkBoxInCell.tag = indexPath.row
cell.checkBoxInCell.addTarget(self, action: Selector("yourCheckBoxClicked:"), forControlEvents: .TouchUpInside)
// cell.images.image = UIImage(named: tableData[indexPath.row])
// if images name is same as in tableData put it in front of label
return cell
}
func yourCheckBoxClicked(cbx:UIButton){
let picked = self.tableData[cbx.tag]
if choosenSet.contains(picked) {
choosenSet.remove(picked) // uncheck
} else {
choosenSet.insert(picked) // check
}
print(choosenSet)
}
Number of rows in section ->
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
Checkboxes class ->
class checkBox: UIButton {
//images
let checkedImage = UIImage(named: "button_checkboxFilled")
let uncheckedImage = UIImage(named: "button_checkboxEmpty")
// Bool Property
var isChecked : Bool = false {
didSet{
if isChecked == true{
self.setImage(checkedImage, forState: .Normal)
}else {
self.setImage(uncheckedImage, forState: .Normal)
}
}
}
override func awakeFromNib() {
self.addTarget(self, action: "buttonClicked:" , forControlEvents: UIControlEvents.TouchUpInside)
self.isChecked = false
}
func buttonClicked (sender:UIButton) {
if (sender == self) {
if isChecked == true {
isChecked = false
}else {
isChecked = true
}
}
}
}
This is because of cells reusage. You should just add this line to your func tableView(tableView:cellForRowAtIndexPath:) method:
cell.checkBoxInCell.isChecked = choosenSet.contains(tableData[indexPath.row])
Your cells are reused, quick solution which will work fine as your table view doesn't have a lot of cells:
let cell: TblCell = self.tableView.dequeueReusableCellWithIdentifier("cell" + String(indexPath.row)) as! TblCell
If your tableView has many rows than you should have "cell" identifier and update the selection style on each cellForRowAtIndexPath call

Remove the subView inside Cell

In my ViewController, I have a variable:
var shareButtonTapped = false
I want when I click the shareButton on the navigationBar, it will show the shareButton all of the cell, except the cell which indexPath.row == 0.
Here is the action of shareButton:
#IBAction func shareButtonTapped(sender: AnyObject) {
shareButtonTapped = !shareButtonTapped
collectionView.reloadData()
}
And here is the CollectionViewDataSource method:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! GiftCollectionViewCell
if shareButtonTapped {
cell.gift = gifts[indexPath.row]
let shareButton = FBSDKShareButton(frame: CGRect(x: 0, y: 0, width: 80, height: 30))
shareButton.tag = 1
let photo = FBSDKSharePhoto()
photo.image = gifts[indexPath.row].image
photo.userGenerated = true
let content = FBSDKSharePhotoContent()
content.photos = [photo]
content.contentURL = NSURL(string: "http://www.fantageek.com")
shareButton.shareContent = content
cell.contentView.addSubview(shareButton)
return cell
} else {
cell.gift = gifts[indexPath.row]
return cell
}
}
It worked:
But I want to click this shareButton on NavigationBar again, all of shareButton inside each cell will disappear. How to do this?
Any helps would be appreciated. Thanks.
Use removeFromSuperview() method inside your else block:
else {
cell.gift = gifts[indexPath.row]
for subview in cell.contentView.subviews {
if subview is FBSDKShareButton {
subview.removeFromSuperview()
}
}
return cell
}
Better approach will be to keep the share button always be part of cell. And show and hide the button based on status of shareButtonTapped of bar button.
Let's say your button name is shareImage then in cellForRow
cell.shareButton.hidden = false
if(shareButtonTapped){
cell.shareButton.hidden = true
}

when I search through search controller, indexPath doesn't change with original array

I did implement search page in my app. I put PFObjects in postsArray, when user searching something, searched object goes in filteredArray. that is what I tried to do.
tableView shows result, but when I tap on it, it show postArray indexPath which is indexPath before I search it. For example, original(postsArray) first item is red, and I searched yello, when I tap yellow tableView Cell, it shows red post.
here is my code for this.
override func viewDidLoad() {
super.viewDidLoad()
self.resultSearchController = UISearchController(searchResultsController: nil)
self.resultSearchController.searchResultsUpdater = self
self.resultSearchController.dimsBackgroundDuringPresentation = false
self.resultSearchController.searchBar.sizeToFit()
self.myTable.tableHeaderView = self.resultSearchController.searchBar
self.myTable.reloadData()
self.bringAllDatafromParse()
}
func updateSearchResultsForSearchController(searchController: UISearchController) {
self.filterdArray.removeAllObjects()
let normalizedSearchText =
searchController.searchBar.text!.lowercaseString
for posts in self.postsArray {
var title = ""
var tag = ""
if let titleText = posts["titleText"] as? String {
title = titleText
}
if let tagText = posts["tagText"] as? String {
tag = tagText
}
let results = "\(title) \(tag)"
if results.lowercaseString.rangeOfString(normalizedSearchText) != nil {
self.filterdArray.addObject(posts)
}
}
self.myTable.reloadData()
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
if self.resultSearchController.active{
return self.filterdArray.count
}else
{
return self.postsArray.count
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("myCell", forIndexPath: indexPath) as! SearchTVCE
//cell.textLabel!.text = searchResults[indexPath.row]
var postObjects : PFObject!
if self.resultSearchController.active{
postObjects = self.filterdArray.objectAtIndex(indexPath.row) as! PFObject
}else {
postObjects = self.postsArray.objectAtIndex(indexPath.row) as! PFObject
}
//솔드
cell.soldLabel.hidden = true
if (postObjects.objectForKey("sold") as! Bool) == true {
cell.soldLabel.hidden = false
}
// 제목
cell.titleLabel.text = (postObjects.objectForKey("titleText") as! String)
+ " : " + (postObjects.objectForKey("tagText") as! String)
return cell
}
My question is how can I get right indexPath after I get result from search bar.
And after I search and tap on it, it goes another view. but the searchbar doesn't disappear unless I tap on cancel bar button. How do I fix this?
Your code looks good.
However, you are not showing your didSelectRowAtIndexPath function which might give clue for your problem.
My guess is - you are getting index path correct as you are always linking self.filterdArray on tableview. As I understand, everything on UI looks good but only when you tap on first cell, new view controller is loaded with the data that belongs to first cell of non-filtered array. I would advise you to put a check on your didSelectRowAtIndexPath and see if data is being fetched correctly. It should look something like this:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
if (self.resultSearchController.active) {
myData = (self.filterdArray[indexPath.row])!
} else {
myData = (self.postsArray[indexPath.row])!
}
self.performSegueWithIdentifier("MySegue", sender: self)
}
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
if (segue.identifier == "MySegue") {
let myViewController = segue.destinationViewController as MyViewController
myViewController.data = self.myData
}
}
And to your other question:
searchbar doesn't disappear unless I tap on cancel bar button. How do
I fix this?
Just call : searchController.active = false