I have found a project with expandable table view cells and it works great. The view controller is initialised in AppDelegate.m like this:
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
AccordionTableViewController *vc = [AccordionTableViewController new];
self.window.rootViewController = vc;
[self.window makeKeyAndVisible];
I have InboxTableViewController with some content and it has "Menu" button on it(push segue) which goes to the second ExpandableCellTableViewController. When I go to 2nd view, I only see empty cells. But when I use the code in AppDelagate - this view has all content that it supposed to, but in such case, this 2nd controller becomes initial and its the only accessible view.
So, my question is - why table view cells are empty, while it works when it is initialised in AppDelegate.m
I will add any other code that will be required as I am not sure what should I provide at this stage. Thank you.
EDIT:
I have just found that arrays that hold data for tableview cells are empty when i NSLog them in viewDidLoad when the view initialised in my way (through button press). But works when initialised form AppDelegate.m.
I put NSLog into - (id)init but it seems like it is never called, and this is why data holding arrays are empty.
What you will need to do is create another UIViewController whose UIView will contain nothing but a button. Now initialize that ViewController in your app delegate like you have dont in the code sample above.
Once that is done, add an action for the button in your UIViewController class and open up your new controller at this point.
Does this help ?
Firstly, I figured out that my data holding arrays are empty by logging them out in viewDidLoad. So I though, that they don't get initialised. So I put NSLog in - (id) init and indeed, init is never called. I searched for it and found this thread: ["-(id) init" do not fire in ViewController when using storyboard
It suggested to use:
- (id)initWithCoder:(NSCoder*)aDecoder
{
if(self = [super initWithCoder:aDecoder])
{
// Do something
}
return self;
}
This worked for me.
Hope someone adds more details to this answer, explaining why it happens.
Related
I'm developing an application which will work based on maps. So once user opens MapViewController then I will load some data every 5 seconds.
I'm using navigation controller(Push view controller).
So every time when user goes to MapViewController viewdidload method calling. I don't want like that.
That's why I'm trying to avoid viewdidload method like tabbarcontroller.
Is there any way to achieve this?
viewDidLoad is getting called because your MapViewController is getting deallocated when you pop it off of the top of your navigation controller. When you recreate the view controller, it's getting allocated all over again, and the view loads again. If you keep a reference to MapViewController in the class containing your navigation controller, then ARC will not deallocate the object, and you can use this reference to push it back onto the stack so viewDidLoad will not get called again.
Edit: Adding code for reference:
MapViewContoller *mapViewController; // declared globally so there's a strong reference.
- (void) openMapViewController {
if (!mapViewController) {
mapViewController = [self.storyboard instantiateViewControllerWithIdentifier: MapViewControllerID];
}
[self.navigationController pushViewController: mapViewController, animated: YES];
}
Try this
-(void)clickForPush{
// declarre viewcontroller e.g 'saveRecipeVC' instance globally in interface
if (!saveRecipeVC) {
saveRecipeVC = [self.storyboard instantiateViewControllerWithIdentifier:SaveRecipeVCID];
}
[self.navigationController pushViewController:saveRecipeVC animated:YES];
}
viewDidLoad is intended to use when,not possible or efficient to configure 100% of an interface in a XIB. Sometimes, a particular property you wish to set on a view isn't available in a XIB. Sometimes, you use auto layout, and you realize that the editor for that is actually worse than writing auto layout code. Sometimes, you need to modify an image before you set it as the background of a button.
If you dont want to do these things make your viewDidLoad empty. Than avoiding. Or
Add code conditionaly into your viewDidLoad.
(void)viewDidLoad {
[super viewDidLoad];
if(condition) {
// put your code here
}
}
I have 2 ViewControllers that I use App delegate to switch them according to user interaction.
in AppDelegate.m I have:
- (void) switchViews
{
if (_viewController.view.superview == nil) {
[_window addSubview:_viewController.view];
[_window bringSubviewToFront:_viewController.view];
[viewController2.view removeFromSuperview];
} else
{
[_window addSubview:_viewController2.view];
[_window bringSubviewToFront:_viewController2.view];
[_viewController.view removeFromSuperview];
}
}
_viewController is for main view and _viewController2 is for glview(I am using isgl3d). The switch works but everytime I switch back to glview, I see duplicated view on top, which I suspect even main view is duplicated too.
Any idea how can I remove the view entirely so that I don't have this issue? Thanks!
You shouldn't be adding and removing the views like this, just change which controller is the root view controller of the window. Doing that make the new controller's view a subview of the window, and removes the old controller's view.
if ([self.window.rootViewController isEqual: _viewController]) {
self.window.rootViewController = viewController2;
}else{
self.window.rootViewController = viewController;
I found out how to do this after watching Stanford Coding Together:IOS.
Some critical info of VC that I am not aware of:
Everytime VC is instantiate, viewDidLoad is called once to setup all the important stuff like outlets and such. Then viewWillAppear and viewWillDisappear will be called for in between view swapping. Because it is called just a moment before view is shown to user, all the geometry setting like view orientation and size is set here.
so what I do is:
I addSubview in viewDidLoad, the do all the running setup in viewWillappear and viewWillDisappear.
one more note: view will remain there as long as the app still running.
anyway Thanks rdelmar for helping.
This is the first time I'm trying to implement navigation from a tableView cell to another tableView using UINavigationController and it doesn't work for me.
I'm NOT using nib file and I have a simple tableView that I present it in a modal dialog in my app, it works fine, now I added the disclosureInidcator to one of it's cell, to make the user enable to choose from a fixed number of options available from another list(tableView). For this purpose I have another class that makes the second tableView. the problem is now navigation from the cell(contains disclosure icon)in first tableview to second tableView doesn't do anything, no error, no nothing. I guess the way I setup the navigation controller would be wrong, the code doesn't fall in delegate, or datasource of the second class at all.
in First TableView in method : didSelectRowAtIndexPath I tried to catch that row, then call the second tableView like this:
mySecondViewController *secondVC = [[[mySecondViewController alloc] initWithStyle:UITableViewStyleGrouped ] autorelease];
UINavigationController *navCont = [[UINavigationController alloc] initWithRootViewController: self];//not sure the first controller should act as the root controller?
[navCont pushViewController:secondVC animated:YES]; //it does nothing, no error,...
the second tableViewcontroller class contains all delegate and datasource methods, and initialization method:
- (id)initWithStyle:(UITableViewStyle)style
{
if ((self = [super initWithStyle:style])) {
}
return self;
}
and declared in interface as:
#interface stockOptionViewController : UITableViewController {
}
I tried to play with viewDidLoad, but didn't help.
Please help me cause I have no clue and all sample codes found is based on using nib files.
Thank,
Kam
Your navigation controller should be the root view controller of the app delegate's window, and the first view controller should be the root view controller of the navigation controller, then you can push new controllers onto it.
Please see the documentation for UINavigationController.
At the moment, you are creating a navigation controller but not putting it anywhere, so asking it to push new view controllers is a little pointless. You have the right code, just not in the right order.
You can present view control modally without nav controller
mySecondViewController *secondVC = [[[mySecondViewController alloc] initWithStyle:UITableViewStyleGrouped ] autorelease];
[self presentModalViewController:secondVC animated:YES];
UINavigationController should be the root view controller. In the current code, navCont is not on the view stack, so it won't work. Instead of pushing myFirstViewController in your appDelegate, push the UINavigationController to the stack and add myFirstViewController as its root view controller.
I'm trying to do a very simple pushViewController with a view controller created from a nib.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ServiceDetailViewController *serviceDetail = [[ServiceDetailViewController alloc] initWithNibName:#"ServiceDetailViewController" bundle:nil];
serviceDetail.employee = _employee;
[self.navigationController pushViewController:serviceDetail animated:YES];
previousSelectedRow = indexPath;
}
If I return the window of the serviceDetail view controller within its viewDidLoad or anywhere else inside of its functions it is null. When I return its window right after pushViewController it is fine.
My viewDidLoad is normal. I am calling super.
It seems like this is either something silly that I'm overlooking, a problem with my splitViewController setup, or a bug in xCode 4/ARC.
I understand I may need to provide a lot more code but I'm hoping someone might have an idea.
viewDidLoad is called right after a view is loaded into memory, but before the view is added to the view hierarchy including the backing window. The viewDidAppear method is called right after being added to a window. Maybe your code needing the window value will work better in that method.
I have a split-view app that allows a user to select and display a thumbnail of a chosen image. I have placed a UIButton in the detailViewController using Interface Builder. When this button is pressed, I would like to have it change to a full screen view of the image. I have set up a new View Controller, called FullViewController and thought I had everything connected. The problem is that the navigation controller is null. I adjusted the AppDelegate.m to the following:
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after app launch.
// Set the split view controller as the window's root view controller and display.
self.window.rootViewController = self.splitViewController;
UINavigationController *nvcontrol =[[UINavigationController alloc] initWithRootViewController:fullViewController];
[window addSubview:nvcontrol.view];
[self.window makeKeyAndVisible];
return YES;
}
This is the function in the DetailViewController.m which is called when the button is pressed. The navigation controller comes up null in here.
//Function called when button is pressed - should bring up full screen view
- (IBAction) pressFullViewButtonFunction: (id) sender{
//viewLabel.text = #"Full View";
if (fullViewController == nil){
FullViewController *fullViewController = [[FullViewController alloc] initWithNibName:#"FullViewController" bundle:[NSBundle mainBundle]];
NSLog(#"fullViewController is %#", fullViewController);
self.fullViewController = fullViewController;
}
NSLog(#"self.navigationController is %#",self.navigationController);//this is null
[self.navigationController pushViewController:self.fullViewController animated:YES];
}
I'm not sure how to fix this. I've tried adding in the couple lines in the AppDelegate, but when it runs, the table in the root view doesn't show up and it no longer properly switches between portrait and landscape views.
I have the rest of the code readily available if that would help clarify. Just let me know!
Thanks.
From the code you post it is not possible to identify the problem, but two common reasons for self.navigationController to be nil are:
you did not push the object behind self on to the navigation controller in the first place; indeed it seems so, since the navigation controller is added as a subview of the split view controller; possibly you mean the opposite... not sure...
(sub-case of 1) you showed the object behind self using presentViewControllerModally.
When I say "the object behind self" I mean the instance of the class where pressFullViewButtonFunction is defined.
If you need more help, post the code where you push your controllers on to the navigation controller...
On a side note, if you do:
UINavigationController *nvcontrol =[[UINavigationController alloc] initWithRootViewController:fullViewController];
and nvcontrol is not an ivar, then you have a leak.
Hope this helps...