Pass selected row title back to main table view controller - swift

I have a main table view controller with static cells that have a title and then a detail label. When the user clicks on "cell 1" they are taken to a second table view controller with static cells. They choose from a list ( only one cell can be picked) and then when they hit the back button whatever cells title they picked is transferred into the detail label of the cell they clicked on. The main view controller has outlets to each detail label. I've messed with it for two days and can't seem to get it to work

Add a delegate property that is type of DismissDelegate to your second view controller and set it to the first controller.
Add this protocol
protocol DismissDelegate {
func selectedCell(index : int)
}
When the second view is dismissed e.g. in the viewWillDisapper method, call the selectedCell method and pass it the selectedCell
delegate.selectedCell(self.tableView.indexOfSelectedCell) //i don't know the correct function
Then in the main view controller conform to the protocol and do whatever you need to do with the index
func selectedCell(index : int) {
//whatever you need to do with the index
}

There are several ways of solving this problem.
Using Delegate
You just implement a delegate and get the data back from the secondary view controller.
In the secondary view controller, you can call a delegate like this.
self.delegate.dataInputed(xxx)
and the first view controller's dataInputed method will be called.
In the dataInputed Method, you can update the value of the data source for the selected indexPath, and reload the Data
Send Notification
You just keep the selected table cell indexPath, and after receiving a notification from the secondary detail view controller, you can update the value of the data source for the selected indexPath, and reload the table.

Related

How could I keep keyboard up when tableview cells are tapped?

I am a beginner learning Swift and trying to build a search page with Swift. In my search page of the app, I have added two Views in my storyboard with one View above the other.
The upper View contains a Collection View where I have two prototypes of collection view cells. The first type of the cells has Label. The second type of the cells has TextField.
The other View on the bottom half of the screen contains a dynamic Table View where I have a list of items that can be selected. Each row of the table view cells has a selection item.
So, when I tap on a table view cell, the selection item will appear in the collection view. If I type a keyword in the TextField in the collection view, table view reloads and shows all the selection items that has the keyword, so I can tap and add an item to the collection view.
I would like to keep adding by typing a keyword after I tap on a searched item in the table view. So, I made the first cell showing selected items with labels and the second cell that has the TextField separated into two sections of the collection view. So, I only reload the first section (without TextField) for each selection. But somehow the keyboard automatically resign whenever I tap on the table view cell to add an item to the collection view.
Is there any way I can keep the keyboard up even when I tap on the tableview cells?
The keyboard also resigns when I tap the collection view cells.
I would appreciate your advice. Thanks.
I hope you are having a good day.
You can try calling this method on the UITextField you would like to show the keyboard for (maybe call it after the user taps on the UITableViewCell):
textField.becomeFirstResponder()
where "textField" is the variable name of your UITextField.
Please let me know if this fixed your issue.
Edit #1
Hello! Since my previous solution did not achieve your intended behavior. There is another solution in my mind, however I have not tried it before.
As an introduction to the concept of delegation, there is a method created by Apple called "textFieldShouldEndEditing" which is called by Apple whenever any keyboard will disappear on any text field.
This method is created by Apple, but you can override it (i.e. customize it) to suit your needs and tailor its behavior.
To override this method you have to assign your class as the delegate of UITextField by adding UITextFieldDelegate to your class definition as follows:
class YourClassName: UIViewController, UITextFieldDelegate { }
Now you have to set your class as the delegate by saying textField.delegate = self For every UITextField you create in your collection views
You then can re-create the method we discussed earlier in your class:
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
//let's implement it the next steps, but for now, let's return true.
return true
}
Now instead of Apple calling their version of the method, they will call yours.
You then can create a variable in the top level of your class (I will let you know where this will be helpful later), and "maybe" name it as:
var isCellBeingClicked = false
Now upon clicking on a cell, make this variable true, I believe you are using the method didSelectRowAt (but you could be using any other method which is fine):
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
[...]
isCellBeingClicked = true
[...]
}
Now back to our customized method textFieldShouldEndEditing mentioned in step 3. You can add this implementation:
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
//If a cell is being clicked right now, please do not dismiss the keyboard.
if isCellBeingClicked {
isCellBeingClicked = false //reset the value otherwise the keyboard will always be there
return false
}
else { return true }
}
Please let me know if this fixes your issue.
Best regards

CollectionView within a CollectionView: Using didSelectItemAt to performSegue

