Common pattern with segues and table views in iOS - ios

I have the set up of a user clicking a UITableViewCell, this triggers a segue to a 'detail' view controller which is popped onto the stack.
First,
User Taps -> [myVC tableView didSelectRow...] - this is where I can work out which cell and therefore which model object my user wants to modify or access.
Second,
User Taps -> [myVC prepareForSegue...] - this is where I set up my detail view controller with the correct model object.
So, do I just store the selected model object in an instance variable between the two functions being called?

In prepareForSegue, the sender argument will be the cell, so you can work out which one was tapped at that point. You could also check the tableview's selectedIndexPath property.
You don't need to implement both functions.

I understand that you need to pass an instance of your model to your details view controller after you tap on a table view row. You have some ways to achieve that:
You can create a property in your view controller with a data type of your model. Let's name it for example firstObject. Then, inside didSelectRow you can set this property or update it according to your needs. Then, inside prepareForSegue you can pass this instance to your details view controller, by doing something like: detailsVC.detailsObject = firstObject.
Inside prepareForSegue, you can get the value of the current tapped table view row using indexPathForSelectedRow.row. Assuming that you have an array holding different objects of your model that you need them to be sent to your details view controller based on the tapped table view row index, you can do something like:
detailsVC.detailsObject = myObjectsArray[myTableView.indexPathForSelectedRow.row].
I hope that I was able to make it more clear for you.

Related

iOS tableview cell segue storyboard

I am currently implementing a simple fitness app.
I have each exercises for each tableviewcell row and when i click each tableviewcell, I want to segue it to tutorial screen where it shows short clip of video.
My question is;
If I have 100 different exercises, do i need to created 100 different segue for each exercises?
and how do I make different tableviewcells to segue into same view?
You asked "If I have 100 different exercises, do i need to created 100 different segues..."
In a word, no.
You could create a single view controller to view controller segue and give it an identifier.
Implement the tableView:didSelectRowAtIndexPath: method. In that method, save the selected indexPath to an instance variable and call performSegueWithIdentifier to invoke your segue.
In your prepareForSegue method, take the selected cell's indexPath and use it to look up the data for that cell. Cast the segue's destination view controller to the correct class, and then set a property you've defined in the destination view controller to the data you want to display for the selected cell (information about the selected exercise, in this case.)

WKInterfaceButton event handling in WKInterfaceTable

I have a WKInterfaceTable table view with a WKInterfaceButton.
How can I add a target action to the button from the table view. As there is no tag property I am not able to handle it.
If your WKInterfaceButton is contained within a row controller, here is one method to determine which row's button was tapped:
Add your WKInterfaceButton to the row controller and use interface builder to connect the button's action to your row controller class
Add a property to your row controller that allows you to reference your data (for example, a weak reference to your data or a tag)
Add a property to your row controller that allows you to set your interface controller as a delegate
Create a protocol for the delegate that allows you to pass the data reference
When initializing each row controller, be sure to set the data and delegate properties
When the button action is handled in the row controller, call the delegate method that you defined in your protocol. Something like:
- (void)rowController:(MyRowControllerClass *)rowController didSelectRowWithTag:(NSInteger)tag
Handle this delegate method in your interface controller to do whatever work is necessary.
I use this technique in my own Watch app, and it works very well.

Update Table View on command from View Controller

