create a group from selected tableview cells - ios

I am trying to send the checked rows from my table view into a newly created group to my firebase database, once the user selects the rows and the checkmark is displayed, how can I send the selected rows information to my database. I am not sure if I should be doing this in the didSelectRowAt function or to add a "create group" button once the rows are selected. Any information will be helpful thank you.
import UIKit
class FriendsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var userList = [Users]()
#IBOutlet weak var myTableView: UITableView!
final let urlString = "https://api.lookfwd.io/v1/test/users"
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return userList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let myCell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
myCell.selectionStyle = UITableViewCellSelectionStyle.none
myCell.nameLabel.text = userList[indexPath.row].name
return myCell
}
override func viewDidLoad() {
super.viewDidLoad()
self.downloadJsonWithTask()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if myTableView.cellForRow(at: indexPath)?.accessoryType == UITableViewCellAccessoryType.checkmark{
myTableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCellAccessoryType.none}
else{
myTableView.cellForRow(at: indexPath)?.accessoryType = UITableViewCellAccessoryType.checkmark
}
}
func downloadJsonWithTask() {
let url = NSURL(string: urlString)
var downloadTask = URLRequest(url: (url as URL?)!, cachePolicy: URLRequest.CachePolicy.reloadIgnoringCacheData, timeoutInterval: 20)
downloadTask.httpMethod = "GET"
URLSession.shared.dataTask(with: downloadTask, completionHandler: {(data, response, error) -> Void in
if let response = data {
if let jsonData = try? JSONSerialization.jsonObject(with: response, options: .allowFragments) as? [String:Any] {
if let dataArray = (jsonData as AnyObject).value(forKey: "users") as? [[String:Any]] {
for data in dataArray{
let newUser = Users(data: data)
self.userList.append(newUser)
print(jsonData!)
}
}
OperationQueue.main.addOperation({
for use in self.userList {
print(use.name ?? "")
}
self.myTableView.reloadData()
})
print(jsonData!)
}
}
}).resume()
}
}

The best way to achieve this to add a button instead of checkbox, set the images of checkbox for the selected and default state of button and in your "cellForRowAt" method do this:
In your "cellForRowAt" method:
let button = cell.viewWithTag(123) as? UIButton // 123 is tag that is defined in Stoyboard for this button/checkbox.
button.accessibilityHint = "\(indexPath.row)"
button.addTarget(self, action: "action:", forControlEvents:
UIControlEvents.TouchUpInside)
Paste this method any where in your ViewController:
func action(sender:UIButton!) {
let position = Int(sender.accessibilityHint) // This is the position that will help you to get the specific item from your list.
if (sender.selected == true)
{
sender.setBackgroundImage(UIImage(named: "box"), forState:
UIControlState.Normal)
sender.selected = false
// Remove from Datbase
}
else
{
sender.setBackgroundImage(UIImage(named: "checkBox"), forState:
UIControlState.Normal)
sender.selected = true
// Add into database.
}
}
This is a method of a button directly connected from Storyboard to ViewController. For your table view you have o follow these steps:
Get your button in "cellForIndexAt" method with Tag.
Set "accessibilityHint" of your button with "indexPath.row".
Add target to your button.
Get the position through "accessibilityHint" in your targeted method.
Use logic given above in your targeted method.
But if you don't want to go through all this process then simply add your item in databse in your "didSelectRowAt" method, but it will perform the action wherever user taps on the whole cell.

Related

Is there a way to get the id of a UITableViewCell?

