How to share local var in different view in Objective-C - ios

I am making casual game now.
I'd like to share the score with twitter.
My this work image is that below.
1.After game player plays the game and there is the score.
2.When the game goes to gameoverscene, they can push twitter button (using social.framework)
3. There is a text like "You got xx score !!" in the twitterdisplay(modal).
*I would like to change xx to the shared score.
Could you please give me some advices to do that ?
I am a beginner of Objective - C. So, easy way is better for me.
Little by little, I'd like to concern about security and scalability.
[Information]
*MainScene and GameOverScene are made from SKScene
MainScene.m
#implementation MainScene {
//The score
NSInteger _score;
}
- (void)incrementScore
{
_score++;
}
GameOverScene.m
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if([node.name isEqualToString:#"twitterbutton"]){
NSLog(#"self.delegate = %#",self.delegate);
[self.delegate showShareScreen];
//delegate to ViewController
if (nil == self.delegate) NSLog(#"delegate is nil");
}
}
ViewController.m
-(void)showShareScreen
{
NSLog(#"showShareScreen");
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
SLComposeViewController *tweetSheet = [SLComposeViewController
composeViewControllerForServiceType:SLServiceTypeTwitter];
tweetSheet.modalPresentationStyle = UIModalPresentationFormSheet;
tweetSheet.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[tweetSheet setInitialText:#"You got xx score"];
NSLog(#"self = %#",self);
[self presentViewController:tweetSheet animated:YES completion:nil];
}
else {
NSLog(#"not sls type twitter");
}
}

Change your line in delegate method in ViewController
[tweetSheet setInitialText:#"You got xx score"];
to as shown below; to include the score with a NSString's stringWithFormat: method
-(void)showShareScreenWithScore:(NSInteger) score {
NSLog(#"showShareScreen");
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeTwitter])
{
SLComposeViewController *tweetSheet = [SLComposeViewController
composeViewControllerForServiceType:SLServiceTypeTwitter];
tweetSheet.modalPresentationStyle = UIModalPresentationFormSheet;
tweetSheet.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[tweetSheet setInitialText:[NSString stringWithFormat:#"You got %d score",score]];
NSLog(#"self = %#",self);
[self presentViewController:tweetSheet animated:YES completion:nil];
}
else {
NSLog(#"not sls type twitter");
}
}
And from GameOverScene call this delegate method.
Note: When you are creating Game over scene at that time after object instantiation you can set the property of GameOverScene. So just declare a property
#property (assign , nonatomic) NSInteger score;
and set its value Using NSURLSession that the game is getting over. And score value you can get from MainScene score property.
NSURLSession
The NSURLSession class and related classes provide an API for
downloading content via HTTP. This API provides a rich set of delegate
methods for supporting authentication and gives your app the ability
to perform background downloads when your app is not running or, in
iOS, while your app is suspended.

Related

Game Center Sandbox mode display multiple leaderboards

I'm preparing to launch my first app and want to have multiple leaderboards inside my game. Currently in sandbox mode I can track and log scores into Game Center successfully. Game Center saves my scores (only if it is higher) and seems to be fully functional.
I know through Itunes Connect we have the ability to set up multiple leaderboards and it seems pretty straight forward. I still want to be able to test multiple leaderboards before publishing my game though. Is there a way to do this in sandbox mode? Currently it seems like my scores are only automatically logged into a default leaderboard. Below is the relevant code I'm using to save/access scores. Thanks!
ABGameKitHelper.m
#pragma mark - Leaderboard
-(void) reportScore:(long long)aScore forLeaderboard:(NSString*)leaderboardId
{
GKScore *score = [[GKScore alloc] initWithCategory:leaderboardId];
score.value = aScore;
[score reportScoreWithCompletionHandler:^(NSError *error) {
if (!error)
{
if(![self hasConnectivity])
{
[self cacheScore:score];
}
if (ABGAMEKITHELPER_LOGGING) NSLog(#"ABGameKitHelper: Reported score (%lli) to %# successfully.", score.value, leaderboardId);
}
else
{
[self cacheScore:score];
if (ABGAMEKITHELPER_LOGGING) NSLog(#"ABGameKitHelper: ERROR -> Reporting score (%lli) to %# failed, caching...", score.value, leaderboardId);
}
}];
}
-(void) showLeaderboard:(NSString*)leaderboardId
{
GKLeaderboardViewController *viewController = [GKLeaderboardViewController new];
viewController.leaderboardDelegate = self;
if (leaderboardId)
{
viewController.category = leaderboardId;
CCLOG(#"Going to category already created");
}
[[self topViewController] presentViewController:viewController animated:YES completion:nil];
}
MainScene.m
- (void)gameCenter {
[[ABGameKitHelper sharedHelper] reportScore:1400 forLeaderboard:#"Score"];
[[ABGameKitHelper sharedHelper] showLeaderboard:#"Score"];
}
I'm not sure if I understand your question properly, but I'll try to answer! Game Center does support multiple leaderboards:
-If you want to send a score to specific leaderboard, you just have to call the function [[ABGameKitHelper sharedHelper] reportScore:X forLeaderboard:LEADERBOARD_ID];, where X represents the score you'd like to send, and LEADERBOARD_ID is the ID of the leaderboard you want to send the score to, as specified in iTunes Connect.
-When you have multiple leaderboards, if you don't want to show just one leaderboard, but a list of them all, you should use the GKGameCenterViewController class instead. However, be careful; this ViewController has been added in iOS 6 only, so you must check which version the device is running. I am also using the ABGameKitHelper, so I've made a function to show this kind of view. Here it goes :
ABGameKitHelper.m
- (void) showGameCenter{
if (![[ABGameKitHelper sharedHelper] hasConnectivity]) return;
//Check if device runs on iOS 5
if([[[UIDevice currentDevice]systemVersion]intValue]==5)
{
//If so, we must use the GKLeaderboardViewController
GKLeaderboardViewController *leaderboard = [[GKLeaderboardViewController alloc] init];
if (leaderboard != nil)
{
leaderboard.leaderboardDelegate = self;
[[self topViewController] presentViewController:leaderboard animated:YES completion:nil];
}
}else if ([[[UIDevice currentDevice]systemVersion]intValue]>=6)
{
//if it runs on iOS 6 or higher, we use GKGameCenterViewController
GKGameCenterViewController *gameCenterController = [[GKGameCenterViewController alloc] init];
if (gameCenterController != nil)
{
gameCenterController.gameCenterDelegate = self;
gameCenterController.viewState = GKGameCenterViewControllerStateDefault;
[[self topViewController] presentViewController:gameCenterController animated:YES completion:nil];
}
}
}
And don't forget to add :
- (void) gameCenterViewControllerDidFinish:(GKGameCenterViewController *)gameCenterViewController{
[gameCenterViewController dismissViewControllerAnimated:YES completion:nil];
}
Using this function will allow you to show a nice view containing all your leaderboards and achievements.
Hope this helps!

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.");
}]; }
}

Why SLComposeViewController doesn't have delegate?

Say you want to do something once user finish. What do you do?
It doesn't have a delegate. What to do once a present view controller is dismissed?
In the Apple documentation you'll find that SLComposeViewController has a completion handler property instead of a delegate. You just need to set that property using the setCompletionHandler method. Then you use the constant SLComposeViewControllerResult to recover whether the post was posted or canceled and take action accordingly.
-(void) shareToFacebook {
//1. Set link and image
NSString *appLink = #"https://itunes.apple.com/app/id989793966";
UIImage *twitterImage = [UIImage imageNamed:#"TF_400x400.png"];
//2. Check if we can share
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
//3. Compose the share view controller
SLComposeViewController *FBViewController = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[FBViewController addURL:[NSURL URLWithString:appLink]];
[FBViewController addImage:twitterImage];
//4 Set completion handler and define actions to take
[FBViewController setCompletionHandler:^(SLComposeViewControllerResult result)
{
if (result == SLComposeViewControllerResultCancelled) {
[self addEmptyScreenButtonTargets];
} else if (result == SLComposeViewControllerResultDone) {
//Unlock words; show thank you screen
[NewCardManager unlockWordsForPackage:4];
[self openFBThankYouScreen];
}
}];
//5. Call to modally present the share controller
[self presentViewController:FBViewController animated:YES completion:nil];
}
}

iOS 6 : Game center authentication

I have a problem with the integration of game center in my app' which use iOS 6 SDK.
In fact I use the sample code from Apple, but it looks like incomplete :
I have tried this code :
-(void) authenticateLocalPlayer {
GKLocalPlayer* localPlayer =
[GKLocalPlayer localPlayer];
localPlayer.authenticateHandler =
^(UIViewController *loginVC,
NSError *error) {
[self setLastError:error];
if ([GKLocalPlayer localPlayer].authenticated)
{
// authentication successful
[self enableGameCenterForPlayer:[GKLocalPlayer localPlayer]];
}
else if (loginVC)
{
// player not logged in yet, present the vc
[self pauseGame];
[self presentLoginVC:loginVC];
}
else
{
// authentication failed, provide graceful fallback
[self disableGameCenter];
}
};
}
But the problem is that enableGameCenterForPlayer, pauseGame, presentLoginVC, disableGameCenter are not implemented methods, and it returns :
Instance method '-enableGameCenterForPlayer:' not found (return type defaults to 'id')
How can I fix this problem ?
Thanks
I use the method [self presentLoginVC:VC] to pass my UITabViewController or UINavigationController the viewController because the block below is not on the main thread.
localPlayer.authenticateHandler = ^(UIViewController *loginVC, NSError *error) {
When you are in a block you should be sure not to change UI elements because you really don't know when it will complete or where you will be in your app. There are probably many ways to do this, but this is my solution.
Below is my UITabBarController 'category' .m file (additions of methods for a class without subclassing) I create the method presentLoginVC and just have it call 'showGameCenterViewController' through my UITabBarController:
#import "UITabBarController+GameKitAdditions.h"
#implementation UITabBarController (GameKitAdditions)
-(void) showGameCenterViewController: (UIViewController *)VC {
[self presentViewController:VC animated:NO completion:nil];
}
-(void)dismissGameCenterViewController:(UIViewController *)VC {
[self dismissViewControllerAnimated:YES completion:nil];
}
#end
As to the other functions:
-(void) enableGameCenterForPlayer:(GKLocalPlayer *) localPlayer;
-(void) disableGameCenter;
-(void) pauseGame;
They could be as simple as just setting a BOOL called enableGameCenter to YES or NO. To get around errors you can just add these prototypes to your .h file and then write the functions just to output something to NSLog() or something.

Tutorial for SLComposeViewController sharing [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
What are the steps I need to follow to use iOS 6's new SLComposeViewController to post to Facebook, Twitter or Sina Weibo?
For details on this framework please see Apple's Social Framework Class Reference
Additional tutorials:
http://soulwithmobiletechnology.blogspot.com/2012/07/tutorial-how-to-use-inbuilt.html
http://www.mobile.safilsunny.com/iphone/integrating-facebook-ios/
https://rudeboy-quickies.blogspot.com/2012/06/steps-to-integrate-facebook-in-ios6.html
For this example, we will be using the SLComposeViewController's SLServiceTypeFacebook. If you wish to use Twitter or SinaWeibo just change out the SLServiceType to one of the following:
SLServiceTypeFacebook
SLServiceTypeSinaWeibo
SLServiceTypeTwitter
iOS 6 has made it very easy to post directly to Facebook, Twitter or Sina Weibo using the SLComposeViewController. This works very similarly to iOS 5's TWTweetComposeViewController.
First, in your view controller's header file (.h) #import the Social Framework and the Accounts Framework.
#import <Social/Social.h>
#import <Accounts/Accounts.h>
Here we will declare a simple UIButton and an IBAction that we will later link to that button and a void (sharingStatus) which will be used to check that the selected sharing service is available.
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UIButton *easyFacebookButton;
- (IBAction)facebookPost:(id)sender;
- (void)sharingStatus;
#end
#implementation ViewController
Then, in your implementation file (.m), we'll start by implementing the (sharingStatus) void that we declared in the header file. sharingStatus uses SLComposeViewController's isAvailableForServiceType BOOL to return whether or not you can post to the service specified in its argument. In this case, we will use the service type SLServiceTypeFacebook. If the service is available the post button will be enabled with an alpha value of 1.0f, and if the service isn't available the button will be disabled its alpha value set to 0.5f.
- (void)sharingStatus {
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
NSLog(#"service available");
self.easyFacebookButton.enabled = YES;
self.easyFacebookButton.alpha = 1.0f;
} else {
self.easyFacebookButton.enabled = NO;
self.easyFacebookButton.alpha = 0.5f;
}
}
Here we will set up the IBAction that will call up the composer. For good practice, we will check isAvailableForServiceType again to avoid calling up the composer for a service type that isn't available. (Incase something went wrong during the last check, or if availability somehow changed in the fraction of a second in between tapping the post button and the composers all/init. The code below has been set up to display a Facebook composers sheet with text, an image, and a link. This action also utilises a completion handler for the composer's cancelled and done results.
- (IBAction)facebookPost:(id)sender {
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook]) {
SLComposeViewController *mySLComposerSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[mySLComposerSheet setInitialText:#"iOS 6 Social Framework test!"];
[mySLComposerSheet addImage:[UIImage imageNamed:#"myImage.png"]];
[mySLComposerSheet addURL:[NSURL URLWithString:#"http://stackoverflow.com/questions/12503287/tutorial-for-slcomposeviewcontroller-sharing"]];
[mySLComposerSheet setCompletionHandler:^(SLComposeViewControllerResult result) {
switch (result) {
case SLComposeViewControllerResultCancelled:
NSLog(#"Post Canceled");
break;
case SLComposeViewControllerResultDone:
NSLog(#"Post Sucessful");
break;
default:
break;
}
}];
[self presentViewController:mySLComposerSheet animated:YES completion:nil];
}
}
In viewWillAppear we will register an observer to ACAccountStoreDidChangeNotification so the application can be notified when account information changes. This observer will then be removed in viewDidDisappear.
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(sharingStatus) name:ACAccountStoreDidChangeNotification object:nil];
}
- (void)viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
[[NSNotificationCenter defaultCenter] removeObserver:ACAccountStoreDidChangeNotification];
}
And finally, open up interface builder and add a UIButton which will be the post button. Then in the connections inspector link the IBOutlet and IBAction we created earlier to the button, and that's it! You're done!
Just use this code to share on Facebook.
SLComposeViewController *controllerSLC = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[controllerSLC setInitialText:#"First post from my iPhone app"];
[controllerSLC addURL:[NSURL URLWithString:#"http://www.appcoda.com"]];
[controllerSLC addImage:[UIImage imageNamed:#"test.jpg"]];
[self presentViewController:controllerSLC animated:YES completion:Nil];
If you want this for Twitter then just change SLServiceTypeTwitter.
Safe Use of SLComposeViewController
if ([SLComposeViewController isAvailableForServiceType:SLServiceTypeFacebook])
{
SLComposeViewController *fbPost = [SLComposeViewController
composeViewControllerForServiceType: SLServiceTypeFacebook];
[fbPost setInitialText:#"Text You want to Share"];
[fbPost addImage:[UIImage imageNamed:#"shareImage.png"]];
[self presentViewController:fbPost animated:YES completion:nil];
[fbPost setCompletionHandler:^(SLComposeViewControllerResult result) {
switch (result) {
case SLComposeViewControllerResultCancelled:
NSLog(#"Post Canceled");
break;
case SLComposeViewControllerResultDone:
NSLog(#"Post Sucessful");
break;
default:
break;
}
[self dismissViewControllerAnimated:YES completion:nil];
}];
}

Resources