send an array to next view controller - ios

In my app, I have 4 view controllers, (login,welcome,game view and results view). In the game view, I have two additional views (like this)[screen shot link to the views]. I am using a web api to get data, and my data is consist of items(each item has 1 image and 4 string). Item number is not constant so based on the amount of items(which I store it inside an array), I transition my views from one to another until I ran out of items.(The way I present is really similar to view transitions sample from apple. After displaying the last item, I use perform segue to go to next view.
The problem that I am trying to solve
I am trying to create an additional view/ or view controller that uses some part of the information from my items array.
my question
Why I am getting null for container views array ?(_results array is the array that has the items)
this is what I tried:
based on this question:
GameView
ContainerViewController *container = [[ContainerViewController alloc]init];
container.array = _results;
[self performSegueWithIdentifier:#"changetoResults" sender:self];
ContainerViewController.m
- (void)viewDidLoad
{
[super viewDidLoad];
NSLog(#"items in the array - containerviewcontroller.m %#",array);
}
this is the console:
2013-11-26 19:11:29.157 GuessTheImage[3664:70b] there are 8 , of items in the current index -gameviewcontroller.m
2013-11-26 19:12:44.439 GuessTheImage[3664:70b] items in the array - containerviewcontroller.m (null)
Thank you.

Because the ViewController that you create isn't the ViewController that you go to via the segue.
If you'd like to use a segue, you can get the destination ViewController (it already exists) in a prepareForSegue method and tune it however you want (in your case - add an array).
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"changetoResults"])
{
ContainerViewController *vc = (ContainerViewController *)[segue destinationViewController];
vc.array = _results;
}
}

There are two things that you are not doing correctly:
You are setting the array on a temporary view controller different from the instance activated by your segue, and
You are logging the array too early: viewDidLoad: is called before the segue code manages to put the array into the new view controller.
To fix the first problem, remove the two lines above the "perform segue" call, and add this method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"changetoResults"]) {
ContainerViewController *container = segue.destinationViewController;
container.array = _results;
}
}
To fix the second problem, move the logging code into the viewDidAppear:. NSLog should start showing the correct number of items.

Related

Need some insight to make a 3 UIButton menu in XCode that toggles and changes dataset in the main ViewController

