UITableView with toolbar and multiple segues - ios

I have a simple storyboard file with a table view inside a navigation controller. If you cick one of the cells it goes to the details view. Great.
Then I tried adding a toolbar button and hooking it up to my table view controller. The button and the seque seems to work fine, except now, when i click on one of the table cells, the modal view is triggered.
So it seems I have done something wrong, but I don't understand what.
// called by pressing the add button in the toolbar
- (IBAction)showAddEventView:(id)sender {
[self performSegueWithIdentifier:#"showAddEvent" sender:sender];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"showAddEvent"]) {
AddEventVC *addEventVC = [[AddEventVC alloc] init];
// set some property
} else {
EventIndexVC *eventIndexVC = [segue destinationViewController];
eventIndexVC.eventTitle = [self.events objectAtIndex: [[self.tableView indexPathForSelectedRow] row]];
}
}

Related

How to populate a cell in UITableView with an edited content?

Maybe I didn't ask it properly, because I'm not really sure how, so I will explain myself:
I have a simple notes app with two VC's:
table view controller - to list all the notes.
view controller - to create new notes.
In the table vc I have an unwindToList method that create an instance of the create notes page to get the note object that will be passed and if its not nil I will add it to the notes array and reload the data;
- (IBAction) unwindToList: (UIStoryboardSegue *) segue
{
NMCreateNotesViewController *source = [segue sourceViewController];
NMNote *note = source.note;
if (note != nil) {
[self.notes addObject:note];
[self.tableView reloadData];
}
}
and an prepareForSegue method that will identify if this segue is a note segue (this is the segue I JUST want to preform editing in the create note page and when a user taps the save button, to save it in the same cell that the segue came from...):
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(UITableViewCell *)sender
{
if ([[segue identifier] isEqualToString:#"noteSegue"]) {
NMCreateNotesViewController *destination = [segue destinationViewController];
NSInteger indx = [self.tableView indexPathForCell:sender].row;
NMNote *note = self.notes[indx];
destination.passedInString = note.content;
}
}
In the view controller that create the notes I have a prepareForSegue method that looks like this:
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if (sender != self.saveButton) return;
if (self.textField.text.length > 0) {
self.note = [[NMNote alloc] init];
self.note.content = self.textField.text;
}
}
Now, my problem is that when i'm editing a note from the noteSegue i'm creating a new note with the edited content instead of populating the same cell of the segueNote with the new edited content...
this is how the problem looks like:
Please help me to figure this out :/
Appreciate it!
I don't quite understand your explanation.
You have a table view controller that is a master view controller and a note view controller that is a detail view controller.
The usual way to handle communications back from a detail view controller to it's master is to set up a delegate.
Define a delegate property in the detail (notes) VC that will point back to the master.
In the master's prepareForSegue, set destination.delegate = self.
Then, define a protocol for the delegate that the detail view controller will use to tell the master that the contents of a list item has changed.
You will probably need to tell the detail view controller the indexPath of the item that's being edited in the master-to-detail segue, and then before unwinding to the master, invoke a delegate method that gives the edited item to the master, along with it's indexPath so the master can save the changes and redisplay that cell.

Multiple buttons to one Table View

