I'm seem unable to get any kind of communication going between my Main View Controller and a Table View Controller which is being displayed inside a Popover View (iPad).
I'm setting up the Table View inside a Navigation Controller in the usual way:
// create popover
if (self.popoverController == nil) {
filesViewController = [[[MyTableViewController alloc] initWithFiles:fileList] autorelease];
UINavigationController *navCtrl = [[[UINavigationController alloc] initWithRootViewController:filesViewController] autorelease];
self.popoverController = [[UIPopoverController alloc] initWithContentViewController:navCtrl];
self.popoverController.delegate = self;
// resize popover
self.popoverController.popoverContentSize = CGSizeMake(320.0, 44 + [fileList count] * 44);
}
Everything is working fine, and I'm passing an array of file names (fileList) into the Table View, which is held in the Table View as an array called listOfFiles. The Table View displays the filenames, and when one is selected by the user I want to pass that filename back to the Main View Controller. However, I cannot get any communication going back from the Table View's didSelectRowAtIndexPath method to the Main VC. I've tried all sorts of outlets going in various directions, and I've tried creating a new object in didSelectRowAtIndexPath to handle the filename coming from the Table View. I can pass the filename out to the new object, but when I try to send that into the Main VC it is null again. Everything I send to my Main VC while that popover is active comes up as null.
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
NSLog(#"%#", handler.addressForImageFile);
self.popoverController = nil;
[self.popoverController release];
}
Is there some reason why my Main VC won't get anything but null objects from my Table View? I've spent days trying so many different things. I feel like there's some fundamental gap in my knowledge of how popovers work. Surely there is a simple way to send a string back to my Main VC when it is selected from the Table View?
Thanks so much for any help!
There's propably a much better way to do this, but depending on the goal of passing the string, one way could be to use NSUserDefaults.
Related
I have a ViewController with a TableView and a MapView and a button which opens a PopOver with another TableView. There the user can select some positions which should be shown on the Table and the MapView in the mother ViewController.
I have a function which calculates the table data and draws those annotations in the mother ViewCoontroller. This is called from the child ViewController by initiating it:
MotherViewController * MVC = [[MotherViewController alloc] init];
[MVC calculateresults];
The selected data is then passed back via protocol and the function calculates the proper results. However the table won't reload because [self.TableView reloaddata] doesnt work when the PopOver is still opened. If I close the PopOver and start the function directly on the mother ViewController everything works fine.
Tried already this, but doesn't work:
iPad SplitViewController: Reloading the root view controller's tableview from the detail view controller
How can i update a Map and a Table in a mother ViewController while a PopOver is opened?
The reason this is failing is not that "[self.TableView reloaddata] doesnt work when the PopOver is still opened." The reason is that self is a different self. You are saying:
MotherViewController * MVC = [[MotherViewController alloc] init];
[MVC calculateresults];
So MVC is not the MotherViewController whose view you see behind the popover. It is a different MotherViewController - the one you just created with alloc. So the MotherViewController that you see behind the popover never gets any message, so it does nothing.
Naturally when you do this directly in that MotherViewController, it works.
Instead of saying
MotherViewController * MVC = [[MotherViewController alloc] init];
You need to arrange for your popover to have a reference to the already existing MotherViewController.
So in my universal app I have a section where a person can look at an existing list of notes from our system (retrieved through a simple web service) and then also create a new note if they want. So for the iphone it's pretty simple layout, a TableViewController for displaying the list with a "Add" button on the NavigationBar that presents the modalview for adding the new item. On the iPad though, the same layout has a lot of wasted space so I opted to go with the popOver method to show the list in a popOver and then let them add from there. My problem is that when the user clicks on the Add button within the PopOver view, the modal view comes up full screen instead of just coming up within the popover view. Here's the code I have so far:
-(void) AddButtonPressed:(id)sender {
NewNoteVC *newNote = [[[NewNoteVC alloc] initWithNibName:#"NewNoteVC" bundle:nil] autorelease];
newNote.defaultClientID = defaultClientID;
UINavigationController *navCon = [[[UINavigationController alloc] initWithRootViewController:newNote] autorelease];
if ([isPopOver isEqualToString:#"YES"]) {
[navCon setModalInPopover:YES];
[self.navigationController setModalInPopover:YES];
[self.navigationController presentModalViewController:navCon animated:YES];
}
else {
[self.navigationController presentModalViewController:navCon animated:YES];
}
}
The "isPopOver" string is just a placeholder sent from the previous screen that called this TableView (I know I can switch this to a boolean for better performance I just put this together real quick to try it out). I know I messed up somewhere, I just don't know what setting I need to get this working correctly.
You need to define the view controller's modalPresentationStyle to be "current context".
navCon.modalPresentationStyle = UIModalPresentationCurrentContext;
This will result in modal view controller filling the popover like the popover's root controller.
Try using the presentViewController:animated:completion: instead of presentModalViewController:animated: and set self.navigationController.definesPresentationContext = YES
Hi in VC1 I have an NSMutableArray displaying results. I want to keep that array alive even when users clicks to a different tab (so they don't have to search again) until the user searches again.
I have a strong pointer to it, but it seems to unload when I leave the view.
Not much code to show (_resultsArray is set from a previous controller using delegates, so it loads with the results already)
- (void)viewDidLoad
{
[super viewDidLoad];
_resultsTableView.dataSource=self;
_resultsTableView.delegate=self;
[self.navigationController.navigationBar setHidden:YES];
}
//then standard tableview delegate methods...
This code is to try to figure out how to segue tab bar to share info.
(in prepareforsegue)
Currently in Search VC. Now I have results I want to give to resultsIndexVC. The code below attempts this.
This is placed in current (search VC) prepare for segue.
ResultsIndexViewController* vc = [[ResultsIndexViewController alloc] init];
UITabBarController* tbc = [segue destinationViewController];
vc = (ResultsIndexViewController *)[[tbc customizableViewControllers] objectAtIndex:1];
vc.SearchDelegate=self;//crash here (normally works if using regular segue)
vc.resultsArray = _temporaryResultsArray;
vc.originalQuery=_queryArray;
Thanks
Issue is that I was pushing a VC. Instead I used the tabbar (which doesnt release the object when switching tabs)
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.
I am using my app delegate to transition between view controllers. When the delegate decides it no longer needs the view controller, based on messages from the server, it needs to remove the current view and replace it with another one. Currently my code looks like the following:
- (void) showFight: (NSNotification*) notification
{
if(self.window.rootViewController != self.fightViewController)
{
NSDictionary* dict = [notification userInfo];
FightViewController *fightView = [[FightViewController alloc]
initWithNibName:#"FightViewController" bundle:nil];
fightView.userId = _userId;
self.fightViewController = fightView;
[fightView release];
[self.radarViewController.view removeFromSuperview]; // Doesn't work.
self.window.rootViewController = self.fightViewController;
[self.fightViewController showMonster:dict];
}
}
I know my view controller isn't being removed because I can hear sound effects from it in the background.
I want to completely destroy the view controller, as I only want one view controller in memory at any time. I plan to create the view controller each time from scratch, as shown in the code above. Am I doing this improperly?
The problem here seems to be that you are not releasing the view controller. Think about what actually happens in your code at:
[self.radarViewController.view removeFromSuperview];
You remove the view from its super view. The view controller still exists, and what it does is control what should be shown on the view, and in your case apparently playing sound.
Put in an easy way: The view controller is an object. It has a child, the view. That's another object. You remove the view from another view, but the object controlling the removed view still lives (and actually, so does the view object).
If you want to kill the entire view controller, call this after removing the view from its superview:
[self.radarViewController release];
Or, if the view is a retain property (which i assume by looking at your code) you can also use:
self.radarViewContoller = nil;
which automatically releases for you in the synthesized setter.
When the view controller is released, its reference count is subtracted by one. If the reference count reaches zero, then the controller will be deallocated.
So far I understand your problem is to add the new ViewController on server notify and change the current view with new View. First of all you've to add the view controller just like below because the reference won't help to update the view.
[self.window.rootViewController.view addSubview: self.fightViewController.view]
In my opinion you need to tag your Controllers and check before adding the controller that if it's already exist in the memory, otherwise the pool of object will leak. Just Say No to Memory Leaks!!
- (void) showFight: (NSNotification*) notification
{
UIView *fightView = (UIView *)[self.window.rootViewController.view viewWithTag: FIGHT_VIEW_TAG];
if (self.window.rootViewController.view.tag != fightView.tag) {
NSDictionary* dict = [notification userInfo];
FightViewController *fightView = [[FightViewController alloc]
initWithNibName:#"FightViewController" bundle:[NSBundle mainBundle]];
//Remove the current view.
[self.window.rootViewController.view removeFromSuperview]; // If you're adding the fighting View in the root View, then why are you trying to remove current view through radar controller which has already added in the window (root view).
fightView.userId = _userId;
[fightView setTag: FIGHT_VIEW_TAG];
[self.window.rootViewController.view addSubView: self.fightViewController.view];
[self.fightViewController showMonster:dict];
[fightView release];
}
}
You don't need to take them as global until your requirements are different.