iOS: How do I detect if an email has been successfully sent? - ios

I am trying to check if an Email message was sent and display an Alert allowing the user know.
I tried the delegate method below , but sadly will display the alert message if user cancels as well. Any help will be appreciated and rewarded.
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error{
if (error) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:
[NSString stringWithFormat:#"Error %#", [error description]] delegate:self
cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[alert show];
}
NSLog(#"email sent");
}
}

All that it means when that function is called is that something happened with the email because the MFMailComposeViewController is finished. To know what did actually happen, you have to take a look at the value of result, which can be any of the following:
MFMailComposeResultCancelled
MFMailComposeResultSaved
MFMailComposeResultSent
MFMailComposeResultFailed
As rmaddy says in comments, you can't be 100% sure that the email was actually sent (it could be stuck in the outbox). What MFMailComposeResultSent signifies, then, is that the email has been sent over to the Mail app, which will send it as soon as it can.

Related

iOS - HomeKit: why it takes too long to add a user?

I am trying to add a user (HMUser) to my home (HMHome) by
[self.home addUserWithCompletionHandler:^(HMUser *user, NSError *error) {
if (error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:error.localizedDescription
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
return;
}
NSLog(#"add done!");
[weakSelf.tableView reloadData];
}];
as referenced from: https://developer.apple.com/library/ios/documentation/NetworkingInternet/Conceptual/HomeKitDeveloperGuide/ManagingUsers/ManagingUsers.html
From my phone (whose iCloud email is: me#gmail.com for e.g.), I add a guest (whose iCloud email is: guest#gmail.com for e.g.). Immediately, the guest receives a notification from Apple and has to press Accept, as expected. After that, my app can display the guest email, which is correct. The issue is: the guest is very hard to view my shared home. Sometimes I have to wait ~ 2 hours but the guest still cannot view my home layout. I tried to reset wifi/bluetooth on the guest phone but things are not better.
Do you have any ideas about this issue on how to fix it?
Thanks in advance,

Touch ID for login iOS

I'm making an iOS application (Obj-c) with a login form. I'm trying to figure out if there is a way to use Touch ID to login. This will be an amazing feature for my app, but I can't find a way to do it.
In the last PayPal update they include the Touch ID login - so there is a way to do it.
EDIT: I know how to get if the user enter the correct Touch ID, but I don't know what to do after that.
What if the user enter his username and then add the Touch ID correctly? How could I know this user have this Touch ID?
Okay first create an action like so:
We need more detail tough, as I do not know if you mean Obj-C or swift, I'll just post both.
Obj-C
Firstly import the local authentication framework
#import <LocalAuthentication/LocalAuthentication.h>
Then we create an IBAction and add the following code:
- (IBAction)authenticateButtonTapped:(id)sender {
LAContext *context = [[LAContext alloc] init];
NSError *error = nil;
if ([context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error]) {
[context evaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics
localizedReason:#"Are you the device owner?"
reply:^(BOOL success, NSError *error) {
if (error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"There was a problem verifying your identity."
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
return;
}
if (success) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Success"
message:#"You are the device owner!"
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"You are not the device owner."
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
}
}];
} else {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Your device cannot authenticate using TouchID."
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles:nil];
[alert show];
}
}
The just connect your IBAction to a button that will prompt authentication.
However in Swift you would use:
Add the following framework to your project: LocalAuthentication
Then import it in your swift file:
import LocalAuthentication
Then create the following method that will prompt you to use touch id:
func authenticateUser() {
// Get the local authentication context.
let context = LAContext()
// Declare a NSError variable.
var error: NSError?
// Set the reason string that will appear on the authentication alert.
var reasonString = "Authentication is needed to access your notes."
// Check if the device can evaluate the policy.
if context.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error) {
[context .evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: reasonString, reply: { (success: Bool, evalPolicyError: NSError?) -> Void in
if success {
}
else{
// If authentication failed then show a message to the console with a short description.
// In case that the error is a user fallback, then show the password alert view.
println(evalPolicyError?.localizedDescription)
switch evalPolicyError!.code {
case LAError.SystemCancel.rawValue():
println("Authentication was cancelled by the system")
case LAError.UserCancel.rawValue():
println("Authentication was cancelled by the user")
case LAError.UserFallback.rawValue():
println("User selected to enter custom password")
self.showPasswordAlert()
default:
println("Authentication failed")
self.showPasswordAlert()
}
}
})]
}
else{
// If the security policy cannot be evaluated then show a short message depending on the error.
switch error!.code{
case LAError.TouchIDNotEnrolled.rawValue():
println("TouchID is not enrolled")
case LAError.PasscodeNotSet.rawValue():
println("A passcode has not been set")
default:
// The LAError.TouchIDNotAvailable case.
println("TouchID not available")
}
// Optionally the error description can be displayed on the console.
println(error?.localizedDescription)
// Show the custom alert view to allow users to enter the password.
self.showPasswordAlert()
}
}
Lastly from the func viewDidLoad call the function like so: authenticateUser()
Hope that helps. Keep coding.
Sources:
Swift:
App Coda iOS 8 Touch ID Api
Objective-C:
tutPlus iOS Touch ID
Thanks to Matt Logan for the updated swift code.
I think I understand what I have to do!
After the first user Login I'll save his password (at NSUserdefaults for example).
If the user want to use his Touch ID at the next login - I'll ask him for the Touch ID and if it's correct i'll let him in with the password saved at the beginning.
Thanks to Julian :)