Can someone point me in the right direction? I have one View Controller with multiple buttons. I want the button presses to open my custom one Table View Controller and load the data dynamically. I know I could make multiple Table View Controllers for each button press, but I was thinking there has to be a way to do this dynamically. Let me be clear that another view will determine which data to load into the Table View Controller. I'm new to iOS and Objective-C, but not programming, so take it easy on the rocket science answers. Let me know if you need to see some code.
Basically I have 4 buttons on one View Controller that when pressed will determine what data to load on the Table View. Let's keep it simple for now and just say that the data is 4 NSMutable Arrays.
EDIT:Based on babygau's post this is what I came up with:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"allCattleSegue"]) {
CattleTableViewController *controller = segue.destinationViewController;
controller.cattleArray = [[NSMutableArray alloc] initWithObjects:#"cattle1",#"cattle2",#"cattle3", nil];
}
else if ([segue.identifier isEqualToString:#"bullsSegue"]){
CattleTableViewController *controller = segue.destinationViewController;
controller.cattleArray = [[NSMutableArray alloc] initWithObjects:#"bull1",#"bull2",#"bull3", nil];
}
}
- (IBAction)allCattleTouchUpInside:(UIButton *)sender {
[self performSegueWithIdentifier:#"allCattleSegue" sender:self];
}
- (IBAction)bullsTouchUpInside:(UIButton *)sender {
[self performSegueWithIdentifier:#"bullsSegue" sender:self];
}
this gets the job done but now my navigation doesn't work properly when I press the back button. It gives me a blank screen.
UPDATE: Debugging I see that it is calling the prepareForSegue twice; once with the Controller as the sender and again with the button as the sender. Still attempting to understand how this works and how to resolve this navigation issue.
RESOLVED: Apparently I don't need the actions (TouchUpInside) wired up. Thanks for all of the help.
Hi just create one Viewcontroller and TableViewController. Set the tag fro all button and then create one #property int variable in TableViewController then do like this below..
Create common method to trigger for all button in UIControlTouchUpInside .Then in UITableViewController create int variable like this.
TableViewController.h file you create like this.
#property (nonatomic, assign) int buttonSelected;
ViewController.m create common method like this.
-(IBAction)commonMethod:(id)sender
{
TableViewController *tableVc = [[TableViewController alloc]initWithNibName:#"TableViewController" bundle:nil];
if(button.tag==0)
{
tableVC.buttonSelected = 0;
}
if(button.tag==1)
{
tableVC.buttonSelected = 1;
}
[self.navigationController pushViewController:tableVc animated:YES];
}
TableViewConroller.m file do this
-(void)viewDidLoad
{
[super viewDidLoad];
if(buttonPressed == 0)
{
tableDataSourceArray = ...
}
else if (buttonPressed == 1)
{
tableDataSourceArray = ...
}
}
I hope it helpful for you..
Assume that your table has tableViewData is an array.
In each button action, you use the following pattern code:
[self performSegueWithIdentifier:#"YOUR_IDENTIFIER" target:sender];
Implement the following segue delegate method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
YOURCUSTOMTABLEVIEWCONTROLLER *tableVC= segue.destinationViewController;
tableVC.tableViewData = YOUR_CORRESSPONDING_MUTABLE_ARRAY;
[tableVC.tableView reloadData];
}
That's it, you will have tableView display dynamically based on which button you click.
Notice: you have to create 4 segue between View Controller corresponding to 4 buttons and name the identifier for each segue. e.g #"fromButton1toTableVC", #"fromButton2toTableVC" and so on...
You could pass something like the button label or an identifier telling which mutable array to use.
if your doing the transition in code using a segue in your prepareForSegue method you can pass the value to the destination TableViewController i.e.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
UITableViewController *controller = segue.destinationViewController;
controller.buttonTitle = sender;
}
Then in the button handler
[self perfomSegue:#"segue" sender:buttonTitle];
assign tag for each button. according to tag you can populate different data in table.simply take only one array.populate data to that array according to tag
if(button.tag==0)
{
//array=#[..];
}
if(button.tag==1)
{
//array=#[..];
}
.
.
.
Now use this array in cellForRowWithIndexPath delegate method

How do I set the title on the destination view controller during prepareForSegue:

I want to simply set the title on my destination view controller so that it shows in its navigation controller's navigation bar in the prepareForSegue: method however setting its title or navigationItem like so:
[segue.destinationViewController setTitle:#"doesn't work"];
[segue.destinationViewController.navigationItem setTitle:#"this either"];
doesn't work possibly because the destination's view controller's view isn't loaded yet. Can I do this without creating a custom destination view controller?
Try accessing your ViewController that is embedded in the UINavigationController like this.
First you give your segue an identifier in the interface builder, then you access the segue in the prepareForSegue method and set the title by accessing the topViewController property of the navigation controller you segue to.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"yourSegueIdentifier"]) {
UINavigationController *navController =
(UINavigationController*)[segue destinationViewController];
YourViewController *destViewController =
(YourViewController* )[navController topViewController];
destViewController.navgationItem.title.text = #"Your new title";
}
}
This is for a segue into another UITableView
Set a public NSString property in the destination UITableViewController file.
#property (strong, nonatomic) NSString *navBarTitle;
Override the setter in the .m file just to be sure.
- (void) setNavBarTitle:(NSString *)navBarTitle
{
_navBarTitle = navBarTitle;
}
In the originating tableView's segue method, pass whatever string you need in the title.
- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString: #"userDetails"]) {
UsersActivitiesTableViewController *destinationController = segue.destinationViewController;
//Get the index path of the cell the user just clicked
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
//Grab the object from the array of users if the next view requires a specific title for a user name etc.
UserMO *thisUser = [self.users objectAtIndex:indexPath.row];
//Pass the string you want as the title to the public NSString property
destinationController.navBarTitle = thisUser.name;
}
}
And now for the important bit....
In the destination controller, get the top controller of the view and set the title property, after the view is loaded, and before it has been displayed:
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController topViewController].title = self.navBarTitle;
}
If you want a static title this can now (i.e., in Xcode 4.6.3) this can be done in Storyboard simply by setting the title in the nav bar on the relevant view controller.
If however you want the nav bar title to change according to what view is being segued to, e.g., a detail of a particular table row, as far as I know that needs to be set programmatically.
It took me FOREVER (newbie, sigh!) to figure out how to modify Julian Vogels' correct answer to call the key I wanted to use. Here's what worked:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:#"DetailSegue"]) {
// Fetch Item
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
NSDictionary *item = [self.groceries objectAtIndex:[indexPath row]];
// Configure Detail View Controller
TPDetailViewController *vc = [segue destinationViewController];
vc.navigationItem.title = [item objectForKey:#"name"];
[vc setItem:item];
}
If the segue is a push segue - which it should be if you're using a UINavigationController - then the destination view controller is automatically added to the window hierarchy, and you don't even need to identify the UINavigationController:
if ([segue.identifier isEqualToString:#"yourSegueNameHere"]) {
[segue.destinationViewController setTitle:#"yourTitleHere"];
}

One segue - a few buttons

Okey guys, here's the deal...
I'm trying to connect two views with one segue and writing in Label a tag from clicked button. I hope you know what I mean...
Here's the example:
Title view appears and you have to choose the difficulty 1-3 (tag values of buttons) and after clicking your're moved to game view but you'd like to use tag values from title view buttons in game logic.
Here's the sample screen:
This is what I've found and this perfectly suits!
// When any of my buttons are pressed, push the next view
- (IBAction)buttonPressed:(id)sender
{
[self performSegueWithIdentifier:#"Segue" sender:sender];
}
// This will get called before the view appears
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"Segue"]) {
// Get destination view
SecondView *vc = [segue destinationViewController];
// Get button tag number (or do whatever you need to do here, based on your object
NSInteger tagIndex = [(UIButton *)sender tag];
// Pass the information to your destination view
[vc setSelectedButton:tagIndex];
}
}
And here is the link to whole topic.
Set your buttons to trigger the segue that presents the second view controller.
In your first view controller, implement - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender and use the sender to retrieve the tag.