my problem: I want to open some kind of Profil if a user pushes a Button in a Table-View Cell. The Cells Data is downloaded from Parse.
The idea is based on Instagram, if you click on the username-button on Insta the profile from the user who posted the image will open. I want to create the same code, but i can't create the code to get the user. Can you help me?
Heres some code:
import UIKit
import Parse
class HomeController: UIViewController, UITableViewDelegate, UITableViewDataSource {
private let reuseIdentifer = "FeedCell"
var delegate: HomeControllerDelegate?
var newCenterController: UIViewController!
let tableView = UITableView()
//Für Parse:
var users = [String: String]()
var comments = [String]()
var usernames = [String]()
var lastnames = [String]()
var imageFiles = [PFFileObject]()
var wischen: UISwipeGestureRecognizer!
var wischen2: UISwipeGestureRecognizer!
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
getData()
configureNavigationBar()
configurateTableView()
wischen = UISwipeGestureRecognizer()
wischen.addTarget(self, action: #selector(handleMenuToggle))
wischen.direction = .right
wischen.numberOfTouchesRequired = 1
view.addGestureRecognizer(wischen)
wischen2 = UISwipeGestureRecognizer()
wischen2.addTarget(self, action: #selector(handleMenuToggle))
wischen2.direction = .left
wischen2.numberOfTouchesRequired = 1
view.addGestureRecognizer(wischen2)
}
#objc func handleMenuToggle() {
delegate?.handleMenuToggle(forMenuOption: nil)
}
#objc func showProfile() {
let vc: AProfileViewController!
vc = AProfileViewController()
vc.modalPresentationStyle = .fullScreen
present(vc, animated: true)
}
func configureNavigationBar() {
navigationController?.navigationBar.barTintColor = .darkGray
navigationController?.navigationBar.barStyle = .black
navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.font: UIFont(name: "Noteworthy", size: 22)!, NSAttributedString.Key.foregroundColor: UIColor.white]
//navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
navigationItem.title = "Mobile Job Board"
navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "ic_menu_white_3x").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(handleMenuToggle))
navigationItem.rightBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "ic_mail_outline_white_2x").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(showCreateNewArticle))
}
//MARK: Table View
//skiped table view configuration
}
// - MARK: Table view data source
func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return comments.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifer, for: indexPath) as! FeedCell
imageFiles[indexPath.row].getDataInBackground { (data, error) in
if let imageData = data {
if let imageToDisplay = UIImage(data: imageData) {
cell.postImage.image = imageToDisplay
}
}
}
cell.descriptionLabel.text = comments[indexPath.row]
cell.userButton.setTitle("\(usernames[indexPath.row]) \(lastnames[indexPath.row])", for: UIControl.State.normal)
cell.userButton.addTarget(self, action: #selector(showProfile), for: .touchUpInside)
return cell
}
//skiped
}
Thanks a lot!
Tom
The issue here is that your button works on a selector and it has no idea about the sender or where it was called from.
I would do this by creating a custom table view cell (e.g. FeedCell) which allows you to set a delegate (e.g. FeedCellDelegate). Set your class as the delegate for the cell and pass into the cell it's current indexPath. You can then return the indexPath in the delegate call.
Example: Note that code has been removed for simplicity and this code has not been tested. This is simply to guide you in the right direction.
View Controller
import UIKit
class HomeController: UIViewController {
// stripped additional information for example
func showProfile(_ username: String) {
let vc: AProfileViewController!
vc = AProfileViewController()
vc.username = username
vc.modalPresentationStyle = .fullScreen
present(vc, animated: true)
}
}
extension HomeController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return comments.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifer, for: indexPath) as! FeedCell
cell.delegate = self
cell.descriptionLabel.text = comments[indexPath.row]
cell.userButton.setTitle("\(usernames[indexPath.row]) \(lastnames[indexPath.row])", for: UIControl.State.normal)
cell.setIndex(indexPath)
return cell
}
}
extension HomeController: FeedCellDelegate {
func didPressButton(_ indexPath: IndexPath) {
let userName = usernames[indexPath.row]
showProfile(username)
}
}
Feed Cell
import UIKit
protocol FeedCellDelegate {
didPressButton(_ indexPath: IndexPath)
}
class FeedCell: UICollectionViewCell {
var delegate: FeedCellDelegate?
var indexPath: IndexPath
#IBOutlet weak var userButton: UIButton
setIndex(_ indexPath: IndexPath) {
self.indexPath = indexPath
}
#IBAction userButtonPressed() {
if(delegate != nil) {
delegate?.didPressButton(indexPath)
}
}
}
You can generically and in a type safe way get the parent responder of any responder with:
extension UIResponder {
func firstParent<T: UIResponder>(ofType type: T.Type ) -> T? {
return next as? T ?? next.flatMap { $0.firstParent(ofType: type) }
}
}
So:
Get the parent tableviewCell of your button in the target action function
Ask your tableview for the index path
Use the index path.row to index into your users array:
#objc func showProfile(_ sender: UIButton) {
guard let cell = firstParent(ofType: UITableViewCell.self),
let indexPath = tableView.indexPath(for: cell) else {
return
}
let user = users[indexPath.row]
... do other stuff here ...
}

