skscene UIViewController send SMS from SKScene - ios

I am trying to allow the player to share their score by SMS when the game is over.
I have imported the framework in to my project. Imported in the my viewController.h file.
here is my viewController.h file
#import <UIKit/UIKit.h>
#import <SpriteKit/SpriteKit.h>
#import <MessageUI/MessageUI.h>
#interface myViewController : UIViewController <MFMessageComposeViewControllerDelegate> {
}
#end
I also tried to import into MyScene.h like so:
#import <MessageUI/MessageUI.h>
#interface MyScene : SKScene <MFMessageComposeViewControllerDelegate> {
}
When I want to show the SMS share, I use this code in my MyScene.m file
MFMessageComposeViewController *textComposer = [[MFMessageComposeViewController alloc] init];
[textComposer setMessageComposeDelegate:self];
if ([MFMessageComposeViewController canSendText]) {
[textComposer setRecipients:[NSArray arrayWithObject:nil]];
[textComposer setBody:#"Happy Happy Joy Joy!"];
[self presentViewController:textComposer animated:YES completion:NULL];
} else {
NSLog(#"Cant send text!");
}
But on this line
[self presentViewController:textComposer animated:YES completion:NULL];
I get an "No visible #interface for 'MyScene' declares the selector 'presentViewController:animated:completion:'" error.
I have tried to search for the last couple hours. Try god knows how many variations and examples from other posts/tutorials(which was good to learn a few things unrelated to this). Nothing seems the work. I starting to run out of hair to pull out. So any help would be great. I am sure for some of you Gurus here this should be a walk in the park. Thanks.
EDIT: I am not using storyboard, or the view controller for buttons/menu/game play etc...hence why I am not able to call the function from within the viewController itself.
EDIT:
So I tried what Paulw11 suggested in his link. Now I have the following errors.
in myViewController
MyScene.MyViewController = self;
I get a "Property 'MyViewController' not found on object of type 'MyScene'" error
also in MyScene.m
- (void)sendToController
{
NSLog(#"ok");
// use the already-created spriteViewController
[_MyViewController sendSMS];
}
[_MyViewController sendSMS]; line I get an "No visible #interface for 'MyViewController' declares the selector 'SendSMS'"
EDIT 2: *EDIT 2:* EDIT 2: *EDIT 2:*
I got it to open up the SMS. Small problem, it does not allow me to dismiss it /cancel.
Here is my sendSMS code:
-(void) sendSMS {
MFMessageComposeViewController *textComposer = [[MFMessageComposeViewController alloc] init];
[textComposer setMessageComposeDelegate:self];
if ([MFMessageComposeViewController canSendText]) {
[textComposer setRecipients:[NSArray arrayWithObject:#" "]];
NSString *body = [NSString stringWithFormat:#"Happy Day!: %i. ", _score];
[textComposer setBody:body];
UIViewController *vc = self.view.window.rootViewController;
[vc presentViewController: textComposer animated: YES completion:nil];
} else {
NSLog(#"Cant send text!");
}
}
Here is my dismiss code:
-(void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result {
UIViewController *vc = self.view.window.rootViewController;
[vc dismissViewControllerAnimated:YES completion:NULL];
}
EDIT 3
The following code gives me the NSLog at the correct times, but does not dismiss the window.
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller
didFinishWithResult:(MessageComposeResult)result
{
UIViewController *vc = self.view.window.rootViewController;
// Notifies users about errors associated with the interface
switch (result)
{
case MessageComposeResultCancelled:
NSLog(#"Result: SMS sending canceled");
break;
case MessageComposeResultSent:
NSLog(#"Result: SMS sent");
break;
case MessageComposeResultFailed:
NSLog(#"Result: SMS sending failed");
break;
default:
NSLog(#"Result: SMS not sent");
break;
}
[vc dismissViewControllerAnimated:YES completion:NULL];
}

If you refer to the MFMessageComposeViewController Class Reference you will see that you need to present it modally using presentModalViewController:animated:. You are also responsible for dismissing it via your delegate object once you are done.
I suggest you have a look at the Message Composer sample code for an example of using the MFMessageComposeViewController class.
UPDATE
You can just dismiss the view controller that was passed to your delegate method -
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller
didFinishWithResult:(MessageComposeResult)result
{
// Notifies users about errors associated with the interface
switch (result)
{
case MessageComposeResultCancelled:
NSLog(#"Result: SMS sending canceled");
break;
case MessageComposeResultSent:
NSLog(#"Result: SMS sent");
break;
case MessageComposeResultFailed:
NSLog(#"Result: SMS sending failed");
break;
default:
NSLog(#"Result: SMS not sent");
break;
}
[controller dismissViewControllerAnimated:YES completion:NULL];
}

Related

Objective C MFMailComposeViewController Cancel -> Cancel button not working

Please find the code and attached pic. That cancel button not working . If I click that button, that modal alone closing. It is not triggering "mailComposeController:didFinishWithResult" function..I am new to Objective c IOS. Please help me to get out of this issue. I searched in stack overflow. But I problem didn't solve
#import "ViewController.h"
#import <MessageUI/MFMailComposeViewController.h>
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UIButton *send;
- (IBAction)sendMail:(id)sender;
#end
#implementation ViewController
MFMailComposeViewController* controller;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
controller= [[MFMailComposeViewController alloc] init];
controller.mailComposeDelegate = self;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)sendMail:(id)sender {
[controller setSubject:#"My Subject"];
[controller setMessageBody:#"Hello there." isHTML:NO];
if (controller) [self presentViewController:controller animated:YES completion:nil];
}
- (void)mailComposeController:(MFMailComposeViewController*)controller
didFinishWithResult:(MFMailComposeResult)result
error:(NSError*)error;
{
NSLog(#"Coming here");
if (result == MFMailComposeResultSent) {
NSLog(#"Mail It's away!");
}
if (result == MFMailComposeResultFailed) {
NSLog(#"Mail Error!");
}
if(result == MFMailComposeResultCancelled){
NSLog(#"Mail Error!");
}
if(result == MFMailComposeResultSaved){
NSLog(#"Mail Saved!");
}
[controller dismissViewControllerAnimated:YES completion:nil];
return;
}
[![Screen shot][1]][1]#end
Man this cancel button does nothing at all other than dismissing action sheet. If you want to get rid of mail composer you have to press cancel at upper left corner which shows you an action sheet at the bottom with options Delete Draft, Save Draft and cancel. Delete draft and save draft will dismiss the mail composer and the delegate function will be called. Cancel button will actually dismiss action sheet in order to save the mail composer from dismissing in case if user accidentally clicked that cancel button at the top

messageComposeViewController didFinishWithResult delegate method not being called

I have a view controller "Paircontroller" that presents an MFMessageComposeViewController, as so:
NSArray *recpts = [[NSArray alloc]initWithObjects:phone.text, nil];
MFMessageComposeViewController *mcontr = [[MFMessageComposeViewController alloc]init];
mcontr.body = #"Sign up for our app!";
mcontr.recipients = recpts;
mcontr.subject = #"hey!";
mcontr.delegate = self;
[self presentViewController:mcontr animated:YES completion:^{
}];
this view controller's interface looks as follows:
#interface PairViewController : UIViewController<UITextFieldDelegate,CustomIOS7AlertViewDelegate, UINavigationControllerDelegate, MFMessageComposeViewControllerDelegate>
#end
Within the view-controller's implementation, I have defined the delegate method - (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
as follows:
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
switch (result) {
case MessageComposeResultCancelled:
NSLog(#"Cancelled");
break;
case MessageComposeResultFailed:
NSLog(#"unknown error sending m");
break;
case MessageComposeResultSent:
NSLog(#"Message sent successfully");
break;
default:
break;
}
[self dismissViewControllerAnimated:YES completion:^{}];
}
However, the delegate method is not being called (breakpoint not hit, and NSLogs not being hit either).
Can someone help me out on why this is not working?
Thanks!
C
I think the following change should work. MFMessageComposeViewController is a UINavigationController subclass, so in your original code you are setting UINavigationControllerDelegate to self.
mcontr.messageComposeDelegate = self;

Warning: Attempt to present * on * whose view is not in the window hierarchy

i am new to objective C and im trying to make a share button for twitter in my game. Im using spritebuilder to create all my buttons and sprites. All of my code lies in MainScene.m while my code for twitter share sheet is in ShareViewController.m
In my MainScene.m file i have a method sendToController, which using an object of shareViewController calls a method postToTwitter which is in ShareViewController.m. Due to some reason this tweetsheet is not visbile and from what i gather is that there is a window heirachy problem which i am not able to solve.
Here is the code in MainScene.m
ShareViewController *_shareViewController;
#synthesize shareViewController;
(void)sendToController {
_shareViewController = [ShareViewController alloc];
[_shareViewController postToTwitter];
}
Here is the code for ShareViewController.m
#implementation ShareViewController {
MainScene *_mainSceneObj;
}
- (void)viewDidLoad
{
[super viewDidLoad];
_mainSceneObj.ShareViewController = self;
}
- (void)postToTwitter {
NSLog(#"in postToTwitter %d", [SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter]);
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
SLComposeViewController *tweetSheet = [SLComposeViewController
composeViewControllerForServiceType:SLServiceTypeTwitter];
// Sets the completion handler. Note that we don't know which thread the
// block will be called on, so we need to ensure that any required UI
// updates occur on the main queue
tweetSheet.completionHandler = ^(SLComposeViewControllerResult result) {
switch(result) {
// This means the user cancelled without sending the Tweet
case SLComposeViewControllerResultCancelled:
break;
// This means the user hit 'Send'
case SLComposeViewControllerResultDone:
break;
}
};
// Set the initial body of the Tweet
[tweetSheet setInitialText:#"just setting up my twttr"];
if (![tweetSheet addImage:[UIImage imageNamed:#"screen.png"]]) {
NSLog(#"Unable to add the image!");
}
if (![tweetSheet addURL:[NSURL URLWithString:#"http://twitter.com/"]]){
NSLog(#"Unable to add the URL!");
}
// Presents the Tweet Sheet to the user
[self presentViewController:tweetSheet animated:NO completion:^{
NSLog(#"Tweet sheet has been presented.");
}]; }
}

SMS Open Up With Message

I have created an application that uses the SMS and after the user clicks the sms button it opens up with my number already in and no message (thats their job). But when it loads up the sms message page it set the curser thing is up where the recipients are not where the message is. To explain that better, after the sms loads if they were to just start typing they would be adding another person to send the message to, not typing the message. For example if I would like to load up to a specific row on my UIPicker on startup I would:
[picker selectRow:3 inComponent:0 animated:NO];
sms load up:
- (IBAction)sms {
MFMessageComposeViewController *textComposer = [[MFMessageComposeViewController alloc] init];
[textComposer setMessageComposeDelegate:self];
if ([MFMessageComposeViewController canSendText]) {
[textComposer setRecipients:[NSArray arrayWithObjects: #"support#nicmacengineering.com", nil]];
[textComposer setBody:#""];
[self presentViewController:textComposer animated:YES completion:NULL];
} else {
NSLog(#"Can't Open Text");
}
}
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
switch (result) {
case MessageComposeResultCancelled:
NSLog(#"Cancelled");
break;
case MessageComposeResultFailed:
break;
case MessageComposeResultSent:
break;
default:
break;
}
[self dismissViewControllerAnimated:YES completion:NULL];
}
First, your question is fairly hard to understand. Here's my impression of it:
Can I set the cursor to the message field by default in an SMS controller?
And the answer is:
No.
Since it is an Apple framework, with no public method to switch fields (here's the class reference).
Because of this, you won't be able to automatically set the position of the cursor.

Need help dismissing email composer screen in iOS

I have an app that allows the user to send a test email from their iPhone. My app calls a method to activate the compose mail function like this:
-(void)displayComposerSheet
{
//set up a way to cancel the email here
//picker is an instance of MSMailComposeViewController already declared in the .h file
[picker setSubject:#"Test Mail"];
// Set up recipients
// Attach an image to the email
NSString *path = [[NSBundle mainBundle] pathForResource:#"Icon" ofType:#"png"];
NSData *myData = [NSData dataWithContentsOfFile:path];
[picker addAttachmentData:myData mimeType:#"image/png" fileName:#"Icon"];
// Fill out the email body text
NSString *emailBody = #"This is a test mail.";
[picker setMessageBody:emailBody isHTML:NO];
[self presentModalViewController:picker animated:YES];
NSLog(#"mail is working");
}
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error
{
emailLabel.hidden = NO;
// Notifies users about errors associated with the interface
switch (result)
{
case MFMailComposeResultCancelled:
emailLabel.text = #"Mail sending canceled.";
break;
case MFMailComposeResultSaved:
emailLabel.text = #"Mail saved.";
break;
case MFMailComposeResultSent:
{
emailLabel.text = #"Mail sent.";
NSLog(#"It's away!");
UIAlertView *emailAlertView = [[UIAlertView alloc] initWithTitle:#"Sent!" message:#"Mail sent successfully." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[emailAlertView show];
[self dismissModalViewControllerAnimated:YES];
[self.navigationController popViewControllerAnimated:YES];
}
break;
case MFMailComposeResultFailed:
{
emailLabel.text = #"Mail sending failed.";
}
break;
default:
{
emailLabel.text = #"Mail not sent.";
}
break;
}
}
My problem is that when the compose email function is active, I am unable to come out of this function and return to my app. The only way out of this is by actually going ahead and sending a message. There is a default "cancel" bar button that appears on the top left hand corner of the navigation bar, which when clicked, gives me three options: "delete draft", "save draft", and "cancel". If I select "delete draft", it does nothing except to return me to the compose message screen. Is there a way for me to allow the user to return to the app after starting the compose mail function, but prior to sending it? Is there a way to add extra functionality to the "cancel" bar button to accomplish this?
Thanks in advance to all who reply.
You have to implement MFMessageComposeViewControllerDelegate with the - (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result method.
You will dismiss your message view in this method.
EDIT : i confused with MFMailComposeViewControllerDelegate but the purpose is the same as with MFMessageComposeViewControllerDelegate
Take a look at your own code in your ...didFinishWithResult: method:
case MFMailComposeResultCancelled:
emailLabel.text = #"Mail sending canceled.";
break;
case MFMailComposeResultSaved:
emailLabel.text = #"Mail saved.";
break;
case MFMailComposeResultSent:
{
emailLabel.text = #"Mail sent.";
NSLog(#"It's away!");
UIAlertView *emailAlertView = [[UIAlertView alloc] initWithTitle:#"Sent!" message:#"Mail sent successfully." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[emailAlertView show];
[self dismissModalViewControllerAnimated:YES];
[self.navigationController popViewControllerAnimated:YES];
}
When the result is MFMailComposeResultSent you're dismissing the modal view controller and popping the nav stack, which causes the mail compose view controller to go away, and also pops the stack to remove the view controller that presented the compose view controller. When the result is MFMailComposeResultCancelled, however, you just set some label's text. Same for MFMailComposeResultSaved. You need to dismiss the message compose view controller for these cases too if you want the compose view controller to go away when the user cancels or saves.
You should add this method in your view controller
- (void)mailComposeController:(MFMailComposeViewController*)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError*)error {
[self becomeFirstResponder];
[self dismissViewControllerAnimated:YES completion:nil];
}
hope this one helps some one.
Set Delegate of MFMailComposeViewController
MFMailComposeViewController *mailcomposer = [[MFMailComposeViewController alloc]init];
mailcomposer.mailComposeDelegate = self;
And Use this Delegate Method
-(void)mailComposeController:(MFMailComposeViewController *)controller didFinishWithResult:(MFMailComposeResult)result error:(NSError *)error

Resources