Possible to add tag to a static cell within a Dynamic Prototype UITableView? (Swift) - swift

I have a Dynamic Prototype table that also has a few static cell. I am trying to allow one of these static cells to have two textfields within the single cell. I believe to do this, I will need to set tags for each of the textfields.
But, I am not sure how (if possible) to assign the tags to the below lines.
TableViewController:
case DiveMasterIndex:
cell = tableView.dequeueReusableCellWithIdentifier(Resource.DiveMasterCell)
(cell as! DiveMasterTableViewCell).textField.placeholder = Strings.DiveMaster.localized // tag 1001
case DiveMasterIDIndex:
cell = tableView.dequeueReusableCellWithIdentifier(Resource.DiveMasterCell)
(cell as! DiveMasterIDTableViewCell).textField.placeholder = Strings.DiveMasterID.localized // tag 1002
The two TableViewCells
class DiveMasterTableViewCell: UITableViewCell, UITextFieldDelegate
{
#IBOutlet var textField: UITextField!
override func awakeFromNib()
{
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
}
func textFieldDidEndEditing(textField: UITextField)
{
(self.tableViewController as! DiveDetailsNew2TableVC).diveModel.name = textField.text!
}
the second
class DiveMasterIDTableViewCell: UITableViewCell, UITextFieldDelegate
{
#IBOutlet var textField: UITextField!
override func awakeFromNib()
{
super.awakeFromNib()
}
override func setSelected(selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
}
func textFieldDidEndEditing(textField: UITextField)
{
(self.tableViewController as! DiveDetailsNew2TableVC).diveModel.name = textField.text!
}

If you want one cell to have 2 textfields better way would be to create 2 outlets with different names for text fields instead of assigning tags to them. You do not need 2 cells for such case.

Related

How to add an action button to a custom XIB cell?

I want to create a custom XIB Table View Cell with an action button that can segue to a new view controller.
So far, I created a custom XIB Cell (TaskListCell) with a button (timeButton), and registered the TaskListCell to TaskListViewController. For tableView(_:cellForRowAt:), I added tag for timeButton and addTarget(_:action:for:) to respond when timeButton is tapped. However, I get this error message: Thread 1: "-[Sprints.TaskListCell pressedTimeButton:]: unrecognized selector sent to instance 0x105311560"
Here is the custom XIB cell file:
class TaskListCell: UITableViewCell {
#IBOutlet weak var nameField: UITextField!
#IBOutlet weak var timeButton: UIButton!
#IBAction func pressedTimeButton(_ sender: UIButton) {
}
override func awakeFromNib() {
}
override func setSelected(_ selected: Bool, animated: Bool) {
}
}
Here is the ViewController that displays the custom cells in a Table View:
class TaskListViewController: UIViewController {
// MARK: - Outlet Variables
#IBOutlet weak var taskList: SelfSizedTableView!
...
// MARK: - Instance Variables
var taskData = [TaskData]()
var taskCount: Int = 1
...
// MARK: - View Controller Methods
override func viewDidLoad() {
super.viewDidLoad()
// Register TaskListCell.xib file
let taskCellNib = UINib(nibName: "TaskCell", bundle: nil)
taskList.register(taskCellNib, forCellReuseIdentifier: "taskCell")
...
// Connect table view's dataSource and delegate to current view controller
taskList.delegate = self
taskList.dataSource = self
}
// MARK: - Action Methods
// Adds new cell in Table View
#IBAction func pressedAddTask(_ sender: UIButton) {
taskCount += 1
taskList.reloadData()
taskList.scrollToRow(at: IndexPath(row: taskCount-1, section: 0), at: .bottom, animated: true)
}
// MARK: - Methods
// Segues to SelectTime screen when timeButton is pressed
#objc func pressedTimeButton(_ sender: UIButton) {
let destination = SelectTimeViewController()
navigationController?.pushViewController(destination, animated: true)
}
}
extension TaskListViewController: UITableViewDataSource {
// Return the number of rows in table view
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
return taskCount
}
// Return the cell to insert in table view
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell", for: indexPath) as! TaskListCell
// Fatal error for next line: "Unexpectedly found nil while implicitly unwrapping an Optional value"
cell.timeButton.tag = indexPath.row
cell.timeButton.addTarget(self, action: #selector(pressedTimeButton(_:)), for: .touchUpInside)
return cell
}
}
extension TaskListViewController: UITableViewDelegate {
}
Check instance of IBAction from your cell may be it is being called. Remove this function and it will work
#IBAction func pressedTimeButton(_ sender: UIButton) {
}