Getting TableViewCell Index is nil on dropdown item selection

I want tableviewcell index on dropdown item selection. But the index is nil when I am clicking on dropdown item. Is there any way to get index on dropdown item selection? If anyone have any better solution give me some idea.
let EditDropDown = DropDown()
lazy var dropDowns: [DropDown] = {
return [
self.EditDropDown
]
}()
This is my function which I am using for DropDown List.
func setupGenderDropDown() {
let cellHeader = tableview.dequeueReusableCell(withIdentifier: "CellRIDHeader") as! SPOccupationCell
EditDropDown.anchorView = cellHeader.btnDots
EditDropDown.bottomOffset = CGPoint(x: 0, y: 40)
// You can also use localizationKeysDataSource instead. Check the docs.
EditDropDown.dataSource = [
"Edit",
"Make Default",
"Delete"
]
// Action triggered on selection
EditDropDown.selectionAction = { [weak self] (index, item) in
cellHeader.btnDots.setTitle(item, for: .normal)
if item == "Edit"
{
// I am Getting Cell Index but index is nil
let cell = self!.tableview.dequeueReusableCell(withIdentifier: "CellRIDHeader") as! SPOccupationCell
let indexPath = self!.tableview.indexPath(for: cell)
print(indexPath as Any)
let occupation_id = self!.arrayOccupation[(indexPath?.row)!].occupation_Main_id
print(occupation_id)
let next = self!.storyboard?.instantiateViewController(withIdentifier: "EditOccupationVCSID") as! EditOccupationVC
self!.navigationController?.pushViewController(next, animated: false)
next.occupationId = occupation_id
}
else if item == "Make Default"
{
print("B")
}
else if item == "Delete"
{
print("c")
}
}
}
I am assuming you are using DropDown library to show dropdown. There is a problem where you are getting cell when it is tapped so I have created a demo project (simple tableView and not with custom UITableViewCell) for you and I have added comment to explain the changes. Consider below code:
import UIKit
import DropDown
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
var items: [String] = ["We", "Heart", "Swift"]
let editDropDown = DropDown() //Object name should start with small letter
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
}
func setupGenderDropDown(cell: UITableViewCell) { //Pass your cell with argument and change type to your custom cell
//By changing cell argument with your custom cell you will get your button for anchor
editDropDown.anchorView = cell.textLabel
editDropDown.bottomOffset = CGPoint(x: 0, y: 40)
editDropDown.dataSource = [
"Edit",
"Make Default",
"Delete"
]
//Here you need to update selectionAction from their library page
editDropDown.selectionAction = { [unowned self] (index: Int, item: String) in
//Here you will get selected item and index
print("Selected item: \(item) at index: \(index)")
if item == "Edit"
{
print(item)
print(index)
}
else if item == "Make Default"
{
print("B")
}
else if item == "Delete"
{
print("c")
}
}
//This was missing in your code
editDropDown.show()
}
}
extension ViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCell(withIdentifier: "cell") as! UITableViewCell
cell.textLabel?.text = self.items[indexPath.row]
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//Get the selected cell this way
guard let indexPath = tableView.indexPathForSelectedRow else { return }
guard let currentCell = tableView.cellForRow(at: indexPath) else { return }
//Pass your selected cell to setupGenderDropDown method
setupGenderDropDown(cell: currentCell)
}
}
HERE you can check demo project. And it's created into Xcode 10.1

