Three20 - Getting empty TableView when setting a TTTableViewController as TableBannerView - iphone

I have a TTTableViewController and want to show a tableBannerView (as shown in the sample code). The view to show is again a TTTableViewController:
- (void)toggleInfo {
if(self.tableBannerView) {
[self setTableBannerView:nil animated:YES];
} else {
CanteenInfoViewController *infoViewController = [[CanteenInfoViewController alloc] initWithCanteenID:[_canteen canteenID]];
[self setTableBannerView:infoViewController.view animated:YES];
[infoViewController release];
}
}
However, when calling [self toggleInfo], the tableBannerView that is shown is empty (I already checked that [infoViewController createModel]and [infoViewController viewWillAppear:] are called).
When presenting infoViewController modally ([self presentModalViewController:infoViewController animated:YES];), it is shown correctly.
Can anyone give me a hint on what I'm missing?
Thanks,
Tilo

Uhm... you create the infoViewController... set it's view as banner view... which probably increases the views retain count, but then you release the controller which results in a destruction of the controller(its retain count wasn't raised to 2), leaving it's view behind without a controller... are you sure that's what you want?

Related

Can I change the ViewController that calls presentViewController?

I have a ViewController, VC1a, that presents VC2:
VC1a -> presentViewController: VC2
Is it possible to change VC1a into VC1b so that when dissmissViewControllerAnimated is called, it animates to VC1b instead of VC1a?
The reason I ask is because I want to return to a different screen without it animating back to VC1a. This relates to portrait/landscape changes.
Warning. This is potentially a bad/confusing UI choice for your users. But if you must...
You may be able to put VC1a inside a UINavigationController and modify the navigation stack while VC2 is in the foreground. Something like:
// in VC1a.m
[self presentViewController:VC2 animated:YES completion:^{
NSMutableArray *navigationStack = [[NSMutableArray alloc] init];
for (UIViewController *viewController in self.navigationController.viewControllers)
{
if (viewController != self.navigationController.viewControllers.lastItem)
{
[navigationStack addObject:viewController];
}
else
{
VC1b *viewControllerToSwapIn = [[VC1b alloc] init];
// probably some more initialization here
[navigationStack addObject:viewControllerToSwapIn];
}
}
self.navigationController.viewControllers = navigationStack;
}];
or possibly a better idea:
// in VC1a.m
[self presentViewController:VC2 animated:YES completion:^{
VC1b *viewControllerToSwapIn = [[VC1b alloc] init];
// probably some more initialization here
[navigationStack addObject:viewControllerToSwapIn];
[self.navigationController popViewControllerAnimated:NO];
[self.navigationController pushViewController:viewControllerToSwapIn animated:NO];
}];
OK, I implemented a Container view controller with two children - one for portrait, one for landscape and this took care of my problem.
I have spent days trying to figure out how to handle rotation correctly within iOS6 and I didn't realise there was a bug in rotating UITableViewController when pushed from a UINavigationController.
Thanks for the response #paulrehkugler - I was getting pretty desperate when I asked this question. There just doesn't seem to be any good examples of how to handle orientation changes while UINav/TableViewControllers are presented from a main view. I certainly wasn't wanting to implement such a hack.

viewWillAppear not invoked when presenting the viewController modally (iOS)

I have an issue, viewWillAppear method in the UIViewController which is added to the screen by presentModalViewController method does not "go into" viewWillAppear method. Only time this method is invoked is together with the viewDidLoad, the first time.
- (IBAction)openModal:(id)sender {
if (self.nvc == nil) {
ModalViewController *vc = [[ModalViewController alloc] init];
self.nvc = vc;
[vc release];
}
self.nvc.segmentedIndex = [[self.navigationController.viewControllers objectAtIndex:0] index];
[self presentModalViewController:self.nvc animated:YES];
}
The property is of type retain.
Thanks in advance.
right, it works different and it now goes into viewWillAppear only once. So if you want to change the appearance of your view after dismissing a modal view you should do it using a modal delegate pattern. See the link:
http://useyourloaf.com/blog/2010/5/3/ipad-modal-view-controllers.html
Though it's for iPad, but you can get the idea. In the latest iOS versions it works the same.
Hope it helps

Hide detail View

