I have a project that uses the Twitter API to Tweet the users high score. That project is written using Cocos2d v1.1 and everything is working fine. I recently started a new project using Cocos2d v2.0 and attempted to use the same code from my other project to incorporate the same Twitter functionality but the viewcontroller will not appear when the Tweet button is pressed. Below is the code I'm using...
if ([TWTweetComposeViewController canSendTweet]) // Check if twitter is setup and reachable
{
CCLOG(#"Can Tweet");
TWTweetComposeViewController *tweetViewController = [[TWTweetComposeViewController alloc] init];
// set initial text
NSString *theTweet = #"The message..."];
[tweetViewController setInitialText:theTweet];
// setup completion handler
tweetViewController.completionHandler = ^(TWTweetComposeViewControllerResult result) {
if(result == TWTweetComposeViewControllerResultDone) {
// the user finished composing a tweet
} else if(result == TWTweetComposeViewControllerResultCancelled) {
// the user cancelled composing a tweet
}
[viewController dismissViewControllerAnimated:YES completion:nil];
};
// present view controller
[[[CCDirector sharedDirector] openGLView] addSubview:viewController.view];
[viewController presentViewController:tweetViewController animated:YES completion:nil];
}
else
{
// Twitter account not configured, inform the user
NSLog(#"You can't send a tweet right now, make sure your device has an internet connection and you have at least one Twitter account setup");
}
I've discovered that "openGLView" is now depreciated and I have replaced it with "view". This still does not work. The method is firing though. I've included a CCLOG that return the string "Can Tweet" and that is appearing in the output window. Does anyone have any suggestions on how to get this to work. Let me know if I need to provide more information.
Thanks
Use this code in cocos2d 2.0
AppController * app = (((AppController*) [UIApplication sharedApplication].delegate));
TWTweetComposeViewController *tweetViewController = [[TWTweetComposeViewController alloc] init];
[tweetViewController setInitialText:string];
[tweetViewController setCompletionHandler:^(TWTweetComposeViewControllerResult result) {
dispatch_async(dispatch_get_main_queue(), ^{
{
if (result == TWTweetComposeViewControllerResultDone)
{
//successful
[[NSNotificationCenter defaultCenter] postNotificationName:#"PPTweetSuccessful" object:nil];
}
else if(result == TWTweetComposeViewControllerResultCancelled)
{
//Cancelled
}
}
[app.navController dismissModalViewControllerAnimated:YES];
[tweetViewController release];
});
}];
[app.navController presentModalViewController:tweetViewController animated:YES];
Related
Our team manager has proposed the following idea: within our app, when a user taps a Send Msg button, our app opens up the Messages app. Our manager wants to tap Cancel to go back to our app (see screenshot below), instead of the top left Go back to ... shortcut in the status bar. Is that possible?
This is the picture:
UPDATE The messageComposeViewController delegate method is like this, and I see some shaking when I dismiss the message controller?:****
#pragma mark - sms delegate
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller
didFinishWithResult:(MessageComposeResult)result {
switch (result)
{
case MessageComposeResultCancelled:
break;
case MessageComposeResultSent:
break;
case MessageComposeResultFailed:
[LMLSendResultAlert showSuccessOrFail:0 withSuccesString:#"" andFailStr:#"短信发送失败" needPopOrdismiss:0 complete:nil];
break;
default:
break;
}
[controller dismissViewControllerAnimated:YES completion:NULL];
}
This is my viewWillAppear method:
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController.navigationBar setHidden:YES];
}
If you are opening the message editor externally, that is, you just open the default Message app (I guess this is what is happening, otherwise there wouldn't be the Back button at top left corner), unfortunately I'm not aware of any way to go back to your app when clicking the Cancel button.
However, if you are using MFMessageComposeViewController, which probably is a good idea as your users don't have to leave your app, it would be definitely possible to act accordingly when users choose to cancel.
You can take a look at Apple's doc here, which utilizes mailComposeController:didFinishWithResult:error:
- (void)messageComposeViewController:(MFMessageComposeViewController *)controller
didFinishWithResult:(MessageComposeResult)result {
// Check the result or perform other tasks.
// Dismiss the mail compose view controller.
[self dismissViewControllerAnimated:YES completion:nil];
}
Following what Stephenye has said, if you use MFMessageComposeViewController the cancel button will allow you to go back to your app (you will still be in your app anyway because you present the message controller as you present any other view controller).
Here is an example:
-(void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result
{
switch (result)
{
[controller dismissViewControllerAnimated:YES completion:^{
case MessageComposeResultCancelled:
break;
case MessageComposeResultFailed:
[LMLSendResultAlert showSuccessOrFail:0 withSuccesString:#"" andFailStr:#"短信发送失败" needPopOrdismiss:0 complete:nil];
break;
case MessageComposeResultSent:
break;
default:
break;
}
}];
}
-(void)presentMessagerOnViewController:(UIViewController*)controller
{
if(![MFMessageComposeViewController canSendText])
{
//show error message
return;
}
NSArray *recipients = #[#"0424456654"];
NSString *defaulMessage = #"You should absolutely upvote my answer";
MFMessageComposeViewController *composer = [[MFMessageComposeViewController alloc] init];
composer.messageComposeDelegate = self;
[composer setRecipients: recipients];
[composer setBody: defaulMessage];
[self presentViewController: composer animated:YES completion: NULL];
}
I have a simple iOS app which makes use of Game Center. However recently when updating it to iOS 7, I noticed that the authenticate method does not work.
One of the issues is with the code I am using to present the view controller to the user if they need to sign in to game centre, it no longer pops up the game centre login window in the app.
Another issue I have is that I can't find what method to use instead of the deprecated "authenticateWithCompletionHandler".
Here is my code:
-(void)authenticateLocalUser {
GKLocalPlayer.localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error) {
if (GKLocalPlayer.localPlayer.authenticated) {
// Already authenticated
}
else if (viewController) {
[self presentViewController:viewController animated:YES completion:nil];
}
else {
// Problem with authentication, probably bc the user doesn't use Game Center.
}
};
if ([GKLocalPlayer localPlayer].authenticated == NO) {
[[GKLocalPlayer localPlayer] authenticateWithCompletionHandler:^(NSError *error) {
[self callDelegateOnMainThread: #selector(processGameCenterAuth:) withArg:NULL error: error];
}];
}
}
Thanks for your time, Dan.
No matter I managed to figure it out in the end. As for 'authenticateWithCompletionHandler', I used this:
[[[UIApplication sharedApplication] keyWindow].rootViewController presentViewController:viewController animated:YES completion:nil];
I am trying to integrate Game Center for matching players. I am using that very simple function:
- (void)findOpponent {
GKMatchRequest* request = [[GKMatchRequest alloc] init];
request.minPlayers = 2;
request.maxPlayers = 2;
GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc]
initWithMatchRequest:request];
mmvc.matchmakerDelegate = self;
[[self viewController] presentViewController:mmvc animated:YES completion:nil];
}
I do have some callback, never called tho':
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindMatch:(GKMatch *)theMatch {
NSLog(#"he");
[[self viewController] dismissViewControllerAnimated:NO completion:nil];
GKMatch* match = theMatch;
[match setDelegate:self];
NSLog(#"Ready to start match!");
}
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didFindPlayers:(NSArray *)playerIDs {
NSLog(#"Super he");
}
- (void)matchmakerViewController:(GKMatchmakerViewController *)viewController didReceiveAcceptFromHostedPlayer:(NSString *)playerID {
NSLog(#"Wow");
}
When I test onmy device (wether iPhone or iPad), both using iOS 7.1, I can open Game Center from my Application, but as soon as I click on "Play Now" I instantaneously get the error: "Failed to find players". Yet none of my callback seems to get triggered in my code. Any idea of what I am doing wrong? I did try to reset my iPad settings, logging off from iCloud, rebooting my device, etc.
Fixed.
More than creating a Provisioning Profile and enabling Game Center inside, you also need to Add your app on iTunes Connect.
You need to go to an extremely strange process where it ask for the release date of your app, the price, some screen shots and icons, but once done you will be able to enable Game Center for real.
What is the proper way to handle invitations from other players in iOS 7?
After my view did load on my root View Controller, I'm calling a game center authentication method, after that I'm setup a invitation handler like so:
[[GKLocalPlayer localPlayer] registerListener:self];
My view controller adopt GKLocalPlayerListener and GKInviteEventListener protocols, by the way, what is the best place to register a listener AppDelegate? Maybe or maybe my custom Game Center singleton?
I add a method described in GKInviteEventListener
-(void)player:(GKPlayer *)player didAcceptInvite:(GKInvite *)invite
{
NSLog(#"Invite accepted!");
GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc] initWithInvite:invite];
mmvc.matchmakerDelegate = self;
[self presentViewController:mmvc animated:YES completion:nil];
}
But, game center matchmaker class have such topic: Receiving Invitations From Other Players and method – matchForInvite:completionHandler:
I don't understand how to use it.
So, what I must use and how?
I think you're doing things correctly. I did things the same way, and it works for me. -matchForInvite:completionHandler is deprecated in iOS 7, so I don't do anything with it.
First I set the authentication handler. This is called when my app loads for the first time, you can set it anywhere you like, but it is best to set the handler as soon as possible.
-(void)authenticateLocalPlayer
{
GKLocalPlayer *localPlayer = [GKLocalPlayer localPlayer];
__weak GKLocalPlayer *blockLocalPlayer = localPlayer;
//Block is called each time GameKit automatically authenticates
localPlayer.authenticateHandler = ^(UIViewController *viewController, NSError *error)
{
[self setLastError:error];
if (viewController)
{
self.authenticationViewController = viewController;
[self disableGameCenter];
}
else if (blockLocalPlayer.isAuthenticated)
{
[self authenticatedPlayer:blockLocalPlayer];
}
else
{
[self disableGameCenter];
}
};
}
If authentication is successful, then I call this method:
-(void)authenticatedPlayer:(GKLocalPlayer*)localPlayer
{
self.isAuthenticated = YES;
[[NSNotificationCenter defaultCenter]postNotificationName:AUTHENTICATED_NOTIFICATION object:nil];
[[GKLocalPlayer localPlayer]registerListener:self];
}
Then I implemented the two listener methods:
(void)player:(GKPlayer *)player didAcceptInvite:(GKInvite *)invite
{
//.... insert some cleanup code here to manage view controllers etc before presenting the matchmakerviewcontroller.
[self presentMatchmakerViewControllerWithInvite:invite];
}
-(void)player:(GKPlayer *)player didRequestMatchWithPlayers:(NSArray *)playerIDsToInvite
{
//......insert some cleanup code for managing view controllers
GKMatchRequest *match = [[GKMatchRequest alloc]init];
match.playersToInvite = playerIDsToInvite;
GKMatchmakerViewController *mmvc = [[GKMatchmakerViewController alloc]initWithMatchRequest:match];
mmvc.matchmakerDelegate = root.viewControllers[0];
[[[[[UIApplication sharedApplication]delegate]window]rootViewController]presentViewController:mmvc animated:YES completion:nil];
}
I call Chartboost interstitial at applicationDidBecomeActive. My game use s Game Center and sometimes GC authorization window pops up under Chartboost interstitial, blocking Chartboost window. Only solution is switch to GameCenter and login there. Is it possible to check what authorization window was shown?
Blocking ads when Game Center login is on screen might be an option! Code works only on iOS6 btw
#interface ChartboostBridge : NSObject<ChartboostDelegate>
#end
#implementation ChartboostBridge
- (BOOL)shouldDisplayInterstitial:(NSString *)location{
NSLog(#"CB shouldDisplayInterstitial for %#",location);
if ([location isEqualToString:#"game_launch"]) {
if( [[GameCenterIos shared ] hasLogInView] ){
return NO;
}
}
return YES;
}
#end
#implementation GameCenterIos
- (BOOL)hasLogInView{
return isViewOnScreen;
}
- (void)login
{
GKLocalPlayer* localPlayer = [GKLocalPlayer localPlayer];
if (localPlayer.isAuthenticated) {
isViewOnScreen=NO;
return;
}
localPlayer.authenticateHandler =
^(UIViewController *viewController,
NSError *error) {
if (localPlayer.authenticated) {
isAuthenticated = YES;
isViewOnScreen=NO;
} else if(viewController) {
NSLog(#"Game Center shows login ....");
isViewOnScreen=YES;
[self presentViewController:viewController];
} else {
NSLog(#"Game Center error or canceled login ....");
//User canceled Login view
isAuthenticated = NO;
isViewOnScreen=NO;
}
};
}
#pragma mark UIViewController stuff
-(UIViewController*) getRootViewController {
return [UIApplication
sharedApplication].keyWindow.rootViewController;
}
-(void)presentViewController:(UIViewController*)vc {
UIViewController* rootVC = [self getRootViewController];
[rootVC presentViewController:vc animated:YES
completion:nil];
}
#end
This is and old question but I just had the same problem and found a workaround.
Change the modalPresentationStyle of the gamecenter loggin view (returned by the ios 6 authentication handler) to UIModalPresentationFullScreen.
On iphone the screen doesn't lock when gamecenter loggin and chartboost interstitial appear. Only on Ipad happens. And whats the difference? that in ipad the loggin is not fullscreen. So I tested changing it to fullscreen and now it works without locking =)