MFMailComposer Exec_bad_access - might it have something to do with initialization - iphone

In a view controller i have a button which internally calls an IBAction and that internally calls the
[self showEmailModalView:FinalEmail];
now ... in the showEmailModalView i have
-(void) showEmailModalView:(NSString *)email{
MFMailComposeViewController *mvc =[[[MFMailComposeViewController alloc] init]autorelease];
mvc.mailComposeDelegate = self;
NSArray *mails = [[NSArray arrayWithObject:email]autorelease];
[mvc setToRecipients:mails];
NSString*emailBody =[NSString stringWithFormat:#" "];
[mvc setMessageBody:emailBody isHTML:YES];
mvc.navigationBar.barStyle = UIBarStyleBlack;
[[self navigationController] presentModalViewController:mvc animated:YES];
}
and then
-(void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
[[self navigationController] dismissModalViewControllerAnimated:YES];
}
Now it works alright... for all the scenarios of email or delete or anything like that but right after completion of the code the simulator just throws a exec_bad_access and then does nothing.... can you help.
PS: i also found out that that when ever you are giving a release to the mvc as declared above the error is called. ant thoughts.
Update:
I did install the app with only one change... i initialized the mvc in the header file and then just use the same statement. so now i am not getting the exec_bad_access errors anymore... i think it was frightened of the nsZOMBIES....Haha... thanks for your Help and support.. guys... Both of you....

You shouldn't autorelease this object, it's already autoreleased :
NSArray *mails = [[NSArray arrayWithObject:email ]autorelease];
Instead of change to:
NSArray *mails = [NSArray arrayWithObject:email];

Related

Sending an email through app; any way will do

Here is the code that I have for my cell of my UITableView:
forKeys:[NSArray arrayWithObjects:#"Title", #"Cells", #"Footer Title", nil]] autorelease];
[tableView1CellData addObject:sectionContainer_3];
NSMutableArray *cells_4 = [[[NSMutableArray alloc] init] autorelease];
NSDictionary *cellContainer_4_1 = [[[NSDictionary alloc] initWithObjects:[NSArray arrayWithObjects:#"Support", #"", #"", #"", #"", #"1", nil]
What would I have to add so that when the cell is tapped, it happened up a MailView in the app (preferably) but I understand that the easiest way is to just use the HTML "mailto" ? I'm brand new to Objective-C, but I am able to edit C and C++, so I think that I can work in any answer. Thanks in advance!
P.S. Posting this from iPhone (just thought of asking question) so sorry if the code isn't highlighted, but i tried to space it out.
Check out the documentation on MFMailComposeViewController. You can present a mail compose view, user will fill it out and send the mail.
1.Add the Message UI Framework
2.You should have registered a delegate for the UITableView. See a UITableView tutorial if needed.
3.Implement the following method:
- (void)tableView: (UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *) indexPath {
...
}
4.Inside the method use MFMailComposeViewController to send the email. Example usage:
MFMailComposeViewController* controller = [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
[controller setSubject:#"My Subject"];
[controller setMessageBody:#"Hello there." isHTML:NO];
if (controller) [self presentModalViewController:controller animated:YES];
[controller release];
Read More: How can I send mail from an iPhone application
UITableView/UITableViewCell tap event response?
And yes, you can use the mailto: URL thing... but #jer's answer is the one I would prefer to do myself, as a developer.
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"mailto://info#iosdevelopertips.com"]];
(details for the above can be found at http://iosdevelopertips.com/cocoa/launching-other-apps-within-an-iphone-application.html)

Send SMS iPhone

I was trying to send SMS from within my app. I wrote this piece of code but it seems not to work.
No crash, no error log, simply nothing happen (of course I tried to log canSendText and the result is 1).
- (void)viewDidLoad
{
[super viewDidLoad];
messageComposer = [[MFMessageComposeViewController alloc] init];
if ([MFMessageComposeViewController canSendText]) {
[messageComposer setBody:#"Messaggio generato da SMSTest"];
[messageComposer setRecipients:[NSArray arrayWithObject:#"3333333333"]];
[messageComposer setDelegate:self];
[self presentModalViewController:messageComposer animated:YES];
}
}
Can anyone explain me what I'm doing wrong?
The problem is that presentModalViewController does not work in viewDidLoad yet as the view is loaded but might not even be on screen yet. If you put your code in viewWillAppear:animated, this should work.
Edit: As per Saphrosit's comment: viewDidAppear: is an even better place to do this.
I use this successfully:
MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
controller.messageComposeDelegate = self;
controller.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentModalViewController:controller animated:YES];
Note that it's messageComposeDelegate, not 'delegate' as you do.
Tim
When i try the code on simulator i get an UIAlert saying text messaging is not available, because simulator canĀ“t send messages. Have you checked that your header file is a delegate of MFMessageComposeViewControllerDelegate ?
YourClassName : UIViewController <MFMessageComposeViewControllerDelegate>
//try this ... it will run ..
MFMessageComposeViewController *controller = [[[MFMessageComposeViewController alloc] init] autorelease];
if([MFMessageComposeViewController canSendText])
{
controller.body = #"Hello from Kartik";
controller.recipients = [NSArray arrayWithObjects:#"12356478", nil];
controller.messageComposeDelegate = self;
[self presentModalViewController:controller animated:YES];
}

Can't set recipients of MFMessageComposeViewController?

I have a method like this:
void sendSMS{
if ([MFMessageComposeViewController canSendText]) {
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
picker.recipients = [NSArray arrayWithObject:#"0933660805"];
[picker setBody:#"Message body"];
picker.messageComposeDelegate = self;
[self.navigationController presentModalViewController:picker animated:YES];
//[picker release];
return;
}
}
Message composer open but recipients and message body are empty (image below). Anybody know how can i fix it :(
Go for this ones and then check may be it will resolve your issue
void sendSMS
{
if ([MFMessageComposeViewController canSendText]) {
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
picker.messageComposeDelegate = self;
NSString *bodyString = nil;
NSMutableArray *toRecipients = [[NSMutableArray alloc]init];
[toRecipients addObject:#"0933660805"];
[picker setRecipients:(NSArray *)toRecipients];
[toRecipients release];
bodyString = [NSString stringWithFormat: #"Message body"];
[picker setBody:bodyString];
[self presentModalViewController:picker animated:YES];
[picker release];
}
Also take a look at this tutorial http://blog.mugunthkumar.com/coding/iphone-tutorial-how-to-send-in-app-sms/
Good Luck!
OK I answered my own question. Now I want no one else to have to go thru this. I was calling this method from just an NSObject. It was a delegate to MFMessageComposeViewControllerDelegate but that made no difference. I had to move this method to my MainViewController, then it worked.
iOS 10.0 is here and this is still a problem for me. So, I have fashioned a workaround.
According to previous comments that initializing the MFMessageComposeViewController in the viewDidLoad() won't solve the problem (which I can attest to), unless the view controller gets presented, it won't be cached. So, the hack here is to make a window, set its root view controller, present a dummy MFMessageComposeViewController instance and immediately dismiss it, somewhere before your actual need (like in viewDidLoad())
Here is a sample code I'm using (Swift 3.0 - Let me know if you were interested in Obj-C counterpart):
let window = UIWindow()
let vc = UIViewController()
window.rootViewController = vc
let messageCompose = MFMessageComposeViewController()
vc.present(messageCompose, animated: false) { [weak messageCompose] in
messageCompose?.dismiss(animated: false, completion: nil)
}
The thing here is that if you present it in the currently active window's view controller chain, it will mess up your UI by showing and hiding the keyboard abruptly (no matter how you try to hide the controller's view and what not), due to the message body selection on present. But adding it to a whole new window which is not in view cycle, it will be correctly initialized and there will be no trace of such transaction on view. Plus, you won't boggle the memory too much this way (because the scope of the controller should be minimal now) and you can initialize your actual MFMessageComposeViewController any time you want and get it much faster now. If your application heavily relies on MFMessageComposeViewController (which I doubt) you can move this to your AppDelegate to be ready anywhere around your app's life cycle.
Cheers,
M.
Try this
- (void)sendSMS
{
if ([MFMessageComposeViewController canSendText]) {
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
picker.messageComposeDelegate = self;
NSString *bodyString = nil;
NSArray *toRecipients = [NSArray arrayWithObject:#"NUMBER HERE"];
[picker setRecipients:toRecipients];
[self presentModalViewController:picker animated:YES];
[picker release];
}
In my case (on iPhone 3g s) the problem was when I called [self.navigationController pushViewController... ], when i tried call [self presentModalViewController ...] it worked, I dont know why, but it is. Try it.
set the MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
before if ([MFMessageComposeViewController canSendText]) {...}
Try this.
Try this.
- (void)forwardPromo
{
MFMessageComposeViewController *composeViewController = [[MFMessageComposeViewController alloc] init];
composeViewController.body = #"Message body";
composeViewController.recipients = [NSArray arrayWithObject:#"0933660805"];
composeViewController.messageComposeDelegate = self;
[self presentViewController:composeViewController animated:YES completion:nil];
}
You should have a "nil" at the end of the array:
composeViewController.recipients = [NSArray arrayWithObject:#"0933660805", nil];

The dealloc method is not called in the present modal view contrller

It is in My view controller
-(void)doctorsListAction
{
if(isFirst == YES)
{
[self getDoctorsListController];
[[self navigationController] presentModalViewController:doctorListViewNavigationController animated:YES];
[doctorListViewController release];
}
}
-(void)getDoctorsListController
{
//DoctorListViewController *doctorListViewController=[[[DoctorListViewController alloc]initWithNibName:nil bundle:nil]autorelease];
doctorListViewController=[[DoctorListViewController alloc]init];
doctorListViewNavigationController=[[UINavigationController alloc]initWithRootViewController:doctorListViewController];
doctorListViewController.doctorList=doctorList;
doctorListViewNavigationController.navigationBar.barStyle= UIBarStyleBlackOpaque;
[doctorListViewController release];
}
It is in DoctorListViewContrller
-(void)closeAction
{
printf("\n hai i am in close action*******************************");
//[doctorList release];
//[myTableView release];
//myTableView=nil;
printf("\n myTableView retainCount :%d",[myTableView retainCount]);
[[self navigationController] dismissModalViewControllerAnimated:YES];
}
//this method is not called I don't know why if it not called i will get memory issues
- (void)dealloc
{
printf("\n hai i am in dealloc of Doctor list view contrller");
[doctorList release];
[myTableView release];
myTableView=nil;
[super dealloc];
}
this method is not called I don't know
why if it not called i will get memory
issues
When exactly dealloc gets called (i.e. when the object is deallocated) shouldn't really matter to you. What matters is that you pair up each alloc with a release/autorelease. Which you are likely not doing.
The above code doesn't read very well and looks a bit "Java"-ish. Your "get" method doesn't actually return anything, which looks strange. But you normally wouldn't name a method "get___" anyway.
You're probably leaking memory in your getDoctorsListController method on this line:
doctorListViewNavigationController=[[UINavigationController alloc]initWithRootViewController:doctorListViewController];
Since you didn't define doctorListViewNavigationController in this method, and I assume you posted code that compiles, it is either a member (although not necessarily a property) of your class or a static variable somewhere. Which means it could already be pointing to an object. Which means when you assign a new alloc'ed object to it, the old one is lost (leaked).
Here's how you should refactor it.
- (void)doctorsListAction
{
if (isFirst == YES)
{
[self showDoctorsList];
}
}
- (void)showDoctorsList
{
DoctorListViewController* doctorListViewController = [[DoctorListViewController alloc] initWithNibName:nil bundle:nil];
doctorListViewController.doctorList = doctorList;
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:doctorListViewController];
navController.navigationBar.barStyle = UIBarStyleBlackOpaque;
[self.navigationController presentModalViewController:navController animated:YES];
[navController release];
[doctorListViewController release];
}
There might be a lot of other objects 'behind the scenes' that want to keep the DoctorListViewController around. If you just balance out your retains and releases, you should be ok.
Also in -(void)doctorsListAction, shouldn't [doctorListViewController release]; be [doctorListViewNavigationController release]; instead?

iphone bring up address book contact

I am having some trouble accessing the iphone addressbook given a ABReferenceID.
The method is being called correctly (accessoryButtonTappedForRowWithIndexPath), all the #import stuff is fine (as I can save the data no problem).
I have a contact with ReferenceID = 69273024, I simply want to bring 'him up.
I am trying to do this with the following technique, but line 2 is wrong. I can't work out how to correctly integrate the number into the problem. Any tips?
ABPersonViewController *pvc = [[ABPersonViewController alloc] init];
pvc.displayedPerson = 69273024;
[[self navigationController] pushViewController:pvc animated:YES];
Regards, norskben.
The displayedPerson property should be set to an ABRecordRef. You can get the ABRecordRef from the ABRecordID using ABAddressBookGetPersonWithRecordID. You can get the ABAddressBookRef using ABAddressBookCreate.
UPDATE
Here is example code, but I haven't tested it:
ABPersonViewController *pvc = [[ABPersonViewController alloc] init];
pvc.displayedPerson = ABAddressBookGetPersonWithRecordID(ABAddressBookCreate(),69273024);
[[self navigationController] pushViewController:pvc animated:YES];
[pvc release];