New to iOS programing and objective-c and am getting stuck on something which I am guessing is simple. Here's my question:
I have a simple, single view application with two text fields, a button and a table view. The idea is that I want to take the text from the two text fields and populate the next available cell in the tableview with this text. I've got everything sorted out except for how to update the contents of the table view on command. Ideally, I'd like the table view to be updated upon pressing the button.
I have a View Controller which is serving as the data source and delegate for the table view.
I am aware of the [tableView reloadData] method, but it requires the appropriate tableView variable within scope. This is fine in say a delegate method like tableView:didSelectRowAtIndexPath, and I've gotten it update upon selection of any cell, but what if I want to update the table view when an action unrelated to the table view is performed, say when the button is pressed? There is no tableView variable in scope of this method to call reloadData from (or is there)?
So I guess my question is: is there a way to access the table view variable from the rest of the view controller for the purpose of calling reloadData OR is there a method I'm not aware of that would facilitate this?
Thanks for any help!
Why do you you create an outlet for your table view in view controller?
Your view controller will be delegate and data source for the table view (you should set in interface builder or from code:
self.tableView.delegate = self;
self.tableView.dataSoure = self;
I am assuming that self.tableView - is the outlet that I mentioned. When ou have an outlet you can easily update table view after pressing the button: e.g you add new value to an array that is used for filling table view and call
[self.tableView reloadData];
If you do not want to reload all table you can use method insertRowsAtIndexPaths:withRowAnimation:
Actually you have to read next manuals as well:
https://developer.apple.com/library/ios/documentation/uikit/reference/UITableView_Class/Reference/Reference.html
https://developer.apple.com/library/ios/documentation/userexperience/conceptual/tableview_iphone/AboutTableViewsiPhone/AboutTableViewsiPhone.html
This references are really useful.

Populating a Text Field with a Selected Cell from a Separate Table View Controller

I have a working app which just needs some modification. It's a basic app with a Table View Controller that gets populated when a user taps the Plus button and fills in some information into text fields. The user will enter a name and event and I've made life easier by creating table view cells under the text fields so that when a user starts typing, it auto populates with the same names the user has entered before.
I'm using Core Data and NSFetchedResultsController. I'm modifying the app to be more seamless now for the user. Instead of the keyboard popping up when selecting the text field, I'm taking the user modally to another Table View Controller where the user can search, create or just select an existing entry from the Table View Cells.
I've got the new table view controller appearing and displaying the existing entries using NSFetchedResultsController and that's working well.
My question is: how do I go about selecting a Cell in the new Table View Controller and having that selection of the cell do two things:
1) Dismiss the Modal View
2) Populate the name text field (in the view controller that brought up the new Table View) with the selected name from the table view controller (that came up modally).
I have this working if the table view is in the same view controller, but I'm not quite sure how I would go about extracting that information from the other table view controller.
I'm guessing I would use protocols but I'm quite a newbie and so any pointing in the right direction or even some simple sample code would be massively appreciated!
Thanks,
You have to implement delegate protocol.
The idea is VC1 should conform the delegate (i.e. need to have a procedure -(void)dataAvail:(NSString *)data withViewController:(ViewController *)sender{...}). VC1 will push VC2 and set VC2.delegate = self.
In VC2, when cell is selected, just call [self.delegate dataAvail:self.yourTextField.text withViewController:self];
Now, in your VC1, you should implement dataAvail... just get the value and dismiss your modal VC2.
For more info on how to declare the protocol, just google for "ios delegate tutorial". delegate Protocol is used everywhere when coding for iOS (like MVC or KVC).

TableView index from rootcontroller to detailcontroller (UINavigationController)

My root view is a grouped tableview. When the user selects a row, i want to be able to retain which row was selected to give to the detailcontroller for loading the correct data.
All the navigation is working fine, I just don't want to have to create a global variable to just retain the index. Is there a built in method for the navcontroller or something?
You can either set a property in you detail view controller before it is pushed giving info about the row selected so it can influence the behaviour of the detail view controller, or it is possible to access the parent view controller directly from the detail view controller with:
#property(nonatomic, readonly) UIViewController *parentViewController
I prefer the first option - you can write a custom init... method, to supply the data for the detail view controller when it's created.
There isn't a builtin way as such, you should try and make the view controllers de-coupled as possible so they can be re-used and are resistent to changes elsewhere in the app.
This is a useful quote from the View Controller Programming Guide for iOS:
With the exception of view controllers managing leaf data, each custom view controller must provide a way for the user to navigate to the next level of the data hierarchy. A view controller that displays a list of items can use taps in a given table cell to display the next level of data. For example, when a user selects a photo album from the top-level list, the Photos application creates a new photo album view controller. The new view controller is initialized with enough information about the album for it to present the relevant photos.
I wanted to follow up with how I ended up coding this. I'm still somewhat new to Obj-C, so some concepts I haven't dealt with or come across, so if this is old hat, sorry.
You can create your data element in the child controller and pass the data 1 for 1 directly to that element by accessing its property.
ParentController.h
NSDictionary *myData;
ChildController.h
NSDictionary *childData;
// This would get called in the parent controller where appropriate
// but before the child controller is presented
ChildController.childData = myData;
This is obviously very stripped down, but the idea works. Just take your data and pass it to the property before calling it and it will be there once the child view is presented. Hope this helps.

Resources