MyVC* bottle = [[MyVC alloc] initWithDelegate:self];
bottle.title = #"bottle";
if ( water == nil )
water = [[UIPopoverController alloc] initWithContentViewController:bottle];
else
water.contentViewController = bottle;
This code runs once....when I click again on UITableViewCell my app crashes..
I am unable to figure it Out Why??
ERROR
-[UIPopoverController setContentViewController:animated:] can only be called after the popover has been presented.'
NOTE When Change my code this to following it works:
MyVC* bottle = [[MyVC alloc] initWithDelegate:self];
bottle.title = #"bottle";
if ( water == nil )
water = [[UIPopoverController alloc] initWithContentViewController:bottle];
else
water = [[UIPopoverController alloc] initWithContentViewController:bottle];
But i uses memory as double allocation is present.How can I resolve this
You are making a confusion between initialisation, presentation, and content modification of your UIPopoverController.
It is OK to store your popover on an instance variable, to avoid recreating it every time. It doesn't cause any trouble either to set the contentViewController to a new instance of "Bottle" if that "water" exists already.
But your error messages says it all: -[UIPopoverController setContentViewController:animated:] : you are trying to change the content of your popover with an animation. It means, your popover must already be presented (i.e. visible). For doing so, use one of the two methods starting with presentPopoverFrom... before changing its content.
In other words, only once your popover is presented, you can animate a change of content. Note also that it makes no sense to animate a change when your popover is not yet presented / visible. Use the setter .contentViewController = for that (or the non-animated method).
A note on your edit/note: Writing the same allocation in the two branches of the if/else clause is pointless. And it doesn't cause the system to use twice memory. Because when the compiler sees the second line ("else"...), it first releases the existing instance of the popovercontroller before allocating the new one and making the "water" instance variable point to it.
If you want to push then try this
MyVC *Newpage = [[MyVC alloc] initWithNibName:#"MyVC" bundle:nil];
[self.navigationController pushViewController:Newpage animated:YES];
If you want too go back from this page i.e pop then use this
You are using wrong code.
[self.navigationController popViewControllerAnimated:YES];
There is problem in hiding the popover view. Check if presented correctly.
if (popover == nil) {
popover = [[UIPopoverController alloc] initWithContentViewController: MYVC];
popover.delegate = self;
[self.tablesPopoverController presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
Use delegate methods to check if popover is visible or not.
- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController {
// do something now that it's been dismissed
}
Related
I've recently been updating an application to replace instances of the deprecated UIPopoverController with UIViewControllers presented modally, and when I create one, it takes about 250% as long to appear. Also, setting animated:NO in the presentViewController method also seems to have no effect.
Does anyone know why this might be?
Here's some of the relevant code I've written (it's in an IBAction from a UIButton being pressed):
UIViewController *popover = [[MyViewControllerForPopover alloc] initWithNibName:nibName bundle:nil];
popover.modalPresentationStyle = UIModalPresentationPopover;
popover.preferredContentSize = popover.view.frame.size;
popover.popoverPresentationController.sourceView = parentView;
popover.popoverPresentationController.sourceRect = location;
popover.popoverPresentationController.permittedArrowDirections = arrows;
[parentViewController presentViewController:popover animated:NO completion:nil];
I tried setting modalTransitionStyle, but it didn't seem to have any effect on the style or duration of animation. What I see is a delay, followed by the animation, so it looks like there's an extended amount of time spent setting up the view controller.
This is the same view controller that used to be put inside the UIPopover, via the initWithContentViewController init method, so I can't understand why this is slower.
Thanks
This is probably simple. My UISwitch from my xib is connected to an IBOutlet "switch".
however when i create the viewController, i want to check if a variable is YES/NO, and the switch should be the correct value.
ViewController *vc = [[ViewController alloc] init];
if(variable ==YES){
[vc.switch setOn:YES];
}else{
[vc.switch setOn:NO];
}
however its always unchecked. What could i be doing wrong? i´ve double checked the connection to the IBOutlet
You aren't calling the correct method; UISwitch doesnt' have a setOn method. it has an on property and a senOn:animated: method.
either:
ViewController *vc = [[ViewController alloc] init];
vc.switch.on = variable
or:
ViewController *vc = [[ViewController alloc] init];
[vc.switch setOn:variable animated:YES];
Note, you are already checking against a BOOL, I've shown how to do it without the needless check.
This is the most common problem new developers have. Actually i had the same problem once. at that time i don't know the reason of happening this. i think now i am clear about such problems.
Let me give you some tips.
You should never access any UIView controls before presenting or pushing viewcontroller. you can access the UIView controls after presenting/pushing.
You can achieve this by setting the boolean value also. Create deafultSwitchStatus boolean property because its a boolean type this value will remain memory before viewDidLoad. and you can assign this status to your UISwitch object in viewDidLoad.
In short. UIView controls are not created/loaded before viewDidLoad method and viewDidLoad is called after preseting/pushing any controller. it means your controls are nil if you are accessing before presenting/pushing. those controls will not have any effect of your code because it will be overwritten.
Hope i explained right :)
You have created ViewController, but not presented it. So loadView was never called and yours .switch is nil.
try this:
ViewController *vc = [[[ViewController alloc] init] autorelease];
[self presentViewController:vc
animated:YES
completion:^(){
vc.switch.on = variable;
}];
I have an app that is loading a overlay controller (shows camera so I can scan). It works great on the iPhone and it works great on the iPad after I call it a second time. Let me explain.
I have a UIButtonBarItem that loads a view controller modally. There are several controls on in the controller, most buttons (defined using a nib). If I load the controller (by responding to the UIButtonBarItem action) on an iPhone, it loads and all the buttons work fine, every time.
But... if I load the same view controller using an UIPopoverController, none of the buttons will respond the first time I load it. So, I touch the screen somewhere outside of the controller and dismiss the controller. Then, I touch the same action button again and now when the controller loads, all the controls in the the view controller work great. REALLY WEIRD!
[POSSIBLE HINT]
The buttons were placed all over the place in weird positions when I loaded it the first time. Each subsequent call had the buttons showing in the right places. I got this to work by disabling "Autoresize subviews" in the nib. The buttons are now in the right places but they still won't respond when I load this popover the first time.
Here's the code I'm using to respond to the UIButtonBarItem.
-(void)launchOverlayController:(id)sender
{
if([pickerControllerPopover isPopoverVisible])
{
[pickerControllerPopover dismissPopoverAnimated:YES];
pickerControllerPopover = nil;
return;
}
// Deselect any selected cell
[self.tableView deselectRowAtIndexPath:self.tableView.indexPathForSelectedRow animated:NO];
// Working code that shows the overlay (camera on) but the overlay takes the whole screen
SRSScanVINViewController *scanVINViewController = [[SRSScanVINViewController alloc] init];
[pickerController setOverlay:scanVINViewController];
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:scanVINViewController];
[navController setModalPresentationStyle:UIModalPresentationFormSheet];
[navController setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[[UIApplication sharedApplication] setStatusBarHidden:YES];
if([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad)
{
pickerControllerPopover = [[UIPopoverController alloc] initWithContentViewController:pickerController];
[pickerControllerPopover setDelegate:self];
[pickerControllerPopover setPopoverContentSize:CGSizeMake(320.0f, 460.0f)];
[pickerControllerPopover presentPopoverFromBarButtonItem:sender permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
else
{
[self presentViewController:pickerController animated:YES completion:nil];
}
}
I'm totally out of ideas. I can't see why the controls within the overlaycontroller would work fine every time I call it except for the first time.
Thanks for anyones help in advance.
So the answer is that the superclass is mucking with your view. I'm going to guess it was not designed to be subclassed, but no way to know for sure. What it does in one of the 'view..' methods is to override self.view with its own view, and make your view a subview of that view. The first time around it makes the frame of your view have zero dimensions. The next time it leaves it as it was before - maybe some persistent flag. It also inserts the view at different places in its subviews, which seems odd but if you have the code you'd probably see why.
Soooo - the solution to the problem is to just move your view's subviews to the superView (the subclass's view), then set your view's frame to the null frame:
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated]; // StackOverflow says to add this TCL?
// Set the initial scan orientation
[self setLayoutOrientation:self.parentPicker.orientation];
if ([self.parentPicker hasFlash])
{
[flashButton setEnabled:YES];
[flashButton setStyle:UIBarButtonItemStyleBordered];
[self.parentPicker turnFlash:NO];
} else
{
[flashButton setEnabled:NO];
}
textCue.text = #"";
viewHasAppeared = NO;
// move the subviews
while([self.view.subviews count]) [self.view.superview addSubview:[self.view.subviews objectAtIndex:0]];
self.view.frame = CGRectMake(0,0,0,0);
}
PS: note that you were missing a superView call here but it didn't seem to matter much (you don't know which method your complex superclass may want so I'd be sure to send them everything you intercept.
I'm attempting to embed an editable UITextView inside a UIPopoverController, with... strange results. The steps I've taken are:
Create a custom UIViewController class, and create a .xib file with that controller with a UITextView inside it.
When the UI action that should bring up the controller occurs (touch up inside), I instantiate the controller and its view from the .xib file.
I create a new UIPopoverController, with the view controller I just instantiated as the content view.
I present it with presentPopoverFromRect:inView:permittedArrowDirections:animated:
Here's some example code:
- (void)noteButtonPressed:(id)sender {
self.noteview = [[MyTextPopupViewController alloc] initWithNibName:#"MyTextPopupViewController" bundle:nil ];
UIPopoverController *popoverController = [[UIPopoverController alloc] initWithContentViewController:self.noteview];
self.popover = popoverController;
self.popover.delegate = self;
[self.popover presentPopoverFromRect:((UIView*)sender).frame
inView:self.view
permittedArrowDirections:UIPopoverArrowDirectionAny
animated:YES];
}
Then, inside MyTextPopupViewController, I make sure the the text view is the first responder to bring up the keyboard:
- (void)viewDidAppear:(BOOL)animated {
[self.view becomeFirstResponder];
[super viewDidAppear:animated];
}
And that all works... right until it doesn't. Sometimes, it works perfectly; other times, either immediately or after a few keystrokes, the application crashes by exiting the main event loop (!). No exception is thrown (at least not that the lldb catches), but the application simply stops, both on the simulator and on hardware.
Any thoughts? Has anyone gotten this working successfully, or knows for sure that it does not?
I think the UIPopoverController instance needs to be a property in your code.
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.