Pass value to next view when label in Table view cell is tapped

would love to pass the value postArray[indexpath.row].creatorId when the label inside a tableview cell is tapped so it can be passed onto the next view controller so i can load the profile of that particular creator/user. I used custom cells, so how do i get the creator id based on the location of the label(username) selected.
//custom cell
class PostCell : UITableViewCell
{
#IBOutlet weak var timeAgoLabel: UILabel!
#IBOutlet weak var usernameLabel: UILabel!
#IBOutlet weak var profileImageView: UIImageView!
#IBOutlet weak var postImageView: UIImageView!
#IBOutlet weak var captionLabel: UILabel!
#IBOutlet weak var postStatsLabel: UILabel!
}
//do something when label is tapped
#objc func tapFunction(sender:UITapGestureRecognizer) {
//userClicked = creatorData
print(userClicked)
appDelegate.profileView()
print("tap working")
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0{
return 1
}else{
return postsArray.count
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//var returnCell: UITableViewCell!
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "statusCell", for: indexPath) as! statusCell
profilePicture = UserDefaults.standard.object(forKey: "userPic") as? String
if profilePicture != nil {
//load profile picture from library
let urlString = "https://test.com/uploads/profile-picture/"+(profilePicture)!
let profileURL = URL(string: urlString)
cell.statusProfilePic?.downloadedFrom(url: profileURL!)
} else {
print("you have no profile picture set")
}
return cell
} else {
if postsArray[indexPath.row].photos != nil{
let cell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostCell
if postsArray[indexPath.row].comments != nil {
comments = postsArray[indexPath.row].comments?.count
} else {
comments = 0
}
if postsArray[indexPath.row].like_list != nil {
likes = postsArray[indexPath.row].like_list?.count
}else{
likes = 0
}
//assign post id to PostID
postID = postsArray[indexPath.row].post_id
//make username clickable!
let tap = UITapGestureRecognizer(target: self, action: #selector(NewsfeedTableViewController.tapFunction))
cell.usernameLabel.isUserInteractionEnabled = true
cell.usernameLabel.addGestureRecognizer(tap)
cell.usernameLabel.text = postsArray[indexPath.row].fullname
cell.timeAgoLabel.text = postsArray[indexPath.row].data_created
cell.captionLabel.text = postsArray[indexPath.row].content
cell.timeAgoLabel.text = postsArray[indexPath.row].modified
//15 Likes 30 Comments 500 Shares
cell.postStatsLabel.text = "\(likes!) Likes \(comments!) Comments"
//load profile picture from library
let urlString = "https://test.com/uploads/profile-picture/"+(postsArray[indexPath.row].profile_pic_filename)!
let profileURL = URL(string: urlString)
cell.profileImageView.downloadedFrom(url: profileURL!)
//iterate through posts images images array
//load post picture from server library
var postImageName : String?
if postsArray[indexPath.row].photos != nil{
let postImage = postsArray[indexPath.row].photos
for postsImage in postImage!{
postImageName = postsImage.filename!
}
let urlPostImageString = "https://test.com/uploads/post-picture/"+(postImageName)!
let postsImageUrl = URL(string: urlPostImageString)
cell.postImageView.downloadedFrom(url: postsImageUrl!)
} else {
print("Post has no picture")
}
//return cell
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "NoImageCell", for: indexPath) as! NoImageTableViewCell
if postsArray[indexPath.row].comments != nil {
comments = postsArray[indexPath.row].comments?.count
} else {
comments = 0
}
if postsArray[indexPath.row].like_list != nil {
likes = postsArray[indexPath.row].like_list?.count
} else {
likes = 0
}
//make username clickable!
let tap = UITapGestureRecognizer(target: self, action: #selector(NewsfeedTableViewController.tapFunction))
cell.noImageUsername.isUserInteractionEnabled = true
cell.noImageUsername.addGestureRecognizer(tap)
cell.noImageUsername.text = postsArray[indexPath.row].fullname
cell.noImageTime.text = postsArray[indexPath.row].data_created
cell.noImagePost.text = postsArray[indexPath.row].content
cell.noImageTime.text = postsArray[indexPath.row].modified
//15 Likes 30 Comments 500 Shares
cell.noImageLikeAndComment.text = "\(likes!) Likes \(comments!) Comments"
//load profile picture from library
let urlString = "https://test.com/uploads/profile-picture/"+(postsArray[indexPath.row].profile_pic_filename)!
let profileURL = URL(string: urlString)
cell.noImageProfilePic.downloadedFrom(url: profileURL!)
return cell
}
}
}
Use this for example.
Implement didSelectRow() method and in it write something like this:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
// this method works, when you taped cell. write here code of you need. Next code only example, which set user info to some VC and push it:
let controller = UserController as? UserController
if let controller = controller {
controller.user = users[indexPath.row]
self.navigationController?.pushViewController(controller, animated: true)
}
}
add this to your Cell's class:
func setTap() {
let tap = UITapGestureRecognizer(target: self, action: #selector(tapRecognized))
self.label.addGestureRecognizer(tap)
tap.numberOfTapsRequired = 1
}
#objc func tapRecognized(sender: UITapGestureRecognizer) {
// here your code of tap on label
print("label tapped")
}
Check on storyBoard is your label isUserInteractionEnabled? - set it to true. Inside tapRecodnized() method do what are you need. And you need to call method setTap() in your cell's method, which you call in tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell.
Update
Simple example. this code know what are you tapped. if you tap cell, but not label, add code of push some controller, else code of push another controller.
Cell's Class:
class MyTableViewCell: UITableViewCell {
#IBOutlet weak var label: UILabel!
var mainController: ViewController?
func setText(text: String) {
setTap()
label.text = text
}
func setTap() {
let tap = UITapGestureRecognizer(target: self, action: #selector(tapRecognized))
self.label.addGestureRecognizer(tap)
tap.numberOfTapsRequired = 1
}
#objc func tapRecognized(sender: UITapGestureRecognizer) {
if let mainController = mainController {
print("label tapped")
mainController.pushSomeVc(cell: self)
}
}
}
Code of main Class:
class ViewController: UIViewController {
#IBOutlet weak var myTableView: UITableView!
var array = ["1", "2", "3", "4", "5", "6"]
override func viewDidLoad() {
super.viewDidLoad()
}
func pushSomeVc(cell: MyTableViewCell) {
let row = myTableView.indexPath(for: cell)?.row
if let row = row {
// write here code of push controller, when label tapped. row property for get some user from array
print("push some vc with \(row)")
}
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = myTableView.dequeueReusableCell(withIdentifier: "cell") as? MyTableViewCell
if let cell = cell {
cell.setText(text: array[indexPath.row])
cell.mainController = self
}
return cell ?? UITableViewCell()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
// write here code of push controller with comments
print("cell tapped: \(indexPath.row)")
}
}
I tested this code and it's work perfect