How to open View Controller in Table View with Button by using Objc in Swift?

Stackoverflow
I know how to make a button in the table view cells with website links, rate, mail, and many things. However, How could I open the view controller with the instantiateViewController in the #Objc func's statements?
For example.
Create a new Table View Cell folder called FeedBackButtonsTableViewCell
class FeedBackButtonsTableViewCell: UITableViewCell {
#IBOutlet weak var ButtonCells: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Let create a new view controller folder called
class FeedbackViewController: UIViewController {
#IBOutlet weak var TableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.navigationItem.title = "Feedback"
}
}
add the extension to calling the view controller to UITableViewDataSource and UITableViewDelegate and create a obj func statements inside of the second FeedbackViewController with UITableViewDataSource and UITableViewDelegate under the cells.
extension FeedbackViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
if indexPath.row == 1 {
buttonCell = TableView.dequeueReusableCell(withIdentifier: "ButtonCells") as? FeedBackButtonsTableViewCell
buttonCell?.ButtonCells.addTarget(self,action: #selector(LearnMore),for: .touchUpInside)
buttonCell?.ButtonCells.tag = indexPath.row
return buttonCell!
}
#objc func LearnMore() {
// How could I write to open the view controller with UIButton in the Table View Cells?
}
}
Thank you for bring a kind of help! :)
Simple solution could be to use procol.
protocol CellActionDelegate{
func didButtonTapped(index: Int)
}
Now confirm the protocol in FeedbackViewController. Take index and actionDelegate properties in your UITableViewCell subclass.
class FeedBackButtonsTableViewCell: UITableViewCell{
var actionDelegate: CellActionDelegate?
var index: Int?
.....
// Take Action of UIButton here
#IBAction func more(_ sender: Any) {
if let delegate = self.actionDelegate{
delegate.didButtonTapped(index!)
}
}
}
Now in your FeedbackViewController set actionDelegate & Corresponding index in
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {}
you can open anotherView controller from func didButtonTapped(index: Int) definition .
extension FeedbackViewController:CellActionDelegate{
func didButtonTapped(index: Int) {
let storybord = UIStoryboard(name: "Main", bundle: nil)
guard let controller = storybord.instantiateViewController(withIdentifier: "AnotherControllerIdentfier") as? AnotherViewController else{
fatalError("Could not finc another view controller")
}
self.present(controller, animated: true, completion: nil)
}
}
#objc func LearnMore() {
let viewController = FeedbackDetailsViewController()// creation of viewController object differs depends on how you fetch the UI, means either you are using storyboard or xib or directly making ui in code.
self.navigationController?.pushViewController(viewController, animated: true)
}

How to set IBAction for a UIButton in a UITableViewCell for a different ViewController?

