I get this crash in the simulator only. On a real device it works and debugs fine.
(Therefore it is not too critical but I am working on a presentation for which the simulator comes handy.)
- (BOOL)peoplePickerNavigationController:
(ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person {
[self displayPerson:person];
if ([self respondsToSelector:#selector(dismissViewControllerAnimated:completion:)]){
[self dismissViewControllerAnimated:YES completion:nil];
} else {
[self dismissModalViewControllerAnimated:YES];
}
return NO;
}
The crash is on:
[self dismissViewControllerAnimated:YES completion:nil];
All I see is: "Thread 1: EXC_BREAKPOINT (code=EXC_I386_BTP, subcode=0x0)"
There is no specific output in the debug window. Zoombies is enabled. I do ARC. I am using storyboard but I call the ABPersonPicker... programmatically using the following code:
-(void)showPeoplePickerController
{
ABPeoplePickerNavigationController *picker = [[ABPeoplePickerNavigationController alloc] init];
picker.peoplePickerDelegate = self;
if ([self respondsToSelector:#selector(presentViewController:animated:completion:)]) {
[self presentViewController:picker animated:YES completion:nil];
} else {
[self presentModalViewController:picker animated:YES];
}
return;
}
Remember that it is running well on the devices that I have (iPod Touch 4th gen, iPhone 4 and iPhone 4S)
Your problem is that you don't keep a strong reference to the picker. Add a ivar to hold it, then when done in the delegate callback, use a dispatch asyn block on the main queue to nil the ivar out and release it. (Sorry no code entering this from an iPad)
EDIT: look in your showPeoplePickerController method - you create the picker and save it in an automatic which gets released when you exit the method. You want to keep a strong reference to the picker by using an ivar instead of the automatic.
Then you don't want to release the picker in a delegate callback - this often works but will bite you at unexpected times, so you want to release this type of object after the delegate callback is done. In fact I usually set the objects delegate property to nil first if I can then release it with 'picker = nil' . In a block 'picker' gets turned into 'self->picker'. You can also use performSelector:afterDelay:0 too I just prefer blocks.
EDIT2: So what I do in
- (BOOL)peoplePickerNavigationController:shouldContinueAfterSelectingPerson:
is just return NO. I wait until this message:
- (void)peoplePickerNavigationControllerDidCancel:
to dismis it. I also have some other code that pops a an action sheet that confirms saving a selected address and also does a dismiss, but its old code and not sure how it works now. In any case hope this helps.
Related
It looks like this topic comes up a lot. I read through several answers but none were the same case as mine so please excuse me if you've seen similar before.
All of my UIViewControllers are being controlled by UINavgationController. On the first UIViewController (SMOnboardingPhotoMarketingViewController), I call into my keychain wrapper class to see if there is anyone logged in (app resuming). If so I call the segue to go to my main logged in screen (SMThumbnailViewController), where I'm getting the error message: Unbalanced calls to begin/end appearance transitions for .
I have examined all of the view controller life-cycle calls to ensure that I'm calling [super method] if I over-rode them. Done.
Other than that this is just a standard push type segue for all transitions. I don't understand what is so different about this call to a segue than all the others that are triggered by button actions. Here is the code from my first view controller:
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[self loadScrollViewContent];
__weak SMOnboardingPhotoMarketingViewController *weakSelf = self;
[SMAuthentication validateStoredTokenWithCompletion:^(BOOL valid) {
if(valid){
NSLog(#"Logged in. Continue to thumbs page");
[weakSelf performSegueWithIdentifier:kSeguePhotoMarketingToThumbnails sender:self];
}
else{
[SMAuthentication logOut];
NSLog(#"invalid credentials stored. User must log in ");
}
}];
}
I've noticed that in my main view controller (the one that the above code navigates to), viewDidLoad is called, but viewDidAppear is never called. What could cause such an imbalance?
Edit: Adding info. I should state taht if I move the segue call to the outside of that block, the transition goes as normal with no error. Example:
// I know this is ugly. It is for testing only
-(void)viewDidAppear:(BOOL)animated{
[super viewDidAppear:animated];
[self loadScrollViewContent];
__block BOOL complete = NO;
__block BOOL isValid = NO;
[SMAuthentication validateStoredTokenWithCompletion:^(BOOL valid) {
if(valid){
NSLog(#"Logged in. Continue to thumbs page");
isValid = YES;
}
else{
[SMAuthentication logOut];
NSLog(#"invalid tokens stored. User must log in ");
}
complete = YES;
}];
while (!complete) {
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
if(isValid){
[self performSegueWithIdentifier:kSeguePhotoMarketingToThumbnails sender:self];
}
}
You probably have implemented the following ViewController custom container methods:
- (void)endAppearanceTransition
- (void)beginAppearanceTransition:(BOOL)isAppearing animated:(BOOL)animated
I once written and forgot them in a base class and they messed up the whole appearance forwarding to child controllers when using storyboards.
when i click on done button at EKEventEditViewController then app gets crashed saying "exc_bad_access".I also used break point to detect it but cannot find it. There is nothing about crash in gdb. Where should i check crash. Done-button do not shift control to EKEventEditViewDelegate - method. It just crash.Help me out plz.
here is my code
-(void)viewWillAppear:(BOOL)animated
{
EKEventEditViewController *addController = [[EKEventEditViewController alloc]
initWithNibName:nil bundle:nil];
addController.eventStore = self.eventStore;
addController.event = event;
addController.editViewDelegate = self;
[self presentModalViewController:addController animated:YES];
[super viewWillAppear:YES];
}
#pragma mark -
#pragma mark EKEventEditViewDelegate
- (void)eventEditViewController:(EKEventEditViewController *)controller
didCompleteWithAction:(EKEventEditViewAction)action {
NSError *error = nil;
EKEvent *thisEvent = controller.event;
switch (action) {
case EKEventEditViewActionCanceled:
break;
case EKEventEditViewActionSaved:
[controller.eventStore saveEvent:controller.event
span:EKSpanThisEvent error:&error];
break;
case EKEventEditViewActionDeleted:
[controller.eventStore removeEvent:thisEvent span:EKSpanThisEvent
error:&error];
break;
default:
break;
}
[controller dismissModalViewControllerAnimated:YES];
[self backTopreviousController];
}
-(void)backTopreviousController
{
[self.navigationController popToRootViewControllerAnimated:YES];
}
exc_bad_access suggests that you're accessing memory that has been deallocated (probably a mememory management problem). These issues are a bit hard to tackle because you might release an object (which you should not) at some point and you only run into a problem a little later when accessing this object.
You can try the following:
Click the "Run Button Dropdown"
From the list choose Profile
The program "Instruments" should open where you can also choose Zombies
Now you can interact with your app and try to cause the error
As soon as the error happens you should get a hint on when your object was released and therefore deallocated.
(source: dimzzy.com)
Debug the program after setting a breakpoint at the beginning of eventEditViewController:didCompleteWithAction. Once your program reaches the breakpoint execute step by step.
Doing like this, you will know either:
which statement makes the program crash, or
that the program crashes before even entering that method.
In case 1, you should inspect each object you send a message to and make sure it has not been deallocated. In case 2, you should inspect the action definition that is associated to the Done button.
Your code is crashing because of the following lines.
[controller dismissModalViewControllerAnimated:YES];
[self backTopreviousController];
either you want to pop or dismiss. But not both.
It depends how you have called this class. Push or presentModal !
Im having a strange problem that only occurs on the iPad version of my game. When I bring up the GameCenter leaderboard, it appears like normal. No issues there. But when you tap the close button the leader board disappears and the cocos2d scene goes black. No errors, nothing. Nothing I do can bring the screen back. Ive tried resuming the director and even tried some solutions on a similar thread.
Here is my code in the cocos2d scene. GCController is just a subclass of the RootViewController, nothing special:
tempVC = [[GCController alloc] init];
GKLeaderboardViewController *leaderboardController = [[[GKLeaderboardViewController alloc] init] autorelease];
if (leaderboardController != nil)
{
leaderboardController.timeScope = GKLeaderboardTimeScopeAllTime;
leaderboardController.category = [NSString stringWithFormat:#"%#%#", [self cleanString:selectedSong], #"TotalHD"];
leaderboardController.leaderboardDelegate = self;
[[[CCDirector sharedDirector] openGLView] addSubview:tempVC.view];
[tempVC presentModalViewController:leaderboardController animated:YES];
}
- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
[tempVC dismissModalViewControllerAnimated:YES];
[tempVC.view.superview removeFromSuperview];
[tempVC release];
}
Anyone have any ideas? If I can provide any more information let me know. Thanks.
You are not providing enough code. I see no fault in the code you are showing at the moment. Your most likely cause of a black screen (depending on how you do things) is that timers have been interrupted and you may need to reset them with
- (void) onEnter;
or
- (void) onEnterTransitionDidFinish;
If that isn't it then post more code and I will check back. We need to see when the view is presented and what it should return to.
- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController
{
[tempVC dismissModalViewControllerAnimated:YES];
**[tempVC.view removeFromSuperview];**
}
I am facing a bit strange problem with implementation of UIAccelerometer.
I have a UITableViewController where I don't wanna use UIAccelerometer, but after pressing on of the rows I wanna activated one inside a UIViewController, everything is fine when I use simulator, but when I use device iPhone 3G to test it, I got EXC_BAD_ACCESS by pressing return button.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
ShakeControl *percView = [[ShakeControl alloc] init];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:percView animated:YES];
[percView release];
}
It works fine when I disable [percView release];, but it does not sounds like solution for.
Any Idea would be appreciated.
Shake control implementation:
- (void)viewDidLoad {
[super viewDidLoad];
[[UIAccelerometer sharedAccelerometer] setUpdateInterval:1.0 / kUpdateFrequency];
[[UIAccelerometer sharedAccelerometer] setDelegate:self];
}
- (void)viewDidUnload {
[super viewDidUnload];
[[UIAccelerometer sharedAccelerometer] setDelegate:nil];
}
Thx
The viewDidUnload method will get called only in specific case, such as memory warning. You have to remove the delegate in dealloc too.
Try releasing it after you dismiss it, I'm not sure if pushViewController retains.
You could setting the environment variables NSZombiesEnabled & NSAutoreleaseFreedObjectCheckEnabled with a value of 1.
This will prevent objects from really being deallocated, then you should get console logs indicating where the over-release is coming from.
You could use Run With Performance Tools -> Allocations once you know which object is being over-released and see every location where a retain/release was called to spot the imbalance.
I've been searching around but unfortunately have had no luck.
My app requires the user to sign in/sign up the first time he or she launches the app. I know how to determine first launch (using NSUserDefaults) but whenever I try to present the modal containing the sign in/ sign up controls, nothing happens.
Here's what I have:
-(void)viewDidLoad {
[self showLogin];
[super viewDidLoad];
}
-(void)showLogin {
FlipsideViewController *controller = [[FlipsideViewController alloc] initWithNibName:#"AccountView" bundle:nil];
controller.delegate = self;
controller.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:controller animated:YES];
[controller release];
}
However, nothing happens. The main view just loads as normal. Any help is greatly appreciated.
-Giles
[UPDATE]
Fixed simply by using..
-(void)viewDidAppear:(BOOL)animated
{
}
instead of
-(void)viewDidLoad
{
}
Thanks anyway!
/idiocy
I had the same issue and ended up using viewDidAppear as well. The only problem with the viewDidAppear approach is that if you load other UIViewControllers on top, then reshow the base, then your setup code gets called over and over. I ended up having to add a boolean value (initialised to YES) to this view controller and check that value before deciding what to do. Hope this helps someone...
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:(BOOL)animated];
if(justLaunched)
{
justLaunched = NO;
if(settingsFileExists)
{
[self displayMainView];
}
else
{
[self displaySetupView];
}
}
}
How about using performSelector:withObject:afterDelay in the viewDidLoad function? That's how I do it, with a short delay of 0.1s.
And invoking this in the viewDidLoad isn't very safe : the sequence viewDidLoad / viewDidUnload can occur at runtime when the iPhone needs to release some views in order to get back some free memory.
The side effect of such sequence would be that your login controller would be shown...
As you said the viewDidAppear looks better but not simply put it at the end of the appDidFinishedLaunching the delegate of your UIApplication?