Two different MFMailComposeViewController same view - xcode

hi i Have Two different MFMailComposeViewController same view, they write at two different mail address, i need to set one different success alert each one. I try with tag but MFMailComposeViewController can't use tag?
how i can do that?
That's my second MFMailComposeViewController
-(IBAction)inviaMail2{
MFMailComposeViewController *mail2 = [[MFMailComposeViewController alloc] init];
mail2.mailComposeDelegate = self;
if([MFMailComposeViewController canSendMail]){
[mail2 setToRecipients:[NSArray arrayWithObjects:#"piccolericette#alternativeindustries.it", nil]];
[self presentModalViewController:mail2 animated:YES];
}
[mail2 release];
}
- (void)mailComposeController2:(MFMailComposeViewController *)controller2 didFinishWithResult:(MFMailComposeResult)result2 error:(NSError *)error{
[self dismissModalViewControllerAnimated:YES];
if (result2 == MFMailComposeResultFailed){
UIAlertView *alert2 = [[UIAlertView alloc] initWithTitle:#"Messaggio non inviato." message:#"Non è stato possibile inviare la tua mail, verifica la tua connessione internet e riprova." delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert2 show];
[alert2 release];
}
else {
UIAlertView *alert2 = [[UIAlertView alloc] initWithTitle:#"Messaggio inviato." message:#"Grazie per avermi contattato, ti risponderò il più presto possibile." delegate:self cancelButtonTitle:#"Prego" otherButtonTitles:nil];
[alert2 show];
[alert2 release];
}
}

Update:
I somehow missed that you can access controller.view.tag which is closer to what OP wanted.
I'll keep my generic answer since it may apply to other situations where you don't have a custom field you can use.
Original Answer:
This is more of a generic design solution (workaround?) to this problem.
I'm not sure if MFMailComposeViewController has any dynamic user-info field you can use to differentiate, but you can define 2 MFMailComposeViewController* properties in your class, assign to them when creating, and check against them on result.
Something like:
#property (...) MFMailComposeViewController *mail1;
#property (...) MFMailComposeViewController *mail2;
self.mail1 = [[MFMailComposeViewController alloc] init];
...
- (void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result2 error:(NSError *)error{
if(controller == self.mail1) { ... }
}

Related

UIAlertController Warning Message

I am using the below code for UIAlertController in my project.
if([[[UIDevice currentDevice] systemVersion]floatValue] >= 8.0){
UIAlertController * alert= [UIAlertController
alertControllerWithTitle:#"Input Error"
message:#"Please enter a valid email."
preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* okAction = [UIAlertAction
actionWithTitle:#"OK"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
[alert addAction:okAction];
[self presentViewController:alert animated:YES completion:nil];
}
else
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Input Error"
message:#"Please enter a valid email"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil, nil];
[alertView show];
}
I am getting the below waring message:
Warning: Attempt to present <UIAlertController: 0x7f8da58df1f0> on <MBComplaintsViewController: 0x7f8da36454d0> which is already presenting (null)
Kindly guide me how to properly use UIAlertController using Objective C.
Thanks,
Abin Koshy Cheriyan
Yes as per #Alexander you should not be dismissing the alert controller like this explicitly.
As per an apple engineer a new window gets added each time an UIAlertController is displayed so when we go for dismissing it the window is still there though the alert controller disappears.
So there are two ways to handle this -
Way 1 - No explicit dismiss
Do not explicitly dismiss the UIAlertController, let it be done by the user
Way 2 - Use your own window
Simply create a category on UIAertController
Here is the sample code -
.h
#import <UIKit/UIKit.h>
#interface UIAlertController (MyAdditions)
#property(nonatomic,strong) UIWindow *alertWindow;
-(void)show;
#end
In .m
#import "UIAlertController+MyAdditions.h"
#import <objc/runtime.h>
#implementation UIAlertController (MyAdditions)
#dynamic alertWindow;
- (void)setAlertWindow:(UIWindow *)alertWindow {
objc_setAssociatedObject(self, #selector(alertWindow), alertWindow, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (UIWindow *)alertWindow {
return objc_getAssociatedObject(self, #selector(alertWindow));
}
- (void)show {
self.alertWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.alertWindow.rootViewController = [[UIViewController alloc] init];
// window level = topmost + 1
UIWindow *topWindow = [UIApplication sharedApplication].windows.lastObject;
self.alertWindow.windowLevel = topWindow.windowLevel + 1;
[self.alertWindow makeKeyAndVisible];
[self.alertWindow.rootViewController presentViewController:self animated:YES completion:nil];
}
-(void)hide {
self.alertWindow.hidden = YES;
self.alertWindow = nil;
}
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
// just to ensure the window gets desroyed
self.alertWindow.hidden = YES;
self.alertWindow = nil;
}
To show the alert controller
UIAlertCntroller *alert = ## initialisation##;
// will show the alert
[alert show];
//to dismiss
[alert hide];
[alert dismissViewControllerAnimated:YES completion:nil];
Even you can checkout one of my sample implementation here
I don't know about your problem, but you shouldn't do that
handler:^(UIAlertAction * action)
{
[alert dismissViewControllerAnimated:YES completion:nil];
}];
It will be anyway dismissed on any of your actions.

UIAlertView crash iOS7 - Assertion failure

I have a problem regarding the UIAlertView on iOS7.
When I launch my application, it crashes with the following message:
*** Assertion failure in -[UIKeyboardTaskQueue performTask:], /SourceCache/UIKit_Sim/UIKit-2903.2/Keyboard/UIKeyboardTaskQueue.m:388
The error occurs on the following line:
- (IBAction)updatePositions:(id)sender{
_alert = [[UIAlertView alloc] initWithTitle:#"text" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil];
[_alert show]; <====== IT CRASHS HERE
[NSThread detachNewThreadSelector:#selector(updateDataThread) toTarget:self withObject:nil];
}
I'm using ARC and the property _alert is set defined as: #property (nonatomic,strong)
This error seems strange, because on iOS6 the code works perfectly and I don't know what should be different on iOS7.
Does anyone have an idea what could the error?
Thanks in advance.
I encountered the same error, and the issue was that the UIAlertView was attempting to be shown from a thread which wasn't the main thread.
The crash however wouldn't always occur, only when a first AlertView was already being shown while this second AlertView was trying to pop up as well.
In my case, a simple fix was to do:
//Your code here
...
//Alert
_alert = [[UIAlertView alloc] initWithTitle:#"text" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil];
dispatch_async(dispatch_get_main_queue(), ^{
//Show alert here
[_alert show];
});
//Resume your code here
...
I just had this problem after forgetting that I was working from a background thread. I don't know if that's the case here, but I'd make sure you're not trying to call updatePositions: from anything other than the main thread.
Change your code like this :
_alert = [[UIAlertView alloc] initWithTitle:#"text" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil];
[_alert show];
removing [[ and ]] around #"text"
But, your I don't think your problem came from this UIAlertView.
I had the same problem as well but not too familiar with the method dispatch_async. I used
[alert performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:NO];
and the problem hasn't come up again.
Put your alertview code in a separate function like
-(void)showAlert
{
_alert = [[UIAlertView alloc] initWithTitle:#"text" message:nil delegate:self cancelButtonTitle:nil otherButtonTitles: nil];
[_alert show];
}
Then in your IBAction do this
- (IBAction)updatePositions:(id)sender
{
[self performSelectorOnMainThread:#selector(showAlert) withObject:nil waitUntilDone:YES];
[NSThread detachNewThreadSelector:#selector(updateDataThread) toTarget:self withObject:nil];
}
You can also do like this:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Your title" message:#"Your message" delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:YES];
However, if you need to show the same alert in multiple places it's better to create a separate function for it.

UIActivityViewController

I have a problem with the UIActivityViewController on iPad
Here is my Code:
NSString* someText = #"Hi, I am using the official iEveryThing Tech app #iEveryTech";
NSString* Website = [NSURL URLWithString:#"https://itunes.apple.com/us/app/ieverytech/id578148847?l=de&ls=1&mt=8"];
NSArray* dataToShare = #[someText,Website];
Class activityViewController = NSClassFromString(#"UIActivityViewController");
if(activityViewController) {
UIActivityViewController* activityViewController =
[[UIActivityViewController alloc] initWithActivityItems:dataToShare
applicationActivities:nil];
[self presentViewController:activityViewController animated:YES completion:nil];}
}
On iPhone the Mail composer View will disappear after sending the mail but not the Composer on the iPad here is my Composer:
-(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:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil, nil];
[alert show];
[self dismissModalViewControllerAnimated:YES];
}
else {
[self dismissModalViewControllerAnimated:YES];
}
}
The activityViewController use a native method for send mail don't need use mailComposeController, like this
NSMutableArray *items = [NSMutableArray new];
[items addObject:#"text for share"];
[items addObject:[UIImage imageWithData:[NSData dataWithContentsOfFile:self.imagePath]]];
NSArray *activityItems = [NSArray arrayWithArray:items];
self.activityVC = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:[NSArray arrayWithObjects:whatsapp,instagram, nil]];
self.activityVC.excludedActivityTypes = #[UIActivityTypeAssignToContact, UIActivityTypePrint,UIActivityTypeAirDrop,UIActivityTypeCopyToPasteboard];
[self presentViewController:self.activityVC animated:YES completion:nil];
First thing, when using the activityViewController, your class is not the delegate for the mail composer and the code will not be called. This is all handled internally in the activityViewController.
As for your view not being dismissed, implement the complete block call for the activityViewController. In the block be sure to dismiss the view controller.

Game Center? Xcode

I have been working ver hard on Game center. I have tested so many codes I've lost count.
I would love to know how to automatically submit score as well
here are some codes i have used but i am not sure if this will help
-(IBAction)showleaderboard:(id)sender{
GKLeaderboardViewController *leaderboardController = [[GKLeaderboardViewController alloc]init];
if (leaderboardController !=NULL) {
leaderboardController.category = self.currentLeaderboard;
leaderboardController.timeScope = GKLeaderboardTimeScopeAllTime;
leaderboardController.leaderboardDelegate = self;
[self presentModalViewController:leaderboardController animated:YES];
}
}
-(void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController{
[self dismissModalViewControllerAnimated:YES];
[viewController release];
}
-(IBAction)showAchivementLeaderboard:(id)sender{
GKAchievementViewController *achivements = [[GKAchievementViewController alloc]init];
if (achivements !=NULL) {
achivements.achievementDelegate = self;
[self presentModalViewController:achivements animated:YES];
}
}
-(void)achievementViewControllerDidFinish:(GKAchievementViewController *)viewController{
[self dismissModalViewControllerAnimated:YES];
[viewController release];
}
self.currentLeaderboard= kEasyLeaderboardID;
if ([gameCenterManager isGameCenterAvailible]) {
self.gameCenterManager= [[[GameCenterManager alloc] init] autorelease];
[self.gameCenterManager setDelegate:self];
[self.gameCenterManager authenticateLocalUser];
}else{
UIAlertView *openURLAlert = [[ UIAlertView alloc] initWithTitle:#"Game Center turned off" message:#"You are not connected to game center." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil];
[openURLAlert show];
[openURLAlert release];
}
To report a score you need to use GKScore as follows;
GKScore *scoreReporter = [[GKScore alloc] initWithCategory:self.gameCategory.leaderboardString];
scoreReporter.value = score;
[scoreReporter reportScoreWithCompletionHandler:^(NSError *error) {
if (error != nil) {
[[KYTGlobals instance] storeScore:score forCategory:self.gameCategory.leaderboardString];
}
}];
The above code allocates and inits a GKScore object using the identifier that you have already set up on game center for the category that you want to report a score for. You update the value for the score and then use reportScoreWithCompletionHandler making sure to test for error so that you can archive the score and report it later.

Why does iPhone execute both of these if statements in a view controller .m file?

When the IBAction login is invoked it supposed to use a response from SOAP Web Services of either true or false, false meaning the user is not authorized to use the app.
I have it using these if statements after it gets the response, but for some reason it runs both true and false ifs.
{
[soapResults appendString: string];
NSLog(soapResults);
if (soapResults = #"true")
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:soapResults delegate:self cancelButtonTitle:#"Try Again",nil otherButtonTitles:nil];
[alert show];
[alert release];
[soapResults release];
soapResults = nil;
[loginIndicator stopAnimating];
loginIndicator.hidden = TRUE;
loggedinLabel.text = usernameField.text;
loggedinLabel.textColor = [UIColor blackColor];
NSLog(#"Valid Login");
}
if (soapResults = #"false")
{
NSLog(#"Invalid Login");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:soapResults delegate:self cancelButtonTitle:#"Try Again",nil otherButtonTitles:nil];
[alert show];
[alert release];
[soapResults release];
soapResults = nil;
[loginIndicator stopAnimating];
loginIndicator.hidden = TRUE;
}
}
Please Help
There is only one equal sign in the if statements. This assigns the string to the soapResults variable which causes the if statement to evaluate the string (which will always be true).
if (#"true")
Instead, use two equal signs to do the comparison.
if (soapResults == #"true")
Some avoid this common problem by always placing the variable at the end of the comparison.
if (#"true" == soapResults)
This way if you forget the second equal sign it will cause a compilation error which is much easier to find.
Update: as the commentators kindly pointed out, you should not compare Objective-C strings using the == operator. Instead use the isEqualToString method.
if ([soapResults isEqualToString:#"true"])

Resources