unable to detect crash in EKEventEditViewController - iphone

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 !

Related

Unbalanced calls to begin/end appearance transitions for (I believe this is UINavigationController 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.

ABPeoplePickerNavigationController crashes while being dismissed in Simulator only

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.

EXEC_BAD_ACCESS on a UIActionSheet with ARC

Just converted a project to ARC and am now getting a EXEC_BAD_ACCESS after I dismiss a UIActionsheet, it was previously working and I am unsure if this is even ARC related. Zombies is enabled but showing me nothing and I tried instuments and it also gave me nothing.
This is presented in a modal view controller, case 0, the quit button works fine but the other two give me the bad access error.
This is my first conversion to ARC, am I missing something here?
Action sheet Creation:
-(IBAction)quitPressed:(id)sender {
UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:#"Quit This Game?" delegate:self cancelButtonTitle:#"Keep Playing" destructiveButtonTitle:#"Quit" otherButtonTitles:#"Quit and Reveal Answers",nil];
[sheet showInView:self.view];
}
Action sheet delegate:
-(void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex{
switch (buttonIndex) {
case 0: //quit
[self dismissViewControllerAnimated:NO completion:^{
[self.delegate quitGame];
}];
break;
case 1: //quit and reveal
NSLog(#"reveal");
break;
case 2: //cancel
NSLog(#"cancel");
break;
default:
break;
}
}
If your delegate is declared strong in the .h file. Have you initialized the self.delegate at least once in the .m file(preferably viewDidLoad) using
self.delegate = [[UIApplication sharedApplication] delegate];
Delegates should be weak or assign (__weak / __unsafe_unretained for ivars) to avoid any retain cycles.
Hold a reference to the sheet that you create. You can clear that reference once the sheet was closed.
Thanks everyone for the help. I found the problem when I ran the project under xcode 4.5. It gave a compile error: switch case is protected in scope
I wasn't getting that error in xcode 4.3
It was solved in this thread When converting a project to use ARC what does "switch case is in protected scope" mean?
I wrapped each case in curly brackets and the problem has been fixed.

EXC_BAD_ACCESS and Zombies, Yet not really sure why it keeps coming up

I don't know what's going wrong here. The crash happens when switching back and forth between views.
Here's what instruments gives me:
Clicking into it references this code with the first action :
-(IBAction)pushnews; {
NewsViewController *news = [[[NewsViewController alloc]init]autorelease];
news.title =#"Page";
[self.navigationController pushViewController:news animated:YES]; }
I use autorelease sometimes but usually I just release it my self. Should I get rid of autorelease and add [news retain]
What am I doing wrong?
Edit based on answers:
Following EmptyStack's Advice: ViewWillDisappear Code looks like this:
- (void)viewWillDisappear:(BOOL)animated {
webView.delegate = nil; }
This seems to resolve issues (pending more testing)
In viewdidload I said: webView.delegate = self;, which may have been the issue!
My guess is that, there is a UIWebView in NewsViewController, and it is causing the crash. It is possible that, a delegate method of web view is called after the web view is released. If so, try to setwebView.delegate = nil; in NewsViewController's viewWillDisappear: method.
try this instead :
-(IBAction)viewcontroller;
{
NewsViewController *news = [[NewsViewController alloc]init];
news.title =#"Page";
[self.navigationController pushViewController:news animated:YES];
[news release];
}

Action sheet doesn't display when the MFMailComposeViewController's cancel button is tapped

I'm trying to incorporate MFMailComposeViewController in my app. When I present it modally, the send button works fine and the email is sent, which implies that the result sent to the delegate is right in that case.
Whereas when I tap the cancel button it hangs up the app. The log shows no errors either, just the screen goes dark and everything gets disabled. Apparently, the result is not being passed to the delegate (I checked it through logs). it appears that the
(void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
is never called whenever the cancel button is pressed. Probably that's the reason why the actionsheet (Save draft, cancel, delete draft) is not displayed and therefore the app hangs in right there.
I'm using the exact code from Apple's sample apps (MailComposer), it works perfectly there, but somehow fails in mine. :(
Kindly help me if anyone has ever come across the same issue, and successfully resolved it.
My code:
-(IBAction)emailButtonPressed:(id)sender{
Class mailClass = (NSClassFromString(#"MFMailComposeViewController"));
if (mailClass != nil)
{
if ([mailClass canSendMail])
{
[self displayComposerSheet];
}
else
{
[self launchMailAppOnDevice];
}
}
else
{
[self launchMailAppOnDevice];
}
}
#pragma mark -
#pragma mark Compose Mail
-(void)displayComposerSheet
{
MFMailComposeViewController *picker = [[MFMailComposeViewController alloc] init];
picker.mailComposeDelegate = self;
[picker setSubject:#"Ilusiones"];
// Set up recipients
NSArray *toRecipients = [NSArray arrayWithObject:#"anam#semanticnotion.com"];
[picker setToRecipients:toRecipients];
// Attach a screenshot to the email
UIGraphicsBeginImageContext(self.view.bounds.size);
[self.view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *viewImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSData *myData = UIImagePNGRepresentation(viewImage);
[picker addAttachmentData:myData mimeType:#"image/png" fileName:#"viewImage"];
// Fill out the email body text
NSString *emailBody = #"";
[picker setMessageBody:emailBody isHTML:NO];
[self presentModalViewController:picker animated:YES];
[picker release];
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
switch (result)
{
case MFMailComposeResultCancelled:
NSLog(#"Result: canceled");
break;
case MFMailComposeResultSaved:
NSLog(#"Result: saved");
break;
case MFMailComposeResultSent:
NSLog( #"Result: sent");
break;
case MFMailComposeResultFailed:
NSLog( #"Result: failed");
break;
default:
NSLog(#"Result: not sent");
break;
}
[self dismissModalViewControllerAnimated:YES];
}
#pragma mark -
#pragma mark Workaround
-(void)launchMailAppOnDevice
{
NSString *recipients = #"mailto:anam#semanticnotion.com.com?cc=second#example.com,third#example.com&subject=illusions!";
NSString *body = #"&body=xyz";
NSString *email = [NSString stringWithFormat:#"%#%#", recipients, body];
email = [email stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:email]];
}
Method
(void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error
is never called because you don't press any UIActionSheet button after cancelling, as it doesn't show on screen.
The reason this is happening is that the UIActionSheet appears off-screen. If you check the debug log you'll probably see a message saying Presenting action sheet clipped by its superview. Some controls might not respond to touches. On iPhone try -[UIActionSheet showFromTabBar:] or -[UIActionSheet showFromToolbar:] instead of -[UIActionSheet showInView:]."
That's why you see your view getting darker, but no UIActionSheet appears.
In my case, the problem was that my app is universal, but for some reason there was only one MainWindow.xib, and it was larger than the iPhone screen size (it was, in fact, the iPad screen size).
The solution is to create another MainWindow-iPhone.xib with the right dimensions and change the Info.plist entries called Main nib file base (iPad) and Main nib file base (iPhone) so that they point to the right file. Problem solved!
Hope it helps.
I had the same problem,commented out '[picker release];', and it worked fine! Explanation? I have none.
Msoler has it right, teh action sheet is displayed off-screen.
The MFMailComposeViewController display the action-sheet at x:y 0:0, so you have to make sure teh calling controller frame is at 0:0. I had a similar issue when I tried to display the MFMailComposeViewController from a view that was embedded in a scroll view.
I have implemented the same code . It works absolutely fine. When you click on the delete draft button,didFinishWithResult method is called and the mail is cancelled.
Be sure that you use the correct method,
-(void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
I had a some what similar method implemented which was never called. I have no idea what I exactly had but the compiler did not give me a warning or error message.
Just in case anybody else makes the same mistake as I did... I implemented the mailComposeController:didFinishWithResult:error: method in my Swift code. It worked for a while but after several refactorings I noticed that it was suddenly not being called anymore. Eventually I noticed that the method had taken this form in my code:
private func mailComposeController(controller: MFMailComposeViewController!, didFinishWithResult result: MFMailComposeResult, error: NSError!) {
presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
}
So, as you can see I was a little bit too eager about privatizing my methods: Since the method is marked #optional in the MFMailComposeViewControllerDelegate you do not have to implement it. And while I actually had implemented it, the private modifier from there on hid the implementation - thus, from outside the file it seemed that the method was actually not implemented, at all! However, since the method was optional, the compiler did not complain...
To conclude: Do not mark optional delegate with the modifier private.
I have been wondering ever since learning Swift why there are no optional methods anymore - now I might have understood ;-).