Send a text message directly via an IBAction (Objective-C) - ios

How do I send a text message (using MFMessageComposeViewController) directly via an IBAction? Like, when the button is pressed, a text message is sent with a preset number, and no keyboard shows up or anything. Just an alert saying "SMS was sent successfully," for example.
All the coding is done, except for this "direct sending-function".

Well, you can't technically "auto-send" the message, because it will require user confirmation to go through.
You can, however, set up the message's contents and recipient(s) using MFMessageComposeViewController (quite a mouthful) and display a dialog that will require one extra tap to send.
To have access to that dialog, you'll have to #import <MessageUI/MessageUI.h> and add MFMessageComposeViewControllerDelegate to your view controller declaration in your header file.
Then, you can write the IBAction. First, you want to check that the device can actually send messages with text content using canSendText. Then, you'll create the view controller, populate it with data, and present the dialog.
- (IBAction)sendMessage:(UIButton *)sender {
if([MFMessageComposeViewController canSendText]) {
MFMessageComposeViewController *messageController = [[MFMessageComposeViewController alloc] init]; // Create message VC
messageController.messageComposeDelegate = self; // Set delegate to current instance
NSMutableArray *recipients = [[NSMutableArray alloc] init]; // Create an array to hold the recipients
[recipients addObject:#"555-555-5555"]; // Append example phone number to array
messageController.recipients = recipients; // Set the recipients of the message to the created array
messageController.body = #"Example message"; // Set initial text to example message
dispatch_async(dispatch_get_main_queue(), ^{ // Present VC when possible
[self presentViewController:messageController animated:YES completion:NULL];
});
}
}
One last thing: you have to implement a delegate method to tell the message view controller to dismiss when the user presses "cancel" in the send dialog:
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result {
[self dismissViewControllerAnimated:YES completion:NULL];
}

Related

iOS: How to get the identifier of an event, which was created via a call to EKEventEditViewController

In my app, the user can create events. This is achieved by presenting the user the UI of iOS for creating an event:
- (IBAction)addTermin:(id)sender
{
// Create an instance of EKEventEditViewController
EKEventEditViewController *addController = [[EKEventEditViewController alloc] init];
// Set addController's event store to the current event store
addController.eventStore = self.eventStore;
addController.editViewDelegate = self;
[self presentViewController:addController animated:YES completion:nil];
}
So, I implement the delegate method:
- (void)eventEditViewController:(EKEventEditViewController *)controller
didCompleteWithAction:(EKEventEditViewAction)action
{
MRHomeViewController * __weak weakSelf = self;
// Dismiss the modal view controller
[self dismissViewControllerAnimated:YES completion:^
{
if (action != EKEventEditViewActionCanceled)
{
dispatch_async(dispatch_get_main_queue(), ^{
// Re-fetch all events happening in the next 24 hours
weakSelf.eventsList = [self fetchEvents];
// Update the UI with the above events
[weakSelf.termineTableView reloadData];
});
}
}];
}
So, later I want to retrieve the events a user has created. I was thinking , that somewhere, somehow in the delegate method, I can obtain a reference to the new created event?
Or is there another way to later fetch only events created by the user?
To make this work, you need to first create a new EKEvent, keep a reference to it, and pass it into your EKEventEditViewController:
self.newEvent = [EKEvent eventWithEventStore:self.eventStore];
addController.event = newEvent;
In the delegate method, check for EKEventEditViewActionSaved and then consult self.newEvent to find what you need about the event. If you want to maintain a longer term reference to the event, you can store the eventIdentifier or other fields for later lookup.

Subclass PFLogInViewController to render custom UIAlertViews

I am using Parse as the backend for my iOS app and I'm also using the native PFLogInViewController & PFSignUpViewController for login and signup tasks.
Issue?
I've customized the look of my UIAlertViews throughout the app and it turns out that Parse have hard-coded calls to UIAlertViews in their native PFLogInViewController & PFSignUpViewController implementations. An e.g. for this alert view is when the login fails due to incorrect username & password combination.
I'm wondering how I can subclass PFLogInViewController & PFSignUpViewController and implement my own custom UIAlertView class.
EDIT — Any ideas people?
PFLogInViewController does not provide hooks to change this behavior. You might want to build your own custom PFLogInViewController subclass and override the method which display alert view when login failed.
Since PFLogInViewController's code has been open sourced, according to it the method which displays an alert view is _loginDidFailWithError.
https://github.com/ParsePlatform/ParseUI-iOS/blob/master/ParseUI/Classes/LogInViewController/PFLogInViewController.m#L382-L390
- (void)_loginDidFailWithError:(NSError *)error {
if (_delegateExistingMethods.didFailToLogIn) {
[_delegate logInViewController:self didFailToLogInWithError:error];
}
[[NSNotificationCenter defaultCenter] postNotificationName:PFLogInFailureNotification object:self];
NSString *title = NSLocalizedString(#"Login Error", #"Login error alert title in PFLogInViewController");
[PFUIAlertView showAlertViewWithTitle:title error:error];
}
For example, if you like the following, you can not to display alerts when the login fails.
Define MYLogInViewController as subclass of PFLogInViewController
#interface MYLogInViewController : PFLogInViewController
#end
#implementation MYLogInViewController
- (void)_loginDidFailWithError:(NSError *)error {
if ([self.delegate respondsToSelector:#selector(logInViewController:didFailToLogInWithError:)]) {
[self.delegate logInViewController:self didFailToLogInWithError:error];
}
[[NSNotificationCenter defaultCenter] postNotificationName:PFLogInFailureNotification object:self];
NSString *title = NSLocalizedString(#"Login Error", #"Login error alert title in PFLogInViewController");
//
// Implement to display your custom alert view
//
}
#end
and use it instead PFLogInViewController
MYLogInViewController *logInViewController = [[MYLogInViewController alloc] init];
logInViewController.delegate = self;
[self presentViewController:logInViewController animated:YES completion:nil];
See here: https://parse.com/tutorials/login-and-signup-views under "Subclassing for Full Customization".

How to open iPhone's mail app when clicking an email link in UITextView?

I am new in iPhone devlopment. I have an UITextView in a xib. There I displaying an email address link. I want to open iPhone's mail application while clicking on that email link. How can I achieve that?
As pointed out in this answer, you can set the dataDetectorTypes property of the UITextView:
textview.editable = NO;
textview.dataDetectorTypes = UIDataDetectorTypeAll;
You should also be able to set the detectorTypes in Interface Builder.
From Apple documentation:
UIDataDetectorTypes
Defines the types of information that can be detected in text-based content.
enum {
UIDataDetectorTypePhoneNumber = 1 << 0,
UIDataDetectorTypeLink = 1 << 1,
UIDataDetectorTypeAddress = 1 << 2,
UIDataDetectorTypeCalendarEvent = 1 << 3,
UIDataDetectorTypeNone = 0,
UIDataDetectorTypeAll = NSUIntegerMax
}; typedef NSUInteger UIDataDetectorTypes;
Clicking on the email address in your UITextView should then automatically open the Mail application.
On a side note, if you want to send the email from within your app itself, you can use the MFMailComposeViewController.
Note that for the MFMailComposeViewController to be shown, Mail app needs to be installed on the device, and have an account linked to it, otherwise your app will crash.
So you can check this with [MFMailComposeViewController canSendMail]:
// Check that a mail account is available
if ([MFMailComposeViewController canSendMail]) {
MFMailComposeViewController * emailController = [[MFMailComposeViewController alloc] init];
emailController.mailComposeDelegate = self;
[emailController setSubject:subject];
[emailController setMessageBody:mailBody isHTML:YES];
[emailController setToRecipients:recipients];
[self presentViewController:emailController animated:YES completion:nil];
[emailController release];
}
// Show error if no mail account is active
else {
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:#"Warning" message:#"You must have a mail account in order to send an email" delegate:nil cancelButtonTitle:NSLocalizedString(#"OK", #"OK") otherButtonTitles:nil];
[alertView show];
[alertView release];
}
MFMailComposeViewController Class Reference
In addition to the code above, once the user has pressed the send or cancel buttons you will need to dismiss the modal email view.
The MFMailComposeViewControllerDelegate protocol includes a method called "didFinishWithResult". This method will be automatically called as the view closes.
However, if you don't implement it, nothing will happen & the modal view will remain, bringing your app to a standstill!
The following code is required as a minimum:
- (void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
{
// Close the Mail Interface
[self dismissViewControllerAnimated:YES completion:NULL];
}

mail interface cancel button not working ios - MFMailComposeViewController class

I have a webview object (aWebView) which was added on top of current window like this -
UIWindow *webWindow = [[UIWindow alloc] initWithFrame:CGRectMake(0, 20, 320,460)];
[webWindow addSubview:aWebView];
[webWindow makeKeyAndVisible];
I have a ViewController (viewcontrollerobj) which is subView of aWebView -
[webView addSubview:viewcontrollerobj.view];
Then I am calling sendInAppMail method in the ViewController-
[sviewcontroller sendInAppMail];
SendInAppMail looks like this -
MFMailComposeViewController *mailController = [[[MFMailComposeViewController alloc] init] autorelease];
if([MFMailComposeViewController canSendMail])
{
[mailController setMessageBody:#"hello" isHTML:NO];
[mailController setSubject:#"subject"];
mailController.mailComposeDelegate = self;
[self presentModalViewController:mailController animated:YES];
[mailController release];
}
didFinishWithResult looks like this -
- (void)mailComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
switch (result) {
case MFMailComposeResultCancelled:
break;
case MFMailComposeResultSent:
break;
default:
break;
}
[self dismissModalViewControllerAnimated:YES];
}
Mail viewcontroller shows up fine. The problem is that when I hit cancel it shows the delete/save draf t option and after clicking either delete/save the mail viewcontroller doesn't go away!
When I look at console it shows this log message -
"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:]."
I am not using UIActionSheet anywhere and haven't used in the past so I am not able to understand what it is saying.
I looked at this - https://stackoverflow.com/a/6015957/516938
But it seems like the solution given is very specific to a situation.
Not sure this is the issue, but this is the first thing I would look at.
Based on the error message that you got it sounds like either one of the views (the aWebView or the one from viewcontrollerobj that you defined) doesn't allow enough space for the MFMailComposeViewController, meaning that the dimensions of it are smaller than the MFMailComposeViewController requires. It isn't actually clipping the content, so you see it, but it is blocking the touches so that they don't get to the MFMailComposeViewController.
I hope that is clear enough - I had a hard time describing my thoughts here correctly.

Load screen after finishing web service calls

My first screen that contains a uitableview, I used to call webservice method in viewdidload:
- (void)viewDidLoad {
[super viewDidLoad];
self.navigationItem.title =#"Brand List";
getBrands *obj = [[getBrands alloc]init];
[obj getBrandsList];
getBrandsList, but before the webservice finished, it loads the screen, so the screen contains an empty list.
So I need to wait (ie. loading dialog) until the method completes and then show the screen with data.
How do I do this?
Create an new View with an UIActivityIndicatorView and an UILabel. Then add it on top of your window with some CATransition. When you finish download remove this screen.
-(IBAction) buttonClick: (id) sender{
//show loading dialog here(activity indicator)
[self performSelectorInBackground:#selector(callWebService) withObject:nil];
}
-(void) callWebService
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
//resend request and parse response.
// create new view controller object and push screen
// hide loading indicator
[pool release];
}

Resources