Why does [PFPurchase buyProduct] requires me to login twice?

I use PFPurchase's buyProduct method call to initiate the in-app purchase process. Although it requires me to enter the test account's email address and the password twice to complete the process.
When I enter the email and the password for the first time, the prompt just disappears and comes back after 2-3 seconds and I have to enter them again.
I use auto-renewing subscriptions with a trial period of 7 days.
My app has one ViewController and I have the below code in the viewDidLoad function.
[PFPurchase addObserverForProduct:#"com.tls.1monthsubscription" block:^(SKPaymentTransaction *transaction) {
NSLog(#"Product purchased");
[self checkReceipt];
}];
Below function gets called when I tap on the "BUY" button from the UI:
-(IBAction)purchaseThirtyDaysSubscriptionBtnAction:(id)sender
{
[SVProgressHUD show];
[PFPurchase buyProduct:#"com.tls.1monthsubscription" block:^(NSError *error) {
if (!error) {
[SVProgressHUD dismiss];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Purchase Succeeded" message:#"You have purchased subscription successfully!" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil, nil];
[alertView show];
} else {
[SVProgressHUD showErrorWithStatus:[error localizedDescription]];
}
}];
}
Any ideas?

Parse - Sign Up and Login at the same time

Using Parse (iOS framework), I am able to sign up and login successfully using two API.
When user log in, it will cache the user and so accessing "currentUser" will return appropriate object. But sign up API is not caching.
Is there any way that sign up itself will cache the user and avoid separate log in functionality?
It should automatically log you in as well. For example, if in your completion block in signUpInBackground, you have a segue to your main screen and in your main screen, it is supposed to show information related to the user, then it will because [PFUser currentUser] is set to the user that registered.
here is an example
[user signUpInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (error) {
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[[error userInfo] objectForKey:#"error"] message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok", nil];
[alertView show];
// Bring the keyboard back up, because they'll probably need to change something.
[_usernameField becomeFirstResponder];
}
else{
// Success!
[self performSegueWithIdentifier:#"goToMain" sender:self];
}
}];

App crashes after displaying nserror message in uialertview from parseErrorOccurred

I'm trying to post userid and password and retrieve user information using HttpRequest. I'm getting expected result, but client had reported the app is crashing after authentication. He had sent a video which shows how the app crashes. From that i concluded the app is crashing after displaying nserror message in uialertview from
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError
The error message i'm getting is "The operation couldn't be completed. (NSXMLParserErrorDomain error 39.)"
After showing this message in alert view the app is crashing suddenly. I'm not facing this crash anyhow. Can anyone help me to sort out this. Thanks in advance.
The code i have used in parseErrorOccured is
NSString *errorMessage = [error localizedDescription];
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Connection Error!" message:errorMessage
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
[alertView release];
From experience, [error localizedDescription] or [error localizedFailureReason] may return a nil NSString.
In your code, you should check to see if errorMessage is nil, if it is try setting errorMessage to [error localizedFailureReason]. I'd check for a NULL value again.

Resources