how to implement one radio button to be active while selecting it?

I am having table view and on table view cell the radio button has been placed and the radio buttons may increase or decrease dynamically when I select one radio button the other buttons should not active at a time here is the code I used for selecting a button but I am unable to make other button inactive at a time
func paymentMethodURL() {
let url = NSURL(string: self.paymentmethodURL)
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
self.paymentmethodsArray = (jsonObj!.value(forKey: "payment method") as? [[String: AnyObject]])!
OperationQueue.main.addOperation({
self.tableDetails.reloadData()
})
}
}).resume()
}
func paymentreviewURL() {
let url = NSURL(string: self.paymentReviewURL)
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
let arrayss = jsonObj?.allKeys
OperationQueue.main.addOperation({
})
}
}).resume()
}
#IBAction func selectRadioButton(_ sender: KGRadioButton) {
sender.isSelected = !sender.isSelected
if sender.isSelected {
} else{
}
}
func numberOfSections(in tableView: UITableView) -> Int{
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return paymentmethodsArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let paymentcell = tableView.dequeueReusableCell(withIdentifier: "cell",for:indexPath) as! paymentTableViewCell
tableDetails.isHidden = false
myActivityIndicator.stopAnimating()
let arr = self.paymentmethodsArray[indexPath.row]
paymentcell.paymentNameLabel.text = arr["name"]as? String
return paymentcell
}
you should like this:
var tagSelected = -1
//assume each radio button have tag 0 1 2
#IBAction func selectRadioButton(_ sender: KGRadioButton) {
tagSelected = sender.tag
tableView.reloadData()
}
//cell for RowAtIndexPath
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier:
kCellReuseIdentifier, for: indexPath) as? YourCell else {
fatalError("Cell is not dequeued")
}
//logic for match indexPath.row /section to your button tags
if indexPath.row == tagSelected {
//selected here your radio button
} else {
//unselect all others
}
//other code
return cell
}
var checkIsRadioSelect = [Int]()
var webserviceArray = [modelObj]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let obj = webserviceArray[indexPath.row]
cell.radioButton.tag = indexPath.row
let checkIndex = self.checkIsRadioSelect.index(of: obj.wateverUniqeId)
if(checkIndex != nil){
cell.radioButton.isSelected = true
}else{
cell.radioButton.isSelected = false
}
}
#IBAction func selectRadioButton(_ sender: UIButton) {
let obj = webserviceArray[sender.tag]
let chekIndex = self.checkIsRadioSelect.index(of:obj.wateverUniqeId)
if sender.isSelected {
self.checkIsRadioSelect.remove(at: sender.tag)
} else{
if(chekIndex == nil){
self.checkIsRadioSelect.append(obj.wateverUniqeId)
}
} self.tableview.reloadData()
}
pretty simple solution is to have an integer for exemple to hold the index of the cell containing the selected button, for exemple at t=0 none is selected so say initial value for this new variable would be -1, once the user select button in cell 3 , u put 3 in that new variable , and later when he select cell 5 first you check if the variable has a valid index in it (in this case 3) then you go unselect the radio in cell 3 (which u have its index) and then select cell 5 and so on and so on..
now in your case I take it that IBAction is inside you cell controller, so you dont have direct access to the tableview and other cells to "deselect" if needed, what I would do is create a delegate protocol for that cell and have the viewcontroller containing the tableview be its delegate so whenever the user select a button i just invoke the delegate method with the cell's index as parameter and obviously implement this delegate method in the viewcontroller and do as I said earlier, here s an exemple on how it would go :
in the cell controller :
#IBAction func selectRadioButton(_ sender: KGRadioButton) {
if sender.isSelected {
} else{
self.delegate?.selectButton(index: self.index)
//invoke the delegate so that the viewcontroller deselect any other cell that might be selected
}
}
and in the viewcontroller :
func selectButton(index: index) {
if self.selectedCell != -1 {
let cell = self.tableView.cellForRowAtIndex(IndexPath(0, self.selectedCell))
cell.selectRadioButton(cell.button)
}
self.selectedCell = index
}

