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.
Related
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.
I have a UISplitview controller (with a master and detail view). So, when the detailview loads the viewDidLoad calls a function named [self animateToPosition]; with the following code:
-(void*)animateToPosition
{
NSLog(#"Called Function");
[worldV animateToPosition:MaplyCoordinateMakeWithDegrees(-122.4192, 37.7793) time:1.0];
[self.view setNeedsDisplay];
return 0;
}
Now, when this is first run, my globeViewC correctly animates to the position passed in (worldV is initialized and created an all in viewDidLoad of detailviewController also "Called Function" is printed in the log.
However, I have a view controller and in the didSelectRowAtIndexPath I have the following code (in the file masterViewController.m)
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([[testArray objectAtIndex:indexPath.row]isEqualToString:#"Menu1"]) {
DetailViewController *test=[[DetailViewController alloc]init];
[self addChildViewController:test];
[self.view addSubview:test.view];
[test didMoveToParentViewController:self];
[test animateToPosition];
}
}
When I select the cell called menu1, "Called function" DOES display in the NSLog, but the animation that occurred when the view was first loaded doesn't anymore. I'm wondering if I must somehow reload the detailviewcontroller or initialize it again (but I tried initializing it again and that didn't work)
Would like if someone could see this and help me get this working.
It would be helpful if you could show more, especially how you alloc and init your worldV and what you have in your viewDidLoad.
Normally you don't create a new DetailViewController for SplitView setup.
Instead of creating a new DetailViewController, try to grab a hold of the existing detail view controller by creating a property:
#property(strong, nonatomic) DetailViewController *detailViewController;
and:
self.detailViewController = (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];
First thing to test here is whether your worldV is nil. A simple NSLog in animateToPosition would reveal the answer.
And whenever you need to call that method, do:
[self.detailViewController animateToPosition];
To animate from one coordinate to another with time, you may need to change your animateToPosition method to:
-(void)animateToPosition:(MaplyCoordinate)coordinates time:(CGFloat)time
Consult whether or not your MaplyCoordinate is an object, which I doubt.
So, to sum up, in your tableview's viewDidLoad, get a hold of the detail view controller.
When didSelectRow gets called, use the new method suggested and pass the coordinate and time this way:
[self.detailViewController animateToPosition:coordinates time:1.0];
Hope this helps.
In didSelectRowAtIndexPath function you create an DetailViewController but you don't add it to the view hierarchy. You should add it to the parent view controller like this
[self addChildViewController:viewController];
[self.view addSubview:viewController.view];
[viewController didMoveToParentViewController:self];
or just add it to navigation or present it as a modalViewController
I have a UITableViewController within a UIViewController. While this table viewcontroller was the only one involved, it was pushing views just fine when the user would tap a row. However, ever since I moved it to be one of two contained within the UIViewController, the taps of rows suddenly do nothing.
I've tried searching around and I'm not the first to run into this problem, but none of the answers fit my circumstances or the questions have no working answers. That link was the closest I found, but I'm not using storyboards -- I'm using separate XIBs.
So how do I push a new view from a viewcontroller within a viewcontroller?
To recap:
Here is what I had, and it worked fine in taking users to a new screen!
// Normal table behavior, as illustrated by [another question][2].
- (void)tableView:(UITableView *)tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
SomeView *detailViewController = [[SomeView alloc] initWithNibName:#"SomeView" bundle:nil];
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
}
Now I have the viewcontroller as a property in a view -- and the above code, which is in the file for the tableviewcontroller and not at the "main" view, doesn't cause a new screen to appear anymore!
Thanks for the comments! Here's some code to clarify my scenario.
The controllers within a controller. This is a file from a test project I've been using to test the concept out. In this case, I have a tableview controller within a tableview controller.
#interface SimpleTableViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
// This is the controller within the controller
#property IBOutlet SecondTableViewController *secondTableController;
#property IBOutlet UITableView *secondTable;
My SecondTableViewController has this fun bit.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
UIViewController *detailViewController = [[UIViewController alloc] initWithNibName:#"SimpleNonTableViewController" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[manualViewControllerParent.navigationController pushViewController:detailViewController animated:YES];
}
The view that the user interacts with is hooked up to SimpleTableViewController. In this way, SecondTableViewController is "within" SimpleTableViewController. Feel free to comment if you'd like more details!
I've put my test/concept project on github. https://github.com/hyliandanny/TableViewCeption
You need to use a custom container controller to do what you want. It would be easiest if you used a storyboard, but you can do it in code with xibs as well. The outer controller should be a UIViewController, not a table view controller. You can do something like this (in the outer controller):
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UIViewController *detailViewController = [[UIViewController alloc] initWithNibName:#"SimpleNonTableViewController" bundle:nil];
[self addChildViewController:detailViewController];
detailViewController.view.frame = set the frame to what you want;
[self.view addSubview:detailViewController.view];
[detailViewController didMoveToParentViewController:self];
}
You should read up on Apple's documentation for custom container controllers.
What you need to make sure:
Your UITableView delegate is hooked up to your controller. Otherwise it wouldn't call didSelectRow. You can do this in xib or in viewDidLoad method.
Your self.navigationController is not nil
Your detailViewController is not nil
I also think that what you mean is you have UITableView inside your UIViewController. UITableView is only the view, whereas UITableViewController is a controller. You can't have a controller inside another controller.
I have a view controller embeded in another view using 'addSubView' that is not catching events, how can I make sure it does?
background:
I'm attempting to nest views in order to break up a storyboard that is to be shared by multiple devs. To accomplish this with minimal duplication of functionality I/we have created a mainStoryboard which contains a tab controller and 4 tabs, each tab contains a subview that loads a UIView (contained in another storyboard) into itself. These views are added like so:
//Add sub view
UIStoryboard *board = [UIStoryboard storyboardWithName:#"MessagesStory" bundle:nil];
UIViewController *boardController = [board instantiateInitialViewController];
[self.view addSubview:boardController.view];
boardController.view.frame = CGRectMake(0, 0, 320, 480);
The initial view controller that is loaded is a UITableView subclass, the whole thing works great for rendering the table and it's contents to the screen and I can interact with the table and select rows, however the event listener on the the views controller 'didSelectRowAtIndexPath' fails to fire.
I know it's not firing thanks to good ol' NSLog():
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"Please kind sirs help a poor string appear in the console.");
}
I know it is related to the subview because if I load the subview on it's own as the main view the event listener functions properly.
Any help is appreciated as this is taking longer than expected and I may be pulled to another project before I can finish implementing this.
I figured it out.
It was stunningly simple but I had to do quite a bit of reading to find the answer. All my searches where for 'addSubView' tutorials and examples I didn't even know 'addChildViewController' existed.
Anyway I believe it's this simple:
-(void)viewDidAppear:(BOOL)animated
{
if (firstLaunch) {
firstLaunch = NO;
//Find the view controller in the other storyboard
UIStoryboard *board = [UIStoryboard storyboardWithName:#"MessagesStory" bundle:nil];
UIViewController *boardController = [board instantiateInitialViewController];
//add it as a child view controller (THIS IS WHAT I WAS MISSING)
[self addChildViewController:boardController];
//now it is okay to add the subview
[self.view addSubview:boardController.view];
//trigger this method (also missing this but it will run without it, I assume is good practice)
[boardController didMoveToParentViewController:self];
}
[super viewDidAppear:animated];
}
Once I knew I wanted to 'addChildViewController' it was easy to find information:
How does View Controller Containment work in iOS 5?
Is it wise to "nest" UIViewControllers inside other UIViewControllers like you would UIViews?
I finally managed to trim my code and put all the TableViewController-Methods in a separate class (away from my ViewController). I had many problems which I already solved but there is one that puzzles me.
When a selection in the table occurs, I previously loaded a modalViewController, which worked fine. But now, as I put all the Table-methods in a separate class, the modal view simply does not load. It calls the function, and steps through it nicely when I select a row in the table, but there is no view loaded on the screen of my iPhone?!
Here is the code:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
TaskViewController *taskViewController = [[TaskViewController alloc] initWithNibName:#"TaskViewController"
bundle:nil
task:[listOfEntries objectAtIndex:indexPath.row]];
taskViewController.modalTransitionStyle = UIModalTransitionStylePartialCurl;
[self presentModalViewController:taskViewController animated:YES];
[tableView deselectRowAtIndexPath:indexPath animated:NO];
}
any suggestions?
Problems loading the NIB file? Not returning self from TaskViewController's init method? Are you sure taskViewController is not nil? Maybe you should call this on a parent navigationController? Are you setting UIModalPresentationFullScreen as the modal presentation style?