This is my first time posting and I was just having issues with a "get your feet wet" project (simple tip calculator) I am doing in my spare time.
What I want to do is, to pass an array from ViewController1 to ViewController2, then I want to load ViewController2 and refresh UITableView that is located on ViewController2.
I use ViewController1 to take the user submitted data and calculate the results. I want to take those results and send it over to ViewController2 to display the results. I'm doing this because it's a tabbed application and I want the results to display on another tab.
Here is how I pass the data from ViewController1 to ViewController2
-(void) displayCalculationsView:(NSMutableArray *)array{
UIStoryboard *story = [UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil];
CalculationsViewController *viewController2 = [story instantiateViewControllerWithIdentifier:#"ViewController2" ];
[viewController2 setArrayValueAndRefreshTable:array];
[self.tabBarController setSelectedIndex:1];
}
Here is what is on the receiving end:
-(void)setArrayValueAndRefreshTable:(NSMutableArray *)array{
if (calculationsDisplayArray == nil) {
calculationsDisplayArray = [[NSMutableArray alloc] init];
}
[calculationsDisplayArray removeAllObjects];
[calculationsDisplayArray addObjectsFromArray:array];
for (NSString *data in pushedDisplayArray) {
NSLog(#"PUSHED ARRAY DATA: %#", data);
}
[tableView reloadData];
}
The data seems to be received fine because it displays all the correct data in the NSLog. However, when the [self.tabBarController setSelectedIndex:1]; part hits, it wipes out my calculationsDisplayArray, after the page has loaded.
Is there any way to prevent it from becoming nil? I'm using ARC and it doesn't let me use [arrayname retain]; I'm not sure I want to use segue because I don't have access to my array in the segue method (or do I?), so I would not be able to send it over to the other view.
Once again, I am new at this. So if there is any more clarification needed, please tell me and I will update this post. Thank you.
As others have pointed out, you have created a new view controller instead of accessing the one in your tab bar. You should access your existing view controller:
CalculationsViewController * viewController2 = [self.tabBarController.viewControllers objectAtIndex:1];
Related
In my app there is one view controller that collects information for saving. When the user clicks done, however, I then give the user the option to save some additional information on a second view controller.
In the first VC, the user creates a new object and saves values to its properties. I imagine these are in the managed object context.
If the user elects to go to the second view controller, rather than first save, I would like to pass the object to the second controller and do all the saving after the second batch of info is entered.
Is this allowed?
When I use following code and log the object to console from the second VC, it seems to be null.
Thanks for any suggestions.
-(void) launchSecondVC {
UIStoryboard *storyBoard = self.storyboard;
secondViewController *secondVC =
[storyBoard instantiateViewControllerWithIdentifier:#"alternate"];
UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController: altVC];
// Do whatever setup you want to here for your title bar, etc
secondVC.object=_object;
[self presentModalViewController:nav animated:YES];
}
I have an application that starts with a list of tasks and drills down through one or two list views to a final UIViewController. Due to the project requirements, these view controllers need to be created and navigated programmatically, not via segues in Interface Builder. I have accomplished this with single lists and regular view controllers, but one case has me stumped.
I currently have several UITableViewControllers in Interface Builder that point to other UITableViewControllers, basically a drill-down list. I'm unsure how to create a list item in my UITableViewController that creates another UITableViewController populated with list items I send it, and then navigates to it.
I need the UITableViewController to be generic, so I can create multiple drill-down lists using the same UITableViewController code.
Does this make sense? I feel like it should be a simple thing, but my brain just hasn't made the connection on how yet.
EDIT: Let me try to better illustrate my problem. My UITableViewController contains list items that are passed to it, and an array of objects associated with those items. The UITableViewController uses these objects to create the final UIViewController screen in most cases.
TableVC.h
#interface TableVC : UITableViewController <UITableViewDataSource, UITableViewDelegate>
//Menu items
#property NSMutableArray *itemList;
//Objects to pass to the detail ViewController
#property NSMutableArray *itemObjectList;
- (void)initWithList:(NSMutableArray *)items :(NSMutableArray *)objects :(NSString *)title;
#end
TableVC.m
NSMutableArray *items = [NSMutableArray arrayWithObjects:
NSLocalizedString(#"List Item 1",nil),
NSLocalizedString(#"List Item 2",nil), nil];
NSMutableArray *objects = [[NSMutableArray alloc]init];
MenuListObject *obj1 = [[MenuListObject alloc]init];
obj1.name =NSLocalizedString(#"Name",nil);
obj1.department=NSLocalizedString(#"Department",nil);
obj1.address=#"Address";
obj1.imgName=#"XXXYY.jpg";
obj1.menuIndex=0;
obj1.typeFlag=#"F";
...
[objects addObject:obj1];
[objects addObject:obj2];
TableVC *vc = [[TableVC alloc]init];
[vc initWithList:items :objects :NSLocalizedString(#"My Title",nil)];
[self.navigationController pushViewController:vc animated:YES];
However in some cases the list items don't go to a UIViewController. Instead they lead to another list, which then ends up at the UIViewController. I know how to create list items, but not a list item that leads to another UITableViewcontroller.
If there's a better way to handle all of this, I'm open to suggestions.
You can do this with segues aswell. Just make a "dummy segue" from a bar button item back to the view controller itself.
See this screenshot:
Then you can trigger this segue programmatically - i.e. when tapping a cell in a table view - to make an "infinite" stack of the same view controller.
And if you don't want segues. Just create the view controller programmatically, and push it manually. The same "reuse"-concept applies here.
Declare a class of type UITableViewController.
In it's .h file, declare an NSArray to hold the data.
In the .m file, implement the tableview delegate and data source methods, using the array as the data source.
In your calling tableViewController, in tableView:didSelectRowAtIndexPath:,
create a new instance of the tableviewController class,
then set it's array to the list of items you want to pass it,
and push it:
[self.navigationController pushViewController:_the_new_instance_ animated:YES];
I ended up using a third type flag in my TableViewController to denote when a list item should fire off a new list view rather than go to my destination UIViewController.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MenuListObject *obj = nil;
for (int i=0; i<self.itemObjectList.count; i++){
obj = [self.itemObjectList objectAtIndex:i];
if (obj.menuIndex == indexPath.row){
break;
}
}
if (obj!=nil)
{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
if ([obj.typeFlag isEqualToString:#"F"])
{
if (obj.url ==nil)
{
FacilityDetailVC *vc = [storyboard instantiateViewControllerWithIdentifier:#"FacilityDetail"];
vc.name=obj.name;
vc.department=obj.department;
...
[self.navigationController pushViewController:vc animated:YES];
}
else if ([obj.typeFlag isEqualToString:#"T"])
{
TextDetailVC *vc = [storyboard instantiateViewControllerWithIdentifier:#"TextDetail"];
vc.titleText=obj.titleText;
vc.descriptionText=obj.descriptionText;
vc.URL=obj.url;
[self.navigationController pushViewController:vc animated:YES];
}
//This is the part I added, to redirect to the UITableViewController
else if ([obj.typeFlag isEqualToString:#"L"])
{
TableVC *vc = [[TableVC alloc]init];
[vc initWithList:obj.listItems :obj.listObjects :obj.titleText];
[self.navigationController pushViewController:vc animated:YES];
}
}
I have two view controllers. First is empty, second contains a text field. If this field is empty, I need to move to the second controller automatically.
I tried this:
NSUInteger VCcount = self.navigationController.viewControllers.count;
UIViewController *btVC = self.navigationController.viewControllers[VCcount-2];
if([self.btViewController.Text.text isEqualToString:#""])
{
[self.navigationController pushViewController:btVC animated:YES];
}
and this:
UIViewController* btVC = [storyboard instantiateViewControllerWithIdentifier:#"BTViewController"];
But at the first launch program knows only current controller and doesn't know about thesecond.
How can I get there?
See the example below:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.textField.text = #"some text";
if (self.textField.text.length == 0) {
UIViewController *secondVC = [self.storyboard instantiateViewControllerWithIdentifier:#"secondVC"];
[self.navigationController pushViewController:secondVC animated:NO];
}
}
If you comment out the assignment of "some text" to the textField, the secondVC will be instantiated and presented. I don't know what exactly you are trying to achieve with first two lines of your presented code.
If the secondVC already exist, you can just take a reference to it by knowing its index on the stack, or inspecting viewControllers array of your navigationController before you push it to the stack. If it does not exist, you just instantiate it from storyboard (with the correct identifier) and push it.
i have one problem i hope someone can help, im try to create an app like catalog, in the first view i have a table view with "x" number of items, this tableview is only an image of product, and then when you click on cell (image) the app send to you to another view, that view is the detail of the item.
worth mentioning that in the view controller is the table where I create a NSMutableArray with all products, then when you go to open the following view I do using the following code:
viewController cakeViewController * = [self.storyboard instantiateViewControllerWithIdentifier: # "ViewController"];
UINavigationController * navigationController = [[UINavigationController alloc] initWithRootViewController: viewController];
viewController.selectCake = [_cake objectAtIndex: indexPath.row];
[self presentViewController: navigationController animated: YES completion: nil];
and works but in the second view i try to put a suggestion cake with img and when click image refresh or reload the view but with the data of the suggested cake.
thanks a lot!
When creating a new view controller to be pushed onto the stack, what is the correct method to use to populate that view controller with data?
I have a data object that I need to send to the view controller, which will then set it's text fields, etc. with the data.
ItemDetailViewController_iPad *detailViewController = [[ItemDetailViewController_iPad alloc] initWithNibName:#"ItemDetailViewController_iPad" bundle:nil];
[detailViewController populateWithData:_data];
[self.navigationController pushViewController:detailViewController animated:YES];
in ItemDetailViewController_iPad:
-(void) populateWithData:(Item*)_data
{
self.data = _data;
self.navigationItem.title = self.data.title;
self.descriptionText.text = self.data.desc; //the text does not get updated - it's the default text from the nib file
NSLog(#"Desc: %#", self.data.desc); //this logs valid data
}
You can also declare a property in that VC and then set that property before pushing it. Then in the viewDidLoad method for the pushed VC, set the view's title and text field.
The code you've posted should work fine.
There are lots of ways to do this, and it often comes down to what you understand best, feel most comfortable with, and isn't too dull to type in.
Here are some other options.