How do I add a UIButton into my UITableViewCell in Swift 3?

I have an existing UITableView that displays data and is working fine.
However I now want to add an info button into this UITableViewCell.
I added the UIButton directly into the TableViewCell in storyboard. I then tried to declare this button as an outlet but I got the error
"Outlets cannot be connected to repeating content."
I read around the subject and decided to create a new subclass called "
import UIKit
class PersonalStatsTableViewCell: UITableViewCell {
#IBOutlet weak var personalStatsInfoButton: UIButton!
var selectedCellTitle: String?
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
As you can see I have declared the UIButton personalStatsInfoButton in this sub-class.
With more reading around the subject I believe I need to add something like:
personalStatsInfoButton.tag = indexPath.row
personalStatsInfoButton.addTarget(self, action: "infoButtonClicked", forControlEvents: UIControlEvents.TouchUpInside)
and then have a function:
function infoButtonClicked(sender:UIButton){
let infoCell = sender.tag
print (infoCell)
}
My issue is I don't know whether I need to take all my existing tableView code and transfer it into the the new sub-class PersonalStatsTableViewCell or just the parts that deal with the info button.
Below is my existing VC code that initially deals with the TableView prior to adding in this new button.
import UIKit
class ShowCommunityViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var membersTableView: UITableView!
#IBOutlet weak var communityName: UILabel!
var communityIsCalled: String?
var comIds = [String]()
var communityId: Int?
var selectedCellTitle: String?
var cellId: Int?
var communityPlayerIds = [String]()
var communityPlayers = [String?]()
override func viewDidLoad() {
super.viewDidLoad()
communityName.text = (communityIsCalled)
self.membersTableView.delegate = self
self.membersTableView.dataSource = self
membersTableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.communityPlayers.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "PersonalStatsTableViewCell", for: indexPath as IndexPath)
cell.textLabel?.text = self.communityPlayers[indexPath.row]
cell.textLabel?.font = UIFont(name: "Avenir", size: 12)
cell.textLabel?.textColor = UIColor.white // set to any colour
cell.layer.backgroundColor = UIColor.clear.cgColor
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
self.selectedCellTitle = self.communityPlayers[indexPath.row]
cellId = indexPath.row
}
override func viewDidAppear(_ animated: Bool) {
let myUrl = URL(string: "http://www.???.uk/???/specificCommunity.php?");
var request = URLRequest(url:myUrl!);
request.httpMethod = "POST";
let postString = "id=\(comIds[communityId!])";
request.httpBody = postString.data(using: String.Encoding.utf8);
let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
DispatchQueue.main.async
{
if error != nil {
print("error=\(error)")
return
}
do{
let json = try JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? [String:AnyObject]
if let arr = json?["players"] as? [[String:String]] {
self.communityPlayerIds = arr.flatMap { $0["id"]!}
self.communityPlayers = arr.flatMap { $0["user_name"]!}
self.membersTableView.reloadData()
print ("names: ",self.communityPlayers)
}
} catch{
print(error)
}
}
}
task.resume()
}
}
You don't need to put any code in your class PersonalStatsTableViewCell you can manage all the things from ShowCommunityViewController what you need to done is in your cellForRowAt method add this
cell.personalStatsInfoButton.tag = indexPath.row
cell.personalStatsInfoButton.addTarget(self, action: #selector(infoButtonClicked(sender:), forControlEvents: UIControlEvents.TouchUpInside)
and add this function
function infoButtonClicked(sender:UIButton){
let infoCell = sender.tag
print (infoCell)
}
Your code and what you are thinking is correct, you just need to change the following line.
Apart from what Arun B has said, you need to make sure xcode knows what kind of class cell will belong to.
let cell = tableView.dequeueReusableCell(withIdentifier: "PersonalStatsTableViewCell", for: indexPath as IndexPath)
should be
let cell = tableView.dequeueReusableCell(withIdentifier: "PersonalStatsTableViewCell", for: indexPath as IndexPath) as! PersonalStatsTableViewCell
This happens if the custom class is not set up properly. Make sure that PersonalStatsTableViewCell is set as the Custom class of the UITableViewCell in your storyboard.

Resources