I'm new on Stackoverflow and I'm currently learning XCode from scratch and I'm in a process of making a Single Page Application with options.
Anyone knows how to efficiently make a simple menu with multiple selectable UIButtons that make the main ViewController display different datasets depending on the selection in XCode?
Tried different things (creating SecondViewController for example but can't figure out how to pass data from it to main ViewController).
Any help will be greatly appreciated.
Refer this:
https://www.appcoda.com/storyboards-ios-tutorial-pass-data-between-view-controller-with-segue/
How to pass prepareForSegue: an object
Simple Test from above Answer Reference:
Simply grab a reference to the target view controller in prepareForSegue: method and pass any objects you need to there. Here's an example...
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Make sure your segue name in storyboard is the same as this line
if ([[segue identifier] isEqualToString:#"YOUR_SEGUE_NAME_HERE"])
{
// Get reference to the destination view controller
YourViewController *vc = [segue destinationViewController];
// Pass any objects to the view controller here, like...
[vc setMyObjectHere:object];
}
}
REVISION: You can also use performSegueWithIdentifier:sender: method to activate the transition to a new view based on a selection or button press.
For instance, consider I had two view controllers. The first contains three buttons and the second needs to know which of those buttons has been pressed before the transition. You could wire the buttons up to an IBAction in your code which uses performSegueWithIdentifier: method, like this...
//When any of my buttons are pressed, push the next view
- (IBAction)buttonPressed:(id)sender
{
[self performSegueWithIdentifier:#"MySegue" sender:sender];
}
// This will get called too before the view appears
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([[segue identifier] isEqualToString:#"MySegue"]) {
// 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];
}
}
Hope this help but please go through refernces!

Adding row to the TableView when Button action

I have two ViewControls.
In FirstViewControl i have button and,
In SecondViewControl i have TableView,
When i click on button it should go to the TableView(SecondViewControl) and add one row ,how can i do it with programatically.I did not getting sufficient answers.Can any one help me
First thing that you should do is to create an NSMutableArray property in FirstViewController. That array needs to be filled in with all data that will be displayed on SecondViewController.
#property (nonatomic, strong) NSMutableArray *arrayOfData;
Also create a NSMutableArray property in SecondViewController. Now when you have two properties that are capable of holding data, you can go to step when Button is pressed.
- (IBAction)buttonInCellPressed:(UIButton *)sender {
[arrayOdData addObject:#"E.g. some string.";
// Call transition to second view after button is clicked
[self performSegueWithIdentifier: #"GoToSecondViewController" sender: self];
}
Code above will add new element to the array, based on what you want to add you will need some customization. Once perform segue is called you will need to copy data before view is actually displayed. You will do that in prepareForSegue method.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// This string needs to be equal to one that you put in performSegue and on that is in storyboard
if ([[segue identifier] isEqualToString:#"GoToSecondViewController"])
{
SecondViewController *vc = [segue destinationViewController];
// This is array in second view controller
vc.arrayOfData = [NSMutableArray arrayWithArray:oldArray];
}
}
Now in the new controller, use arrayOfData to fill in TableView. Also, for this solution you will need to return array to the first controller, same process as you did when you send it to second one.
If you want to improve your code, you will need to implement some object that will hold data separately from views.

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.

Steps on how to push segue to tableviewcontroller

I am having issues displaying data in a tableview from a push segue. How do you make data appear in the tableview from the push segue? Do I need to implement a delegate/protocol? What method would I add my logic to display the rows in the TableViewController from the push segue. I able to navigate to the tableview and back to the button sort view controllers.
Can someone show me the process similar how I wrote My Logic? I am stuck on step 4. If you have a easier way to execute please let me know.
Controllers I am trying to coordinate.
"EventFeedController.m " TableViewController executed from Tab Bar Controller. This shows the events.
" ButtonSort.m " to push segue to EventFeedController.m
AppDelegate.m has array.
My Logic...
In the storyboard.
Control drag from UIButton in ButtonSort directly to EventsFeedViewController (not to the navigationcontroller but directly to the view EventViewController itself. ). (Not sure if I should control drag to view controller or the navigation controller of EventsfeedViewController)
Select push segue from popup of the control drag
Give Button a identifier of Button01 (This would find items array where eventFeed.eventType = #"Festival";) So for clarity Button01 = Find events with eventFeed.eventType = #"Festival";
Step I am stuck on. Not sure how to access or display the array created in AppDelegate.m didFinishLaunchingWithOptions paragraph. I thought cellForRowAtIndexPath in EventsFeedViewController would be responsible for being called and displaying the rows again.
Sample of array code AppDelegate.m
Events array created AppDelegate.m. I need to pull the event when clicking the push button segue.
_events = [NSMutableArray arrayWithCapacity:20];
//***************************************
// Event feed related area
//***************************************
SDEventsFeed *eventFeed = [[SDEventsFeed alloc] init];
eventFeed.eventTitle = #"Event Fest Test 1";
eventFeed.eventDescription = #"This is not to be missed";
eventFeed.eventStartTime = #"2:00 PM";
eventFeed.eventImage = [UIImage imageNamed:#"fest.jpg"];
eventFeed.eventType = #"Festival";
[_events addObject:eventFeed];
In the table view controller that you want to push to display the data, you will need to add a property to hold that data. Something like the following:
#property (nonatomic, strong) MyDataClass *myData;
Then in the view controller that you're pushing from (the one with the button that pushes the table view controller), you'll want to add a method - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender. You can implement it in a way like the following:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"YourSegueIdentifierFromStoryboard"]) {
YourTableViewControllerClass *viewController = segue.destinationViewController;
viewController.myData = self.myData;
}
}
To pull the data from the AppDelegate you would need to do the following.
Make sure you import the AppDelegate.h into your class doing the segue.
You can create a NSMutableArray property in AppDelegate.h to hold the array data "eventArray".
This is just one possible solution.
ButtonSort.m
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:#"Button01"]) {
YourTableViewControllerClass *viewController = segue.destinationViewController;
YourAppDelegate *appDelegate = (YourAppDelegate *)[[UIApplication sharedApplication] delegate];
viewController.events = appDelegate.eventsArray;
}
}

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

Resources