UIBarButtonItem makes my iPhone app crash - ios

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

Related

UISwitch not reaction

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;
}];

Adding/removing tabs to UITabBarController programatically gives console warning

In my application, I have a custom UITabBarController that is set as the rootViewController. During the life span of the application, I programmatically add/remove additional tabs based on user interaction, and when doing so I see the following message various times in the console:
Two-stage rotation animation is deprecated. This application should use the smoother single-stage animation.
Any ideas how to prevent this from happening?
EDIT
Here's a simplified example of how I'm adding the additional tabs (example just has 1, but there's actually 4 being added).
UIViewController *viewController = [[MyCustomViewController alloc] init];
viewController.tabBarItem.image = [UIImage imageNamed:#"icon"];
viewController.tabBarItem.title = #"Title";
UINavigationController *navViewController = [[UINavigationController alloc] initWithRootViewController:viewController];
[self setViewControllers:#[ navViewController ] animated:NO];
Is your MyCustomViewController implementing one of the deprecated two-phase rotation methods?
– willAnimateFirstHalfOfRotationToInterfaceOrientation:
- didAnimateFirstHalfOfRotationToInterfaceOrientation:
- willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:
As the error message says, these have been deprecated (since iOS 5.0). Have a look at their documentation to see what the replacement mechanism is (basically, use
willAnimateRotationToInterfaceOrientation:duration: instead).

UINavigationController: app freezes

In myAppDelegate.m:
MainViewController *mainViewController = [ [MainViewController alloc] init];
UINavigationController *navController = [[UINavigationController alloc]
initWithRootViewController:mainViewController];
[navController setNavigationBarHidden:YES];
[[self window] setRootViewController:navController];
In MainViewController.m nothing special, just one action tied to a button:
- (IBAction)go:(id)sender {
if (!whereamiViewController)
{
whereamiViewController = [[WhereamiViewController alloc] init];
}
[[self navigationController] pushViewController:whereamiViewController animated:YES];
}
And in WhereamiViewController.m just a button to show another screen in UINavigationViewController:
-(IBAction)showList:(id)sender
{
PointsViewController *container = [[PointsViewController alloc] init];
[[self navigationController] pushViewController:container animated:YES];
}
And:
#interface PointsViewController : UITableViewController
#end
Everything fine. But when I land on the last screen, PointsViewController, and I go back on WhereamiView, the app freeze, and Xcode shows a trap at CoureFoundation, CFHas.
Now, I know that Objective-C is not php, but this is a simple example indeed: what am I missing? There is a method to debug the problem?
The debugger says:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '- [__NSCFType _forgetDependentConstraint:]: unrecognized selector sent to instance
This morning I ran the app inside the simulator and no crashes!! How is it possible? If I run inside the iPhone crash, in the simulator no crash.
Tim is right. Popping the PointsViewController is the way I would do it, too.
What does your Xcode saying? Can you provide the content of the debugger?
That would be more helpful to track down what's going wrong.
[PARTIALLY SOLVED]
This is very strange: After debugging everything and deleting every suspicious declaration, nothing improved. Same crash SIGABRT. After rebooting both iPhone and Mac, everything is fine!
I am not really seeing where the problem is as it occurs outside of the code you have posted. I may be missing something, but if the app crashes when you go back to whereamiViewController, how do you actually go back? I am not seeing where it's detailed here.
With navigationControllers like this, you would push (to add) or pop (to remove) viewControllers to move up and down the navcontroller tree. As it is at this point that the app seems to be crashing, it may be worth postings how you are dong this? Where are you popping the container (PointsViewController *).
From the code you've posted, I suspect you may be trying to move back to the whereamiViewController by re-pushing it again.

UIAlertView cancel button crashes app

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?

reached while popover is still visible

-(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.

Resources