I have a collectionView within a collectionView and I want to be able to select a cell in the 2nd collectionView to perform a segue to another ViewController.
Currently, when I select a cell, I get the following message:
" Receiver ... has no segue with identifier 'ToVC2'. "
However, I have used this segue/identifier from other UIButtons and it works.
I have two ViewControllers: ViewController1 and ViewController2.
On ViewController1, there is a collectionView ("categoryCollectionView") which has vertical scrolling.
Within categoryCollectionView, there is another collectionView ("eventCollectionView") which allows horizontal scrolling.
The two collectionViews are set up and working correctly for numberOfItemsInSection and cellForItemAt. I now want to be able to select a cell within eventCollectionView, and cause a segue from ViewController1 to ViewController2.
I have added a function in ViewController1:
func segueToViewController2(event: Event){
performSegue(withIdentifier: "ToVC2", sender: event)
}
Within eventCollectionView's didSelectItemAt, I have tried the following:
var viewController1: ViewController1? = ViewController1()
viewController1.segueToViewController2(event: eventSelected)
When I select a cell, I get the following error message:
'Receiver () has no segue with identifier 'ToVC2''
However, this function performs the segue correctly if called from a regular UIButton on ViewController1 (therefore I know the issue is not that there is no segue / the identifier is wrong.) I believe the issue is that the function is being called from a collectionView within a collectionView.
Please help!!!!!
I believe the problem is that when you call var viewController1: ViewController1? = ViewController1(), you are initializing a new instance of ViewController1. This is probably not what you are meaning to do. Based on what you have said, you should pass a reference down the hierarchy of collection views you have created so that your didSelect can call the segue function on the original instance of ViewController1. Ideally, you would use a design pattern like delegation to do this.

Segueing to a single view controller that will display some number of UITextFields depending on index selected in table view controller

In my current application, I have a UITableViewController that allows me to segue to three different indices depending on the row selected. If I select row one, I segue to a view controller with three UITextFields. If I select row two, I segue to a NEW view controller with one UITextField. If I select row three, I segue to ANOTHER NEW view controller with five UITextFields. I am looking for a way to condensing the view controllers I am going to into one view controller that will dynamically hide/unhide or remove/add the needed number of UITextFields depending on the index selected in the table view controller. I need the text fields to display in a vertical stack view.
Although it would be very valuable, I am not looking for a solution/example from someone, but rather letting me know some topics I can research would be extremely helpful.
Thank you for your time,
Tony
There might be different approaches for this problem, but I would create a stackView in the NEW view controller with the maximum possible number of textFields embedded. Lets say the VC with most textFields can contain 3 textFields. Create your stackView with 3 textFields inside.
Then segue the indexPath.row of tableView to the NEW VC, it can hold a variable of Integer like:
var index: Int?
In didSelectRowAt method of tableView:
performSegue(withIdentifier: "yourIdentifier", sender: indexPath.row)
In prepareForSegue method:
if segue.identifier == "yourIdentifier"
let vc = segue.destination as! NEWViewController
vc.index = sender
Set tag to your textFields in your NEW View controller, so you can know which textField you will want to delete depending on index.
Then in viewDidLoad of your newViewController, you can remove textFields from your stackView according to the index (Then you might run into which ):
var counter = 0
while counter < index {
answerStackView.subviews.forEach { (view) in
if counter < index {
if view is UITextField {
if view.tag == /*something here to delete specific textFields depending on index. */ {
view.removeFromSuperview()
}
}
}
counter += 1
}
}

Transitioning from uitableview to new viewcontroller

I'm working on the "settings" portion of my app. When one of the cells is clicked, I need to transition to a new View Controller depending on which cell was clicked.
I have found a ton of answers, but they all seem to not go far enough. I understand how to set up a segue to a new view controller and I understand how to use didSelectRowAt Indexpath to show which cell was clicked. I can figure out the transition, but I can't figure out many different transitions based on which cell was clicked.
Is there a way to do this with dynamic cells or should I be using static?
If you have fixed amount of cells, I'd go for static cells. However if you want to use dynamic cells, you can create something like enum with cases that store row index.
fileprivate enum Row: Int {
case volume = 0
case notification = 1
}
Then in didSelectRowAt delegate method:
let row = Row(rawValue: indexPath.row)!
switch row {
case .volume:
// Navigate somewhere
case .notification:
// Navigate somewhere
}

Swift 3 - How do I insert TableViewCells from another view?

I am using Swift 3, Xcode 8.2.
I am trying to figure out how to insert cells into my table view from another tab of my tabbed view controller.
MyTableView
class MyTableView: UITableViewController {
var items = ["Item 1", "Item 2", "Item 3"]
...
func insertCell() {
items.append("Item \(items.count + 1)")
tableView.reloadData()
}
If I create a bar button item on that table view page, I can successfully insert items, no problem. It's when I try to trigger it from another view controller that nothing happens.
Another Tab
#IBAction func triggerInsert(_ sender: Any) {
//MyTableView().insertCell() // this doesn't work
//MyTableView().items.append("Item") // these two lines don't work either
//MyTableView().tableView.reloadData()
// also tried setting a boolean in here to be read from MyTableView but that didn't work either
}
I'm not quite sure what the "correct" way to do this is. Any help would be greatly appreciated.
The problem is this expression you keep trying to use:
MyTableView()
That creates a completely new and separate table view controller. But that obviously is not what you want to do. You want to talk to the existing table view controller, the one that is, as you say, another tab in the tab bar controller.
For example, if MyTableView is the first tab and OtherViewController is the second tab, then OtherViewController might say:
self.tabBarController!.viewControllers![0] as! MyTableView
...as a way of getting a reference to the existing table view controller.