I have two UITableView controllers, A and B. If the user clicks on cell one of table A, the user is redirected to table B with 10 cells. If the user clicks on cell two of table A, the user is redirected to table B with 1 cell.
Theory
Click 1: Table A, Row One ---> Table B with 10 cells (layout with associated URLs)
Click 2: Table A, Row Two ---> Table B with 1 cell (layout with associated URL)
The bug I am observing is this:
When first clicking on the first row of Table A, and clicking on the second row of Table A thereafter, table B is displayed with 10 cells. 9 of those cells are not clickable, and the first cell is identical with the only cell that should be displayed (but with the layout of the other 9 not clickable cells). Only when clicking the back button and clicking onto the second row of table A again the 1 cell is displayed properly in table B.
Practice
Click 1: Table A, Row One ---> Table B with 0 cells
Click 2: Table A, Row One ---> Table B with 10 cells (layout with
associated URLs)
Click 3: Table A, Row Two ---> Table B with 10 cells
(layout only; 1st cell with associated URL)
Click 4: Table A, Row Two ---> Table B with 1 cell (layout with associated URL)
I believe someone else experienced the same bug (UITableView only sending data to Detail View Controller on Second Try). However, the feedback is for Objective C so I don't understand what to do.
The code for my segue is:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "viewOverviewArticle" {
if let indexPath = self.tableView.indexPathForSelectedRow {
let recentObject = self.fetchedResultsController.objectAtIndexPath(indexPath)
let controller = segue.destinationViewController as! ArticleAnalysis
controller.analysisItem = recentObject
}
}
}
Assuming that I indeed experience the same problem as UITableView only sending data to Detail View Controller on Second Try, my question boils down to this:
How can I make sure the segue that is triggered when clicking onto a row in my table has up-to-date data?
Moved the command for deleting the old saved data from viewWillAppear to viewWillDisappear - that fixed the bug.
Related
I have created a UITableView that includes a UIImage, and two UILabels. This data is passed to a details view controller when the user selects the row. I have also successfully created a UIButton in the prototype cell that updates the text of one of the UILabels. I am unsuccessfully attempting to update this label within the array so this change is reflected on the details view controller. This is what I tried with no success:
#IBAction func updateTableData(_ sender: Any) {
grinds.removeAll()
grinds = createArray()
}
Here is a link to the repo: https://github.com/andrewTuzson/tableViewPractice
In the screenshot below, the left image displays the tableview after the first cell has been toggled to "Needs Work". The right image displays the details screen that is loaded after selecting the row.
How should I approach solving this?
If you want to update a tableViewCell upon the button click then, you should make the model array global to access it in click method and update what you want then reload the tableView either with delegate or NSNotificationCenter
--
in the custom class of the cell declare an integer property and in cellForRow set it like this
cell.index = indexpath.row
I have two different cells: A & B. (where the only difference between A & B is that they have 2 different properties.
I'm trying to get A and B to show up vertically in a collection view like this:
A B A B A B A B
How do I go about doing this in the cellForItemAt method? Maybe by keeping track of which cell was returned last?
There are a few approaches you can take to achieve something like this. If all of your data is the same but you want every other cell to appear differently you can just check to see if it is an even or an odd row when in your datasource methods.
Something like this:
if indexPath.row % 2 != 1 // odd row
{
// set up a cell of type A
}
else // even row
{
// set up a cell of type B
}
Otherwise, if your actual data source can discern the different elements in the array as being of different types, you would just check to see what type of element is in your array at a given index and return the appropriate cell.
I want to open different view controllers on tap of different cells of table view. For that, I have made different Segues in Storyboard. Now lets take example,
Total 4 view controllers A, B, C and D.
A contains table view and table view contains 3 cells
On tap of first cell -> B View controller,
On tap of second cell -> C View controller,
On tap of third cell -> D View controller.
I have implemented above functionality like this:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
switch indexPath.row {
case 0:
performSegueWithIdentifier("B", sender: nil)
case 1:
performSegueWithIdentifier("C", sender: nil)
case 2:
performSegueWithIdentifier("D", sender: nil)
default:
break
}
}
And above code works fine. But sometime it throws an exception when I play randomly, One of random way is mentioned below:
First Cell to B
Back button to A
Second cell to C
Back button to A
Third cell to D
Back button to A
Second cell to C (Now exception is thrown)
This is one of many scenarios in which app crashes. Sometime it crashes on 4th point or 6th point. And I am getting following error:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not load NIB in bundle: 'NSBundle </var/containers/Bundle/Application/E57BCF07-1FBB-469C-A99D-56930FAE1AB0/PMD.app> (loaded)' with name 'Gf1-A9-PrY-view-pxD-t4-NUk' and directory 'Main.storyboardc''
Ideally, It should crashes every time or it shouldn't. But it crashes in some random different ways.
Am I doing something wrong? Please provide your suggestions.
Thanks!
I have a view controller with 2 labels - each to be populated from lists in 2 separate table controllers. In my view controller I have 2 variables (temp and temp_1) to receive the data from the table controllers and populate the labels.
When I call the first table view and select an item that works fine and my first label is populated, when I then call the second table view that works too and my second label is populated - except that the first label is now blank - because temp is now blank.
I have attached my prepareForSegue from my first table view showing me passing my variable temp back to my view controller. (My second is similar and passes back temp_1)
Thanks for any help.
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "return_1" {
if let destination = segue.destinationViewController as? main_ViewController {
if let row = tableView.indexPathForSelectedRow?.row {
destination.temp = array1[row] as! String
}
}
}
}
My guess is that what you are saying in words is not what in fact you are actually doing. You say "back to my view controller", as if you were returning from the table view to the main view controller. That is what you want to do and what you should do, but it isn't what you're doing (I'm guessing). I think you've set up your storyboard with a normal segue from the table view to the main view controller. That doesn't go back; it makes a whole new main view controller. So of course the old label value is missing, because this is a different view controller from the one with the old label value (which effectively is still there, two layers down, covered up by this new instance).
What you want is an unwind segue. That is how you say "go back" in a storyboard.
I'm working on my first app and I've got the UI sketched out, but before I move forward, I've hit a stumbling block out of the gate that's not in the tutorials I've been studying.
Two issues I have:
1) Passing data between TableViewControllers
2) Conditional Segues
The app uses CoreData and has a context with 3 managed objects in the model: FocusArea, Equipment, & Activity.
A portion of my app will have 3 TableViews that display fetched results from FocusArea, Equipment, & Activity. The navigation through them will be as follows:
Step 1 -> Step 2 -> Step 3 -> save selections
focusAreaTVC -> equipmentTVC -> activityTVC -> saveVC
equipmentTVC -> focusAreaTVC -> activityTVC -> saveVC
activityTVC -> focusAreaTVC -> equipmentTVC -> saveVC
When an item/items is/are selected in Step 1, a "next" button will advance to Step 2, display options available for rows selected in Step 1. Once the user makes selections in Step 2, the remaining available selections will be displayed in Step 3. I envision the final selections on the Save screen to be saved as an array or a dictionary.
Issues:
1) View Controllers: Rather than use 9 different ViewControllers, I plan to use performSegueWithIdentifier so I only need to set up 3 view controllers for the objects and figure out the logic to accomplish the transitions.
Would I create a global variable in AppDelegate for the TVC at each step and put logic in a switch statement for each VC within performSequeWithIdentifier?
example:
// AppDelegate variables start all nil, updated at each step, reset to nil on save
var step1VC = "equipmentVCUsed"
var step2VC = "focusAreaTVCUsed"
var step3VC = nil
// VC switch statement (contained in each TableViewController)
var segueIdentifier: String
switch segueName {
case step1TVC = "focusAreaTVC":
segueName = "equipmentTVC"
case step1TVC = "equipmentTVC:
segueName = "focusAreaTVC"
case step1TVC = "activityTVC":
segueName = "focusAreaTVC"
case step2TVC = "equipmentTVC":
segueName = "activityTVC"
case step2TVC = "focusAreaTVC", step1VC = "equipmentVC":
segueName = "activityTVC"
case step2TVC = "focusAreaTVC", step1VC = "activityVC":
segueName = "equipmentTVC"
case step3VC != nil,
segueName = "saveVC"
step1TVC = nil
step2TVC = nil
default:
println("Something so the the compiler doesn't yell at me")
}
2) I plan to make selections in Step 1 and pass them to Step 2's VC, further refine there, pass to Step 3. Since they're all working off the same context, can I just pass the selections from 1 TVC to another or do I need to create a list that the next VC will retrieve items from?
How would I get the information from Step 1 to Step 3? Would I have to save the selections in an Array between segues and refine them with fetches in each VC?
Why not just let the segues be triggered by taps on a table view cell? In other words, make it like this: User selects option from first table view -> User then sees second table view and selects from the appropriate set of options -> User then sees third table view and selects from the appropriate set of options. You can always put a back button at the top so the user can go back and change his/her selections.
Your users might want, and expect, your app to behave like this.
Anyway, to answer your questions:
1) I suggest that you create a UIViewController superclass from which your subclasses inherit, then define a property in that class's .h file that can be set to an object that contains whatever data each view controller needs to pass to the next view controller. Then, use prepareForSegue to pass along the data that the next view controller will need to have.
2) You can pass the selections from 1 TVC to another (see #1)
Edit: If you need any clarification, or if you feel I am misunderstanding your question, please feel free to leave a comment. I got less than 5 hours of sleep last night.