MFMessageComposeViewController feedback of editing of To: field - ios

I have an application which is using standard SMS functionality provided by MFMessageComposeViewController. I have an array of recipients visible in TO: field of the SMS dialog. The user has a possibility to remove or add new recipients. This is ok but my application need to know when the user edit this TO: field, because I have to do some other actions when the receivers field is changed by the user.
Is there any way to know if the recipients field are edited or no, after Cancel button click or Send button click?
I have method callback in my code:
-(void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
This method has controller.recipients but this array contains the recipients before calling of the message controller view.

This is not possible as of iOS 7. The only information provided by the delegate method is whether the user chose to cancel the message, send the message, or the sending is failed.
From the documentation:
This method is called when the user taps one of the buttons to dismiss
the message composition interface. Your implementation of this method
should dismiss the view controller and perform any additional actions
needed to process the sending of the message. The result parameter
lets you know whether the user chose to cancel or send the message or
whether sending the message failed.

To add to Enrico's answer, not only is this not possible from public API standpoint, it is also not possible by trickery, as since iOS6, the mail and message compose view controllers are rendered by different processes than your own, and their view hierarchies are completely hidden to your application. Indeed, if you were to inspect the view hierarchy of the message compose view controller's view, you would notice that none of what is on screen is actually there in the hierarchy. During the remote view's loading, the settings given to the message compose view controller are passed to the remote view controller. However, this is a one-way operation, and the properties are not updated (or read from) after the remote view is loaded.
This is to protect the user's privacy. This is a fundamental design of iOS. You should accept this, and design your application accordingly.

Related

How to get the recipient email from MFMailComposeViewController after the email is sent [duplicate]

I'm currently working on persisting the UI state of my iPhone app across launches, but it's proving to be a bit of an issue in one of my controllers - a sub-classed MFMailComposeViewController.
Essentially, I need to store (on app exit) the current To/CC/BCC lists, the subject, and the body so I can set the view up again after a relaunch. Unfortunately, Apple seems to have only provided setter methods for this data (e.g. setToRecipients:).
No doubt there's some private getters in there somewhere, but I'd rather not risk getting bounced by the App Store approvers...
Any thoughts/suggestions?
The best bet is to use controller.view, and search for all UILabels in the subview hierarchy.
(Also, there aren't private getters for MFMailComposeViewController. Those setters only delegates the message to its internal implementation class.)

Best practice for initial loading in iOS app

Just starting out iOS development.
When starting my app, I'd like it to check if the user has a known account and if they do, "login" by acquiring an access token and then display the main / first view. If they don't have an account or if login fails, they should be redirected to a login / registration screen.
Initially I thought I'd hide this process (check for account + call to get access token) behind a splash screen, but apparently this is against Apples guidelines. Is there a common / recommended way to do this on iOS?
By referencing to application:didFinishLaunchingWithOptions: you can read that this method is good for initializing.
Use this method (and the corresponding
application:willFinishLaunchingWithOptions: method) to complete your
app’s initialization and make any final tweaks. This method is called
after state restoration has occurred but before your app’s window and
other UI have been presented. At some point after this method returns,
the system calls another of your app delegate’s methods to move the
app to the active (foreground) state or the background state. This
method represents your last chance to process any keys in the
launchOptions dictionary. If you did not evaluate the keys in your
application:willFinishLaunchingWithOptions: method, you should look at
them in this method and provide an appropriate response. Objects that
are not the app delegate can access the same launchOptions dictionary
values by observing the notification named
UIApplicationDidFinishLaunchingNotification and accessing the
notification’s userInfo dictionary. That notification is sent
shortly after this method returns.
There may be several ways. But using singleton for token and launching your app is one of the best ways. As you might not need to use that launcher class again. Just for checking user have token and if yes then show main view otherwise login view.
Hope it helps you !!

Handle Push Notification infos before login

My question is about a best practice to use to handle a push notification in a defined scenario.
My app has 3 ViewControllers:
Login: User authenticates to start using the app
TableView: A simple table view with a contacts like appearance
DetailView: A simple viewController containing details from selected row of TableView
I receive a remote notification with some info in the payload (let's say a phone number for example). I need to use that info on DetailView but at receiving time I'm not logged in (app not running), so I press notification and it opens my app (Login) but I need to keep somewhere notification payload (or an object created from it) and pass it to DetailView.
So question is:
what is best practice to pass data from the notification to an inner ViewController, if the notification is received before user is logged in?
My only solution right now is: evaluate an object in didReceiveRemoteNotification, keep it in AppDelegate and access it everytime user's login to open DetailView if object is present (and clean it after using of course) but I don't think it is a good one.
Any suggestion?
What you said is mostly right because the only place you will receive a notification in is your app delegate.
but keeping a global object with the data is not the right thing to do, specially if you would like to respect design pattern and isolation between the classes.
as I understand from you the data you will get in the payload will be used in other screens in the app, so what I think the best is :
save it in User defaults or data base and access it when ever you need, and keep overriding it every time you a new notification.
if you would like to use the data base option I would like to recommend you to use Realm as it way much easier than core data and didn't take much time implementing it.
Hint: if this is the only kind of data you gonna save in the app then use User defaults.
hope this answer your question
try to save this data in User Defaults then, when you are logged in, get the data from User Defaults. Second option - set some variable and initialize it whit this data, and after that pass the data to new ViewController/

Swift logout process

I am building an app in swift which interacts with an API. There a two ways a user can be logged out, by clicking a logout button or by receiving a 401 response when calling the API.
I plan on using NSNotificationCenter in my API class to broadcast an event when an unsuccessfully response is received so generic handling of things like 401, 400, 500 can be handled in one place outside of the API class.
To prevent duplicating the logic involved with logging out in multiple places I have created a Class which will clear any existing tokens and present the login view controller. This class can then be used when the logout button is clicked in the view controller or when a 401 response is picked up by the response observer.
My problem is, since the logic is not inside a view controller I am unsure how I can present the login view controller as I do not have access to the method self.presentViewController
You're going to need to pass that responsibility to a view controller.
How I've handled this in the past is using a key-value observer (or RAC) to monitor the active token. When that token goes away, I swap out the root controller.
Where you do this depends on how you've structured things. The app delegate is a reasonable spot.

Send SMS without presenting MessageComposeViewController in iOS

I am working on sending SMS demo. I want to send how to send the SMS and how to set the delegate to MessageComposeViewController. and in order to send the message we have below line
[self presentViewController:messageController animated:NO completion:nil];
This line will present the MessageComposeView on screen with SEND button. And Once we click on send button it sends the message. What I want is to send the message directly without presenting this MessageController on screen. Please help how can I do this.
In this related question, Apple has restrictions in place on being able to send a SMS message without the user clicking the SEND button.
Apple really wants the user to be in control of the SMS functionality of their phone. Otherwise all sorts of data could be flying off some random app (e.g. spamming your contacts with "try this app out!", which would not be very friendly nor very nice).
One of the answers in this question does have a potential non-MFMessageComposeViewController solution, however I have a feeling that if Apple catches you doing this they might deny your app from being approved for the app store.
You could send the message using some webservice on the internet. http://client.suresms.com/ProjectInfo.aspx?Info=3 or www.clickatell.com. They have bunches of API for sending messages.
In SureSMS simply create an account and make a http request to
http://suresms.com/Script/GlobalSendSMS.aspx?login=[youraccountnumber]&password=[yourpassword]&to=[phonenumber]&Text=Hallo.
Remember to URL encode the message text and use countrycodes. Thats it.
You have to present MessageComposeViewController.It's not possible to send without presenting it.
MFMessageComposeViewController has delegate method while delete/send/save. which only perform while we present it.
(void) mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error
You can't do it without MFMessageComposeViewController. Apple won't allow to send SMS without user interaction.
As per document
You must not modify the view hierarchy presented by this view
controller. You can, however, customize the appearance of the
interface using the UIAppearance protocol.
I've alternate solution of this, Alternative way can be Using web service API. Create a web service at server side that send a message to specific number(s) that accept numbers as parameters with request.(according to your requirement)
As using Web server or external sms provider can do it.
It is NOT possible . Apple willn't accept your App. Apple will reject your App if you do like that. Human interface guidelines should be followed up.

Resources