-(void)showsearch:(id)sender
{
SearchViewController *searchview =[[SearchViewController alloc] initWithNibName:#"SearchViewController" bundle:nil];
settingpopoverController = [[[UIPopoverController alloc]
initWithContentViewController:searchview] autorelease];
[searchview release];
[settingpopoverController presentPopoverFromBarButtonItem:sender
permittedArrowDirections:UIPopoverArrowDirectionAny animated:YES];
}
When I click on button, the app is crash and I got [UIPopoverController dealloc] reached while popover is still visible. message.
There are some good discussions on this topic here:
Retain/release pattern for UIPopoverController, UIActionSheet, and modal view controllers?
UIPopoverController and memory management
The gist of it is you need to:
assign your autoreleased popover to a retain property
set the property to nil in your view's dealloc
as well as setting it to nil in the popoverControllerDidDismissPopover.
think autorelease is incorrect, here is a tutorial
http://www.jannisnikoy.nl/index.php/2010/04/ipad-tutorial-creating-a-popoverviewcontroller
Problem is you're setting
settingpopoverController =
when you mean to do
self.settingpopoverController =
for which the autorelease would be correct. The second one uses the property accessors, the first just uses the iVar.
Related
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
}
I am little confuse because my dealloc is not called in ARC. I have using storyboard in my application.
Case 1: Mydealloc called when i use all IBOutlet from storyboard
Case 2: My dealloc is not called when i try to use alloc and init methods in UIViewController. such as below.
UIViewController *vc = [[UIViewController alloc] initWithNibName:#"ProfileDetailView" bundle:nil];
__weak ProfileDetailView *detailview = (ProfileDetailView *)vc.view;
detailview.backgroundColor = [UIColor clearColor];
vc = nil;
....Set value in object.....
[self.view addSubview:detailview];;
detailview = nil;
Can you explain why dealloc is not called? and How can i able to achieve to call dealloc?
Thanks
The concept of ARC is that an object's retain count should theoretically be 1 in order for it to be deallocated. When you execute:
[self.view addSubview:detailview];;
Your self.view increments detailview's retain count by 1 when it adds it to view.subviews. Logically, when self.view removes detailview, the retain count is decremented by 1.
Again, this is a theoretical perspective. The reality is usually:
INSANE.
No one really knows how the mysterious Objective-C runtime works! (just kidding the whole source code is available online.)
Thanks for your reply. I am able to called my dealloc function when view controller pop. For achieving that, we need to remove my added subviews from my view when user tapped on back button.
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;
}];
Okay, so I have just started iOS development. I'll start by explaining the flow of my app :
1. A view called "appViewController" is loaded.
2. [self presentViewController: controller animated: YES completion:nil]; this loads a webview
3. After I am done with the webview, I dismiss it and load a new UINavigation this way :
[self dismissViewControllerAnimated:YES completion:^{
formViewController *fv = [ [formViewController alloc] init ];
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:fv] autorelease];
navController.navigationBar.hidden = YES;
[presentingViewController presentModalViewController:navController animated:YES];
}];
5.The formViewController has a button, which has the event attached to it for that display an alert this way
UIAlertView *av = [[UIAlertView alloc] initWithTitle:#"Oops!"
message:#"test"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[av show];
Everything works as intended up till here. Now when I click the "Ok"(Cancel) button, the app crashes with NSZombieEnabled saying
-[appViewController _deepestDefaultFirstResponder]: message sent to deallocated instance 0x6e6a570 lldb
What is happening here? Why is it trying to send message to appViewController again? There is no code after [av show]
NOTE : I am using ARC
If you're using arc, the autorelease in your code isn't valid.
This seems like your root view controller gets deallocated at some point and when the responder chain gets traversed the resulting dangling pointer gets accessed.
To verify this, I would implement the dealloc method on appViewController and see if it gets called.
dealloc {
NSLog(#"Problems ahead.");
}
If this does get called before you'd expect that to happen (for a root view controller probably not at all), you need to find out why this happens. You're probably missing a strong reference somewhere. Check you app delegate and verify that you have a strong reference to the window and that you are setting your controller as the root view controller (provided you're not using storyboards).
The Zombies instrument is very good for debugging such problems. It will list all retains and releases of your problematic object. Here's a short introduction to it.
A couple of things.
You are mixing presentViewController and presentModalViewController. If you are new to iOS, you should always use presentViewController. No need getting used to using a method that will soon be deprecated (see answer to this question Difference between presentModalViewController and presentViewController?
In general, you shouldn't autorelease unless you absolutely have to. Since when a controller is presented with presentViewController (and presentModalViewController), it is retained, you can readily release afterwards. I would restructure like so:
UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:fv];
navController.navigationBar.hidden = YES;
[presentingViewController presentModalViewController:navController animated:YES];
[navController release];
3.. Where is the section of code you included located? Like, you push a button and the view is dismissed or what?
I'm working on a project and I'm trying to do the most I can programmatically.
I've to add an UIBarButtonItem to a NavigationController's nav bar created in the App Delegate.
WPViewController *mainVC = [[WPViewController alloc] initWithNibName:#"WPViewController_iPhone" bundle:nil];
UINavigationController *navCon = [[UINavigationController alloc] init];
[navCon pushViewController:mainVC animated:NO];
[self.window addSubview:navCon.view];
Then in the implementation file of the here declared WPViewController I create and add the barbuttonitem as a navigation item of the VC:
UIBarButtonItem *rBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:#selector(test)];
self.navigationItem.rightBarButtonItem = rBarButtonItem;
There is a method called test declared before of this that simply log "test", but when I click on the button the app crashes.
Please help me, this bug is driving me crazy.
Notes:
I'm using ARC in my project
Never had a similar bug before
" Message sent to deallocated instance" in ARC means the compiler has marked, and released, your item before your message could be sent.
Set NSZombieEnabled, MallocStackLogging, and guard malloc in the debugger. Then, when your App crashes, type this in the console:
(gdb) info malloc-history //address of crashing object i.e. 0x543216//
I also had this problem when using addSubview but creating a property with (nonatomic, strong) strong solved it for me.
The Button tries to pass itself as an argument to the test method. I guess your signature of that method doesn't include an argument, because there's no colon in your selector (it should be #selector(test:)). And the method implementation should look like:
- (void) test:(id)sender