Dynamically showing TableView or DetailView

From my TableView I dynamically want to show either a TableView or a DetailView (new segue), based on the cell's content. I setup two segues from the TableView to different DetailViews and one segue from the TableViewCell to the TableView.
I have almost completed the implementation using performSegueWithIdentifier: (see below), but there is one struggling issue remaining: after I call [self dismissModalViewControllerAnimated:YES]; on the DetailView it returns to an empty TableView . I assume because the Storyboard segue from the UITableViewCell is performed. By clicking the back button I return to my original (parent) TableView data.
Any suggestions for this work?
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSLog(#"%s", __PRETTY_FUNCTION__);
NSString *type = [[self.dataController objectInListAtIndex:[self.tableView indexPathForSelectedRow].row] valueForKey:#"cell_type"];
NSLog(#"cell_type: %#", type);
if([[segue identifier] isEqualToString:#"DetailSegue"])
{
UIViewController *detailViewController = [segue destinationViewController];
detailViewController.game = [self.dataController objectInListAtIndex:[self.tableView indexPathForSelectedRow].row];
} else if ...
} else if([[segue identifier] isEqualToString:#"TableViewSegue"]){
if([type isEqualToString:#"TableView"]){
//Create child ViewController, a custom ViewController with custom initWithId:Title:
CategoryViewController *categoryViewController = [[segue destinationViewController] initWithId:categoryId Title:categoryTitle];
}
}
}
I would create in my tableview multiple cells. Each with its own identifier. Then connect each cell to its own detailviewcontroller. You can also connect a cell to its own view controller (creating drill down functionality for only specific cell).
Thats all...

Resources