I have subclassed UITableViewCell. Here I have made an outlet for a button. When that button have been clicked on, it should execute a function in a different ViewController. I have tried this:
override func awakeFromNib() {
super.awakeFromNib()
reloadTableView.addTarget(self, action: #selector(multiplayerChannelView.tappedOnReloadTableView), for: .touchUpInside)
}
However, this crashes with this error:
[test.CreateChannelCell tappedOnReloadTableView]: unrecognized selector sent to instance 0x7fc1198b5200
The function exists, with no typo. Why does this not work? This question looks the same only it is not written in swift 3.0 How to set Action for UIButton in UITableViewCell
multiplayerChannelView is the viewcontroller which holds the UITableView. I got a seperated .swift file with the UITableViewCell subclassed.
add this in the cellForRowAtIndexPath
cell.your_button.addTarget(self, action: #selector(self.tappedButton(sender:)), for: .touchUpInside);
And anywhere in the same UIVeiwController define the function as below
func tappedButton(sender : UIButton){
// Your code here
}
You can do it by creating delegate in your tableViewCell class.
protocol CustomTableViewCellDelegate {
func buttonPressed ()
}
then initialize your delegate like below in your tableViewCell
var delegate: CustomTableViewCellDelegate?
and for button action put below code in your tableViewCell class
#IBAction func cellButtonPressed (sender : UIButton) {
if (self.delegate != nil) {
self.delegate?.buttonPressed()
}
On button click check wether delegate is not nil , please set cell.delegate = self in cellForRowAtIndex method
In the last just add code for button action in your classes where you have used customTableViewCell class
extension ViewController : CustomTableViewCellDelegate {
func buttonPressed () {
// Perfom your code on button action
}
}
your CustomTableViewCellDelegate looks like below:
import UIKit
protocol CustomTableViewCellDelegate {
func buttonPressed ()
}
class CustomTableViewCell: UITableViewCell {
var delegate: CustomTableViewCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
#IBAction func cellButtonPressed (sender : UIButton) {
if (self.delegate != nil) {
self.delegate?.buttonPressed()
}
}
Hope it work for you!
write below code in file VC2
import UIKit
class tblCell : UITableViewCell
{
#IBOutlet weak var btnAction: UIButton!
#IBAction func btnAction(_ sender: AnyObject)
{
print(sender.tag) // you can identify your cell from sender.tag value
// notification is fire here and call notification from VC1
NotificationCenter.default.post(name:NSNotification.Name(rawValue: "buttonAction"), object: nil)
}
}
class VC2: UIViewController,UITableViewDelegate,UITableViewDataSource
{
#IBOutlet weak var tblview: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tblview.delegate = self
tblview.dataSource = self
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Table veiw
func tableView(_ tblBlog: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tblBlog: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell : tblCell = tblview.dequeueReusableCell(withIdentifier: "Cell") as! tblCell
cell.btnAction.tag = indexPath.row
return cell
//
}
}
write below code in file VC1
class VC1: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewWillAppear(_ animated: Bool)
{
// this notification is call when it fire from VC2
NotificationCenter.default.addObserver(self, selector: #selector(ButtonClick), name: NSNotification.Name(rawValue: "buttonAction"), object: nil)
}
func ButtonClick()
{
// code when button is clicked you wanto perfrom
}
}

How to get cell index from uiview in uitableviewcell (swift/xcode)

I have two UIViewControllers called upVote and downVote in MyTableViewCell class. I have added the gesture recognizers for tapping these views programmatically but am not sure how to get the parent cell or index of the cell so I know which cell the UIView that was tapped is in. How do I get the cell or index of the tapped cell in the functions handleTapUp and handleTapDown?
Here is my class
class MyTableViewCell: UITableViewCell {
// MARK: Properties
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var upVote: UIImageView!
#IBOutlet weak var downVote: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
let tapUp = UITapGestureRecognizer(target: self, action: "handleTapUp:")
tapUp.delegate = self
upVote.addGestureRecognizer(tapUp)
let tapDown = UITapGestureRecognizer(target: self, action: "handleTapDown:")
tapDown.delegate = self
downVote.addGestureRecognizer(tapDown)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func handleTapUp(sender: UITapGestureRecognizer? = nil) {
// handling code
// get cell(index)
}
func handleTapDown(sender: UITapGestureRecognizer? = nil) {
// handling code
// get cell()
}
}
I have tried self.superclass to get the uitableviewcell, and when i print the debug description it say uitableviewcell, but whenever I try to do anything else with the object I get an error that self.superclass is type AnyObject. I have tried declaring/casting self.superclass in many different ways and none have worked. This seems like it should be simple so hopefully I am missing something.
Declare a variable in your customCellClass:-
var indexForCell : NSIndexPath!
In your ViewControllers where you are dequeing the cells in the function func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell add this :-
cell.indexForCell = indexPath
Now access the indexForCell in your functions in your class:-
func handleTapUp(sender: UITapGestureRecognizer? = nil) {
let rowValue = indexForCell.row
}
func handleTapDown(sender: UITapGestureRecognizer? = nil) {
// handling code
// get cell()
}

Passing parameters to a Selector in Swift using UITapGestureRecognizer, UIImageView and UITableViewCell

I need to identify the image that the user clicked on a TableCell.
How to pass TAG?
class CustomCell: UITableViewCell {
#IBOutlet weak var imgPost1: UIImageView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
imgPost1.tag=1
let tap = UITapGestureRecognizer(target: self, action: #selector(CustomCell.tappedMe))
imgPost1.addGestureRecognizer(tap)
imgPost1.userInteractionEnabled = true
}
func tappedMe(xTag:Int) {
print(xTag)
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
You can use the view property of the UIGestureRecognizer.
Register for tap gesture:
let tap = UITapGestureRecognizer(target: self, action: "tappedMe:")
imgPost1.addGestureRecognizer(tap)
imgPost1.userInteractionEnabled = true
Now define the tappedMe method
func tappedMe(sender: UITapGestureRecognizer) {
print(sender.view?.tag)
}
PS: Don't forget to set the tag for image