I'm trying to populate UITextFields inside a UITableViewController with a click of a cell. So, I created an init method like:
- (id)initWithObjetoFormulario:(ObjetoFormularioGerenciador *)umObjeto
{
self = [super init];
if(self){
self.objetoFormulario = umObjeto;
}
return self;
}
In my ViewDidLoad I put the line if(self.objetoFormulario){ and after that link the UITextFields to my Object. I don't think there's anything wrong at this point.
So, my Second TableViewController is a SearchDisplayController, it finds the Data I need and at didSelectRowAtIndexPath I have:
ObjetoFormularioGerenciador *objeto = [[ObjetoFormularioGerenciador alloc] init];
[objeto RecebeArrayComDadosECriaObjetoFormularioGerenciador:_arrayComDados eEmail: [searchResults objectAtIndex:indexPath.row]];
GerenciarSeriesTableViewController *gerenciador = [[GerenciarSeriesTableViewController alloc] initWithObjetoFormulario:objeto];
[self.navigationController pushViewController:gerenciador animated:NO];
As I don't have the actual objects in my cells, I call a method to retrieve the object according to the cell entry, that is working as well, now, it opens a blank TableView when I click the cell. It should go Back to my tableView with static Cells containing UITextFields and populate them.
When I use this code:
ObjetoFormularioGerenciador *objeto = [[ObjetoFormularioGerenciador alloc] init];
[objeto RecebeArrayComDadosECriaObjetoFormularioGerenciador:_arrayComDados eEmail:[searchResults objectAtIndex:indexPath.row]];
UIStoryboard *sb = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
GerenciarSeriesTableViewController *gerenciador = [sb instantiateViewControllerWithIdentifier:#"GerenciarSeriesTableViewController"];
[self.navigationController pushViewController:gerenciador animated:NO];
It does open the TableView I want, but it doesn't populate the UITextFields as I didn't pass any object.
Thanks.
Yes, you really don't generally have custom init methods for view controllers, but rather rely upon the standard ones, and then once the view controller has been instantiated, you'd just set the property then, e.g.:
ObjetoFormularioGerenciador *objeto = ... // create and configure objeto
GerenciarSeriesTableViewController *gerenciador = [self.storyboard instantiateViewControllerWithIdentifier:#"GerenciarSeriesTableViewController"];
gerenciador.objetoFormulario = objeto;
[self.navigationController pushViewController:gerenciador animated:NO];
You can also have a segue between the two view controllers, give it an identifier, and then call [self performSegueWithIdentifier:...], and then set the objetoFormulario in the prepareForSegue method. But the above technique should work fine, too.
Related
I have a tableviewcontroller that needs to drill down and show 3 layers of data. I have no problem drilling down but when I go back, the cells and table become empty. I'm currently using storyboard and I didn't have this problem when I was using nib. All I had to to was alloc and initWithNibName the same view and it would create another instance of the same TableView and I can go back and all the data would be there.
I've tried using segue but it's not working as I need the tableviewcontroller to segue back to itself if I'm drilling down. I've created my own method to push the view controller and pass data into the new instance of itself
- (void)drillDown{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:[NSBundle mainBundle]];
ExerciseTableViewController *tableView = [storyboard instantiateViewControllerWithIdentifier:#"ExerciseTableView"];
tableView.title = _detailTitle;
tableView.delegate = self;
tableView.level = _level;
tableView.currentSMID = _currentSMID;
tableView.currentMID = _currentMID;
tableView.muscleNameArray = _muscleNameArray;
if (_level == 2) {
tableView.submuscleNameArray = _submuscleNameArray;
}
[self.navigationController pushViewController:tableView animated:YES];
}
This is what I have in my viewDidLoad
- (void)viewDidLoad {
[super viewDidLoad];
UIBarButtonItem *add = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:#selector(addExercise:)];
self.navigationItem.rightBarButtonItem = add;
NSLog(#"level: %i, currentSMID: %i, currentMID: %i", _level, _currentSMID, _currentMID);
if (self.managedObjectContext_ == nil) {
self.managedObjectContext_ = [(AppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
if (_level == 1) {
_submuscleNameArray = [self submuscleGroup:_currentMID valueForKeyPath:#"submuscleGroup"];
_submuscleIDArray = [self submuscleGroup:_currentMID valueForKeyPath:#"submuscleID"];
} else if (_level == 2) {
//loading and sorting exercise list
_exerciseList = [self loadExercise:_currentMID sub:_currentSMID];
_exerciseListSorted = [self sortKeysByName];
} else {
[self loadMuscleGroup];
}
}
The table view is only populated when I put some of this code in the viewDidAppear but I can't differentiate between drilling down and going back up with the viewDidAppear.
Isn't the navigationController suppose to save my current view and push a new view and when I pop the new view, I go back to my current view?
It seems like everytime I pop the view, the previous view needs to load all over again and this is causing my previous views to become blank.
Any suggestions?
Storyboard attached
So I figured out what was the issue. I have a variable called _level and I use it to track which level of drill down I'm in. When passing this variable to the next level, I've replaced the current level with the next level number therefore when I come back to the previous view. The current level is the same as the next level which screwed things up.
I've solved it by creating a new variable called nextLevel and passing that down instead.
Very basic error on my part.
I'm brand new when it comes to app development so this might be a stupid question. So i have made a UI table. Each row is a different topic. I want to allow users to click on a table cell and it'll direct them to another view controller. All the view controllers will have different content arranged in different ways. Any idea how to implement this using storyboard or just programatically? Appreciate it!
To answer the main question of the post, here is how you create an array of view controllers:
// create your view controllers and customize them however you want
UIViewController *viewController1 = [[UIViewController alloc] init];
UIViewController *viewController2 = [[UIViewController alloc] init];
UIViewController *viewController3 = [[UIViewController alloc] init];
// create an array of those view controllers
NSArray *viewControllerArray = #[viewController1, viewController2, viewController3];
I'm not so sure this is what you actually need to do given your explanation, but without more information this answers the initial question.
You really don't want to create all the view controllers at once and have them sitting there in memory - you really only want to create them when they're actually needed - which is when the user selects the cell. You're going to want to do something like the following to achieve what you want to do:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
if (indexPath.row == 0) {
// create the view controller associated with the first cell here
UIViewController *viewController1 = [[UIViewController alloc] init];
[self.navigationController pushViewController:viewController1 animated:YES];
}
else if (indexPath.row == 1) {
// create the view controller associated with the second cell here
UIViewController *viewController2 = [[UIViewController alloc] init];
[self.navigationController pushViewController:viewController2 animated:YES];
}
else {
// etc
}
}
I am trying to get a UITableView to show up after I tap a next button, I can't get it to work...
I don't know why TimesViewController.m isn't working, how do I link it...
-(IBAction)nextView:(UIBarButtonItem *) sender{
[self pushViewController:TimesTableViewController.m animated:YES];
}
You need to read through View Controller programming guide. Essentially, it depends more on your application design. The most common ways of doing this are:
Tap on nextView should present TableView controller modally.
Tap on nextView should push TableView controller in the navigation stack.
With either of the approach, you need to create a separate view controller for your table view which will manage the table view and act as delegate/data source for it.
From within your button action handler you need to do it this way:
-(IBAction)nextView:(UIBarButtonItem *) sender{
MyTableViewController *tableController = [[MyTableViewController alloc] init];
// For #1 above
[self presentViewController:tableController animated:YES completion:^{
// Any code that you want to execute once modal presentation is done
}];
// For #2 above
[self.navigationController pushViewController:tableController animated:YES];
}
EDIT:
Create a initialize method on your MyTableViewController and pass the values while calling it.
- (id)initWithData1:(NSString *)iData1 data2:(NSString *)iData2 {
if ((self = [super init])) {
self.data1 = iData1;
self.data2 = iData2;
}
return self;
}
MyTableViewController *tableController = [[MyTableViewController alloc] initWithData1:#"Some String" data2:#"Another string"];
PS: You could also expose the string property in your header file of MyTableViewController and set it from the callee class
or if you wanna do it programmatically, in your viewDidLoad, after you created your button
[firstsessionButton addTarget:self action:#selector(showtable:) forControlEvents:UIControlEventTouchUpInside];
-(void)showtable:(UIButton *)sender{
TableViewController *tableViewController=[[TableViewController alloc]init];
[self.navigationController pushViewController:tableViewController animated:YES];
}
I was wondering how I can load a different view into the detailView from rootview..
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
SecondViewController *svc = [[SecondViewController alloc] init];
//[self.navigationController pushViewController:svc animated:YES];
}
}
The splitviewcontroller has an array of 2 views one is root view and another one is detail view,and you can change the views in this array. If you alloc and init a view and replace it with either of these two then this view will replace the current view in the splitviewcontroller.
Use this code for loading different views for different cells of rootview. Change rootview's didSelectRowAtIndexPath method as follow:
- (void)tableView:(UITableView *)aTableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
UIViewController *localdetailViewController = nil;
if (indexPath.row==0)
{
DetailViewController *detailView=[[DetailViewController alloc] initWithNibName:#"DetailView" bundle:nil];
localdetailViewController=detailView;
detailView=nil;
}
if (indexPath.row==1)
{
SecondViewController *secondDetailView=[[SecondViewController alloc] initWithNibName:#"SecondDetailViewController" bundle:nil];
localdetailViewController=secondDetailView;
secondDetailView = nil;
}
UINavigationController *navController=[[UINavigationController alloc] init];
[navController pushViewController:localdetailViewController animated:YES];
YourSplitViewAppDelegate *delegate=[[UIApplication sharedApplication] delegate];
NSArray *viewControllers=[[NSArray alloc] initWithObjects:[delegate.splitViewController.viewControllers objectAtIndex:0],navController,nil];
delegate.splitViewController.viewControllers = viewControllers;
[localdetailViewController release];
[navController release];
}
My solution is using Using Xcode 7.1.1 for a universal app, using Storyboards, Auto Layout and Size Classes, building for iOS 9...
I used a version of Midhun MP's answer... within the current/original (not replacement/new/second) detail view controller's viewDidLoad method:
obviously first import the correct header file for your controller:
#import "NEW_DetailViewController.h"
then within viewDidLoad method:
- (void)viewDidLoad {
[super viewDidLoad];
<<OTHER_CODE>>
if (<<INSERT_THE_LOGIC_YOU_NEED_TO_TRIGGER_THE_REPLACEMENT_DETAIL_VC>>) {
NEW_DetailViewController *viewNewDetailVC = [[NEW_DetailViewController alloc] initWithNibName:#"NEW_DetailViewController" bundle:nil];
UINavigationController *navController = [[UINavigationController alloc] init];
[navController pushViewController:viewNewDetailVC animated:YES];
NSArray *arraySplitViewControllers = [[NSArray alloc] initWithObjects:[self.splitViewController.viewControllers objectAtIndex:0],navController,nil];
self.splitViewController.viewControllers = arraySplitViewControllers;
}
}
NOTE I could make this code work without loading a XIB file, building the entire replacement detail VC in code, with [[UIViewController alloc] init] instead of [[NEW_DetailViewController alloc] initWithNibName:#"NEW_DetailViewController" bundle:nil], but was frustrated that I could not make the XIB file load, so I persisted...
I attempted many variations from many different SO answers in attempting to solve this problem of successfully loading a XIB file as the replacement detail view controller in a split view controller.
Finally this answer by Travis M gave me the hint I needed...
Delete all the efforts you have attempted to date to create a new XIB file and subclass of UIViewController!
Create a new file and make it a subclass of UIViewController. See screenshot:
IMPORTANT ensure you check the checkbox "Also create XIB file".
You don't need to modify the new subclass of UIViewController, unless you'd like to code up the contents of the view. I only needed to add in a UILabel for my solution and I did this using Interface Builder.
Make sure you reference the replacement view controller NEW_DetailViewController in code as per my example above.
That's it!
In your XIB file you should end up with the following:
I have an app in portrait, in my View Controller (UIViewController, not a UITableViewController) there is a table (UITableView) that only occupies half the screen.
I set the delegate and datasource of my table view to my view controller.
Now, I would like to show a detail view when i select any cell of my table. Here is what I tried but nothing appears:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(#"SELECTED");
//ChangeView
DetailViewController *dvController = [[DetailViewController alloc]
initWithNibName:#"DetailViewController" bundle:nil];
[self.navigationController pushViewController:dvController animated:YES];
dvController = nil;
}
Any idea? Is this solution better than a popup solution?
You Should check your tableview in nib file it datasource and delegate is connected or not?
just connect both with file owner.
and if you are using uiview controller then use present model view controller not push modelview controller.
DetailViewController *dvc=[[DetailViewController alloc]initWithNibName:#"DetailViewController" bundle:nil];
[self presentModalViewController:dvc animated:YES];
Put [NSBundle mainBundle] in place of nil. Hope it helps. Tell me what happens!
Also replace dvController=nil; with [dvController release];
EDIT:
Replace ur init function with this one:
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
return self;
}
initialize navigation controller. becauze some time it is due to ui component which has not initialized. but remember that you may have to face some other UI issues
You should check if didSelectRowAtIndexPath is really called or not when you select a table cell (of not, your delegate may not be set correctly), then if
DetailViewController *dvController = [[DetailViewController alloc] initWithNibName:#"DetailViewController" bundle:nil];
returns nil or something meaningful with a debugger, trying to close in on the problem. Also, #M.A.Khan was right, you should remove
dvController = nil;
and replace it with
[dvController release];
giving up the reference in your main view.
Edit:
Your code asumes that beneath your UIViewController, there is a UINavigationController because you're using [self.navigationController pushViewController]. If there isn't, no wonder your view does not get pushed onto something that doesn't exist.
is the viewcontroller with tableview in a navigationcontroller?if not then first you have to create a navigationcontroller with the current viewcontroller as the rootviewcontroller.then try this code u are using now