I need to hide a detail view that is shown when clicked on a tableviewitem
- (IBAction)done:(id)sender {
[self.delegate OrderDetailsViewDidFinish:self];
}
It is all connected up with in the, xib and .h but the view doesnot close, it is loaded via this code and loads great:
//Initialize the detail view controller and display it.
OrderDetailsView *dvController = [[OrderDetailsView alloc] initWithNibName:#"OrderDetailsView" bundle:[NSBundle mainBundle]];
dvController.selectedOrder = (#"%#",selectedOrder);
[self presentModalViewController:dvController animated:YES];
[dvController release];
dvController = nil;
the trouble comes when closing it, please not i ahve all the correct .h in the detail view
Thanks
Mason
If you present a controller as a modalViewController then when hiding it you only need this:
- (IBAction)done:(id)sender {
[self.parentViewController dismissModalViewControllerAnimated:YES];
}
When you use modals a Parent-Child relation is created between two controller (the newly presented is the child) so you can call the previous controller with self.parentViewController from this new controller ;)

Retain/release pattern for UIPopoverController, UIActionSheet, and modal view controllers?

I'm somewhat unclear on the object ownership patterns required for the following instances. When my UIViewController presents a popover controller, an action sheet, or another view controller as modal, am I required to hang onto a retained reference to that child controller until it's been dismissed?
In other words, do the following lines of code effectively "transfer" ownership, or not?
[aPopoverController presentPopoverFromBarButtonItem:someButtonItem permittedArrowDirections:UIPopoverArrowDirectionAny animated:NO];
[anActionSheet showFromBarButtonItem:someButtonItem animated:NO];
[aViewController presentModalViewController:someOtherViewController animated:YES];
Can someone point me to explicit documentation on this subject?
UIPopoverViewController has a slight different memory management/owning. Present a popover does not retain the memory, so you can't transfer the ownership of your popviewcontroller to the presenting object.
To avoid memory leak, you have to adopt the UIPopoverControllerDelegate and implement the DidDismissPopOver method as follow:
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
[popoverController release];
}
This way, you can safe alloc and present a PopOver:
-(void)showSearch:(id)sender {
SearchViewController *searchVC = [[SearchViewController alloc] init];
UIPopoverController *popVC = [[UIPopoverController alloc] initWithContentViewController:searchVC];
popVC.delegate = self;
[popVC setPopoverContentSize:CGSizeMake(320, 100)];
[popVC presentPopoverFromRect:CGRectMake(200, 200, 320, 100) inView:self.view permittedArrowDirections:0 animated:YES];
[searchVC release];
}
Presenting a modal view controller retains the UIViewController. This is actually not clear from the docs. However, I tested it using the following code...
NSLog(#"BEFORE %d", [self.setupViewController retainCount]);
[self.navigationController presentModalViewController:self.setupViewController animated:YES];
NSLog(#"AFTER %d", [self.setupViewController retainCount]);
The self.setupViewController is already retained locally, but presenting it output the following:
2010-05-19 10:07:36.687 LocateMe[27716:207] BEFORE 1
2010-05-19 10:07:36.762 LocateMe[27716:207] AFTER 3
So it is probably being retained in the local modalViewController property, as well as in the view hierarchy. Dismissing it will balance these.
So bottom line is, retain it if you want to control it directly, but you don't have to.
EDIT - Just to be clear, the correct pattern is to always retain an object if you set yourself as its delegate. That's because you should be setting the delegate to nil in your dealloc for safety. Practically though, a modal controller is always going to be dismissed before you dealloc, so it's not an issue. You'll notice Apple also breaks this rule in [UIView setAnimationDelegate:], which actually retains the delegate you set.

after dismissing modal view, parent view seems deallocated?

I'm writing an iPhone app. Starting from a view controller in a navigation stack [called EditCreatorController], I am presenting a custom modal view controller [called BMSStringPickerController]. I have created a delegate protocol, etc. per the Apple guidelines for passing data back to the first view and using that view to dismiss the modal view. I even get the expected data back from the modal controller and am able to dismiss it just fine. The problem is, at that point, almost any action I take on the original view controller leads to debugger errors like
-[EditCreatorController performSelector:withObject:withObject:]: message sent to deallocated instance 0x3a647f0
or
-[EditCreatorController tableView:willSelectRowAtIndexPath:]: message sent to deallocated instance 0x3c12c40
In other words, it seems like the original view controller has evaporated while the modal view was showing. This is true no matter which of the two delegate callbacks is invoked.
Here is the code from the parent controller that invokes the modal view:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.row == 1) { // selection on creator type row
// create a string picker to choose new creator type from list
BMSStringPickerController *picker = [[BMSStringPickerController alloc] initWithNibName:#"BMSStringPickerController" bundle:nil];
picker.delegate = self;
picker.stringChoices = [NSArray arrayWithObjects:#"composer", #"lyricist", #"arranger", #"original artist", #"other", nil];
picker.currentChoice = creator.type;
picker.title = #"Creator Type";
// wrap it in a nav controller so we can get tile bar etc. (from VC prog guide p. 93)
UINavigationController *newNavigationController = [[UINavigationController alloc]
initWithRootViewController:picker];
[self.navigationController presentModalViewController:newNavigationController animated:YES];
[newNavigationController release];
[picker release];
}
}
And here are the delegate callbacks:
- (void)stringPickerController:(BMSStringPickerController *)picker didPickString:(NSString *)string {
NSLog(#"received string back: %#", string);
typeLabel.text = string; // only change the label for now; object only changes if done button pressed
[self.tableView reloadData];
[self dismissModalViewControllerAnimated:YES];
}
- (void)stringPickerControllerDidCancel:(BMSStringPickerController *)picker {
NSLog(#"picker cancelled");
[self dismissModalViewControllerAnimated:YES];
}
Another weird thing (perhaps a clue) is that although I get the "received string back" NSLog message, and assign it to typeLabel.text (typeLabel is an IBOutlet to a label in my table view), it never appears there, even with the table reload.
Anyone have some ideas?
Maybe you release the delegate in dealloc of BMSStringPickerController?
It may not solve your problem, but I suggest telling the picker to dismiss itself (in the delegate methods), allowing the responder chain to correctly handle the dismiss:
[picker dismissModalViewControllerAnimated:YES];
The default behavior when there is a memory warning is the release the view of all view controllers that are not visible. So if there was a memory warning while in your modal view controller, its parent view controller could have its view unloaded.
When this happens, viewDidUnload is called on the view controller so that you can release any references you hold into the view. If you have references that you didn't retain they will become invalid when the view is unloaded. Maybe this is happening in your case?
See the UIViewController reference Memory Management section for details. The UIViewController method didReceiveMemoryWarning: releases the view if the view is not currently visible and then calls viewDidUnload.