Save the Hidden State of A UIButton - uibutton

I have a UISwitch that on Value Change, hides or unhides some UIButtons with an if statement. I would like the hidden state of the UIButtons to be saved when I switch views or exit the app. I have tried using NSUserDefaults but it does not save, it just reverts back to the state I had originally set in the .storyboard
.m code:
- (IBAction)buttonHidden:(id)sender {
NSUserDefaults *Defaults = [NSUserDefaults standardUserDefaults];
[Defaults setBool:china.hidden forKey:ChinaChanged];
[Defaults setBool:japan.hidden forKey:JapanChanged];
[Defaults setBool:french.hidden forKey:FrenchChanged];
[Defaults setBool:spanish.hidden forKey:SpanishChanged];
[Defaults synchronize];
}
.m viewDidLoad code:
- (void)viewDidLoad {
[super viewDidLoad];
NSUserDefaults *Defaults = [NSUserDefaults standardUserDefaults];
china.hidden = [Defaults boolForKey:ChinaChanged];
japan.hidden = [Defaults boolForKey:JapanChanged];
french.hidden = [Defaults boolForKey:FrenchChanged];
spanish.hidden = [Defaults boolForKey:SpanishChanged];
}
I do not know where I can connect the IBAction to make it work.
This is my if statement code for the UISwitch:
(IBAction)switchTheSwitch:(id)sender {
if (Languages.on) {
china.hidden = NO;
japan.hidden = NO;
french.hidden = NO;
spanish.hidden = NO;
}
else {
china.hidden = YES;
japan.hidden = YES;
french.hidden = YES;
spanish.hidden = YES;
}
}
Can anyone help me.

im not sure I follow but to me it seems all you lack is a call to buttonHidden so that defaults get actually saved
just do
-(IBAction)switchTheSwitch:(id)sender {
if (Languages.on) {
china.hidden = NO;
japan.hidden = NO;
french.hidden = NO;
spanish.hidden = NO;
}
else {
china.hidden = YES;
japan.hidden = YES;
french.hidden = YES;
spanish.hidden = YES;
}
[self buttonHidden:sender];
}

Related

I want to stay on logout page, when application runs again (if user did not hit logout button)

Below is my code till sign in process
#import "ViewController.h"
#import "LogOutViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *userid = [defaults objectForKey:#"uid"];
NSString *password = [defaults objectForKey:#"pswrd"];
_lbluserid.text = userid;
_lblpswrd.text = password;
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)btnsignin:(id)sender
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:_lbluserid.text forKey:#"uid"];
[defaults setObject: _lblpswrd.text forKey:#"pswrd"];
[defaults synchronize];
NSLog(#"Credentials are saved");
LogOutViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"logoutvc"];
controller.getUserid = _lbluserid.text;
[self.navigationController pushViewController:controller animated:YES];
}
#end
I have another view which will appear by signing in, on that view I have Log Out button, Now what I want is if user didn't hit logout button the same page (log out page) will be displayed when I run my app again.
Please help me..
try amend you code to.
#import "ViewController.h"
#import "LogOutViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *userid = [defaults objectForKey:#"uid"];
NSString *password = [defaults objectForKey:#"pswrd"];
_lbluserid.text = userid;
_lblpswrd.text = password;
if([defaults boolForKey:#"logedIn"]){
[self moveToLogoutViewController];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)btnsignin:(id)sender
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:_lbluserid.text forKey:#"uid"];
[defaults setObject: _lblpswrd.text forKey:#"pswrd"];
[defaults setBool: YES forKey:#"logedIn"];
[defaults synchronize];
NSLog(#"Credentials are saved");
[self moveToLogoutViewController];
}
- (void) moveToLogoutViewController{
LogOutViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"logoutvc"];
controller.getUserid = _lbluserid.text;
[self.navigationController pushViewController:controller animated:YES];
}
#end
You can try like this
First Open AppDelegate class in didFinishLaunchingWithOptions method.
Check user is exist or not by using NSUserDefaults.If user exist you can show LogOutViewController
Use keychain to store user credentials. In your viewCOntroller class, in viewDidLoad check if user credentials exist or not.If exist, then call:
LogOutViewController *controller = [self.storyboard instantiateViewControllerWithIdentifier:#"logoutvc"];
controller.getUserid = //get user id from keychain;
[self.navigationController pushViewController:controller animated:YES];

AVAudioPlayer for Sprite Kit

I'm utilizing AVAudioPlayer in MyScene - the main game scene in my Sprite Kit game. I also have an OptionsScene containing 2 buttons. 1 of the buttons is for switching music ON/OFF.
Everything works except pressing the button doesn't instantly turn music ON or OFF. I have to leave the app, double-tap iPhone's Home button & swipe-up the game View to turn it off completely.
Once that is done, I can open the game & the previously selected ON/OFF button takes effect. Is there a way to have AVAudioPlayer turn off instantly upon clicking it's button in the options scene?
I do use a custom class for playing the music that I did not write. So I don't completely understand how it works. Here is the method I use inside MyScene to activate the AVAudioPlayer:
-(void)musicPlayer
{
defaults = [NSUserDefaults standardUserDefaults]; //"Activate" defaults.
music = [defaults boolForKey:#"MusicButtonKEY"]; //Then assign that defaults to a BOOL (music in this case).
if (music == YES) //Check what defaults BOOL key value was set to & act accordingly to that.
{
[self.audioController tryPlayMusic]; //tryPlayMusic is a method from AudioController class.
NSLog(#"Music playing");
}
else /*if (music == NO)*/
{
[self.audioController stopPlayingMusic]; //stopPlayingMusic is a method from AudioController class.
NSLog(#"Music not playing");
}
}
Here is the .h & .m files of the AudioController class:
AudioController.h
#import <Foundation/Foundation.h>
#interface AudioController : NSObject
-(instancetype)init;
-(void)tryPlayMusic;
-(void)stopPlayingMusic;
#end
AudioController.m
#import "AudioController.h"
#import AVFoundation;
#interface AudioController () <AVAudioPlayerDelegate>
#property (strong, nonatomic) AVAudioSession *audioSession;
#property (strong, nonatomic) AVAudioPlayer *backgroundMusicPlayer;
#property (assign) BOOL backgroundMusicPlaying;
#property (assign) BOOL backgroundMusicInterrupted;
#end
#implementation AudioController
#pragma mark - Public
-(instancetype)init
{
self = [super init];
if (self)
{
[self configureAudioSession];
[self configureAudioPlayer];
}
return self;
}
-(void)tryPlayMusic
{
//If background music or other music is already playing, nothing more to do here
if (self.backgroundMusicPlaying || [self.audioSession isOtherAudioPlaying])
{
return;
}
// Play background music if no other music is playing and we aren't playing already
//Note: prepareToPlay preloads the music file and can help avoid latency. If you don't
//call it, then it is called anyway implicitly as a result of [self.backgroundMusicPlayer play];
//It can be worthwhile to call prepareToPlay as soon as possible so as to avoid needless
//delay when playing a sound later on.
[self.backgroundMusicPlayer prepareToPlay];
[self.backgroundMusicPlayer play];
self.backgroundMusicPlaying = YES;
}
-(void)stopPlayingMusic
{
if (self.backgroundMusicPlaying == YES)
{
[self.backgroundMusicPlayer stop];
self.backgroundMusicPlaying = NO;
}
}
#pragma mark - Private
-(void)configureAudioSession
{
//Implicit initialization of audio session.
self.audioSession = [AVAudioSession sharedInstance];
//Set category of audio session
//See handy chart on pg. 46 of the Audio Session Programming Guide for what the categories mean
//Not absolutely required in this example, but good to get into the habit of doing
//See pg. 10 of Audio Session Programming Guide for "Why a Default Session Usually Isn't What You Want"
NSError *setCategoryError = nil;
if ([self.audioSession isOtherAudioPlaying])
{ //Mix sound effects with music already playing
[self.audioSession setCategory:AVAudioSessionCategorySoloAmbient error:&setCategoryError];
self.backgroundMusicPlaying = NO;
}
else
{
[self.audioSession setCategory:AVAudioSessionCategoryAmbient error:&setCategoryError];
}
if (setCategoryError)
{
NSLog(#"Error setting category! %ld", (long)[setCategoryError code]);
}
}
-(void)configureAudioPlayer
{
//Create audio player with background music.
NSString *backgroundMusicPath = [[NSBundle mainBundle] pathForResource:#"ThemeA" ofType:#"mp3"];
NSURL *backgroundMusicURL = [NSURL fileURLWithPath:backgroundMusicPath];
self.backgroundMusicPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:backgroundMusicURL error:nil];
self.backgroundMusicPlayer.delegate = self; //We need this so we can restart after interruptions
self.backgroundMusicPlayer.numberOfLoops = -1; //Negative number means loop forever
}
#pragma mark - AVAudioPlayerDelegate methods
-(void)audioPlayerBeginInterruption:(AVAudioPlayer *)player
{
//It is often not necessary to implement this method since by the time
//this method is called, the sound has already stopped. You don't need to
//stop it yourself.
//In this case the backgroundMusicPlaying flag could be used in any
//other portion of the code that needs to know if your music is playing.
self.backgroundMusicInterrupted = YES;
self.backgroundMusicPlaying = NO;
}
-(void)audioPlayerEndInterruption:(AVAudioPlayer *)player withOptions:(NSUInteger)flag
{
//Since this method is only called if music was previously interrupted, you know that the music has stopped playing & can now be resumed.
[self tryPlayMusic];
self.backgroundMusicInterrupted = NO;
}
#end
Here is the button code from OptionsScene:
#import "OptionsScene.h"
#import "ViewController.h"
BOOL soundON;
BOOL musicON;
#interface OptionsScene ()
#property (strong, nonatomic) AGSpriteButton *AGSoundButton;
#property (strong, nonatomic) AGSpriteButton *AGMusicButton;
#end
#implementation OptionsScene
{
NSUserDefaults *defaults;
}
-(id)initWithSize:(CGSize)size
{
self = [super initWithSize:size];
{
defaults = [NSUserDefaults standardUserDefaults];
[self background]; //Won't show code for this method since it just loads the background.
//Background music & sound dispatched once to get things going in this scene so to speak.
static dispatch_once_t onceOS;
dispatch_once(&onceOS, ^ {
//Code to run once
soundON = YES;
musicON = YES;
[defaults setBool:YES forKey:#"SoundButtonKEY"];
[defaults synchronize];
self.AGSoundButton.texture = [SKTexture textureWithImageNamed:#"checkboxYES"];
NSLog(#"SOUND switched to ON");
[defaults setBool:YES forKey:#"MusicButtonKEY"];
[defaults synchronize];
self.AGMusicButton.texture = [SKTexture textureWithImageNamed:#"checkboxYES"];
NSLog(#"MUSIC switched to ON");
});
}
return self;
}
-(void)update:(NSTimeInterval)currentTime
{
}
-(void)didMoveToView:(SKView *)view
{
//Sound button.
self.AGSoundButton = [AGSpriteButton buttonWithImageNamed:#"checkboxYES"];
self.AGSoundButton.position = CGPointMake(self.size.width/2 + 50, self.size.height/2 + 70);
self.AGSoundButton.zPosition = 2.2;
[self.AGSoundButton addTarget:self selector:#selector(soundInit) withObject:[NSValue valueWithCGPoint:CGPointMake(self.size.width + 230, self.size.height/2 + 3)] forControlEvent:AGButtonControlEventTouchUpInside];
[self addChild:self.AGSoundButton];
//Music button.
self.AGMusicButton = [AGSpriteButton buttonWithImageNamed:#"checkboxYES"];
self.AGMusicButton.position = CGPointMake(self.size.width/2 + 50, self.size.height/2 + 10);
self.AGMusicButton.zPosition = 2.2;
[self.AGMusicButton addTarget:self selector:#selector(musicInit) withObject:[NSValue valueWithCGPoint:CGPointMake(self.size.width + 230, self.size.height/2 + 3)] forControlEvent:AGButtonControlEventTouchUpInside];
[self addChild:self.AGMusicButton];
//Call upon the saved BOOL/Button positions from their respective key's.
BOOL soundDefaults = [defaults boolForKey:#"SoundButtonKEY"];
BOOL musicDefaults = [defaults boolForKey:#"MusicButtonKEY"];
//Sound button retrieval.
if (soundDefaults == YES)
{
self.AGSoundButton.texture = [SKTexture textureWithImageNamed:#"checkboxYES"];
NSLog(#"Sound is ON");
}
if (soundDefaults == NO)
{
self.AGSoundButton.texture = [SKTexture textureWithImageNamed:#"checkboxNO"];
NSLog(#"Sound is OFF");
}
//Music button retrieval.
if (musicDefaults == YES)
{
self.AGMusicButton.texture = [SKTexture textureWithImageNamed:#"checkboxYES"];
NSLog(#"Music is ON");
}
if (musicDefaults == NO)
{
self.AGMusicButton.texture = [SKTexture textureWithImageNamed:#"checkboxNO"];
NSLog(#"Music is OFF");
}
}
//Sound button switch ON/OFF.
-(void)soundInit
{
if (soundON == YES)
{
soundON = NO;
[defaults setBool:NO forKey:#"SoundButtonKEY"];
[defaults synchronize];
self.AGSoundButton.texture = [SKTexture textureWithImageNamed:#"checkboxNO"];
NSLog(#"SOUND switched to OFF");
}
else /*if (soundON == NO)*/
{
soundON = YES;
[defaults setBool:YES forKey:#"SoundButtonKEY"];
[defaults synchronize];
self.AGSoundButton.texture = [SKTexture textureWithImageNamed:#"checkboxYES"];
NSLog(#"SOUND switched to ON");
}
}
//Music button switch ON/OFF.
-(void)musicInit
{
if (musicON == YES)
{
musicON = NO;
[defaults setBool:NO forKey:#"MusicButtonKEY"];
[defaults synchronize];
self.AGMusicButton.texture = [SKTexture textureWithImageNamed:#"checkboxNO"];
NSLog(#"MUSIC switched to OFF");
}
else /*if (musicON == NO)*/
{
musicON = YES;
[defaults setBool:YES forKey:#"MusicButtonKEY"];
[defaults synchronize];
self.AGMusicButton.texture = [SKTexture textureWithImageNamed:#"checkboxYES"];
NSLog(#"MUSIC switched to ON");
}
}
//Brings back to GameScene. Called by a 3rd button that I didn't bother including in this code. It doesn't really matter.
-(void)backToGame
{
NSLog(#"Going back");
[defaults synchronize]; //Save button states, just in case, before leaving scene.
//Brings back to game scene.
MyScene *firstScene = [MyScene sceneWithSize:self.size];
[self.view presentScene:firstScene];
}
#end
Really hope this helps with the details.

NSButton Toggle Button change programmatically

I have an NSButton set as a toggle (on/off) in my application. When I click the button it works fine, but when I try and programmatically set it using [toggleButton setEnabled:YES]; it has no effect.
code:
- (void)awakeFromNib {
defaults = [NSUserDefaults standardUserDefaults];
NSString *toggleValue = [[NSUserDefaults standardUserDefaults] objectForKey:#"toggleActive"];
if (toggleValue == nil) toggleValue = #"YES";
if ([toggleValue isEqualToString:#"YES"]) {
[defaults setObject:#"YES" forKey:#"toggleActive"];
isOn = YES;
[toggleButton setEnabled:YES];
}
if ([toggleValue isEqualToString:#"NO"]) {
[defaults setObject:#"NO" forKey:#"toggleActive"];
isOn = NO;
[toggleButton setEnabled:NO];
}
[[NSUserDefaults standardUserDefaults] synchronize];
}
- (IBAction)toggleButton:(id)sender {
if( isOn ) {
[self stopFunction: (NSButton *)sender];
isOn = NO;
[defaults setObject:#"NO" forKey:#"toggleActive"];
} else {
[self startFunction (NSButton *)sender];
isOn = YES;
[defaults setObject:#"YES" forKey:#"toggleActive"];
}
[[NSUserDefaults standardUserDefaults] synchronize];
}
*toggleActive YES or NO get's stored in NSUserDefaults (which works fine); I'm wanting to remember the last button state when the user re-opens the application.
setEnabled: only changes the availability of the button to user interaction
The following will switch the button's image along with setting the button's state to on/off
[toggleButton setState:NSOnState];
[toggleButton setState:NSOffState];
If you would like to have the appropriate action to be taken along with the state change, you will have to call the appropriate functions as well
[toggleButton setState:NSOnState];
[self startFunction:toggleButton];
Alternatively, you can call
[toggleButton performClick:self];
However, this will cause a brief aqua blue shading of the button (like you are actually clicking on it) while it switches state. I prefer the former method on account of this.
All this is just made on some quick observations I made a little while ago, while trying to do the same thing (googling brought me to this thread). Hope this helps :)

Checkbox go to another view controller objective c

I am trying to create a checkbox button, when the user click on that button it will check in and take him to another view controller. below is my checkbox code, can anyone help how can send the user to the other view controller?
Note I am using a storybored.
The header
IBOutlet UIButton *Checkbox;
BOOL checked;
(IBAction)CheckboxAction:(id)sender;
and here is the code:
- (void)viewDidLoad : (BOOL)animated
{NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
checked = [defaults boolForKey:#"boxIsChecked"];
[self checkTheBox];}
-(void) checkTheBox
{
if (!checked)
{[Checkbox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];}
else if (checked)
{[Checkbox setImage:[UIImage imageNamed:#"checkBoxMarked.png"] forState:UIControlStateNormal];}
}
- (IBAction)CheckboxAction:(id)sender
{NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (!checked)
{[Checkbox setImage:[UIImage imageNamed:#"checkBoxMarked.png"] forState:UIControlStateNormal];
checked = YES;
[defaults setBool:checked forKey:#"boxIsChecked"];}
else if (checked)
{[Checkbox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
checked = NO;
[defaults setBool:checked forKey:#"boxIsChecked"];}
[defaults synchronize];
}
- (IBAction)CheckboxAction:(id)sender {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if (!checked) {
[Checkbox setImage:[UIImage imageNamed:#"checkBoxMarked.png"] forState:UIControlStateNormal];
checked = YES;
[defaults setBool:checked forKey:#"boxIsChecked"];
}
else if (checked) {
[Checkbox setImage:[UIImage imageNamed:#"checkBox.png"] forState:UIControlStateNormal];
checked = NO;
[defaults setBool:checked forKey:#"boxIsChecked"];
}
[defaults synchronize];
// ADD THIS
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
YourViewController *yourVC = (YourViewController *)[storyboard instantiateViewControllerWithIdentifier:#"YourViewControllerIdentifier"];
[self.navigationController pushViewController:yourVC animated:YES];
}

Facebook SDK Singleton in xcode auto login before post?

I have had the Facebook SDK working in the APPDelegate as instructed by the Facebook tutorial, however I am trying to put in into a singleton method. Every tutorial i've found seems to be for an older version of the SDK, but I have managed success with this one http://indiedevstories.com/2011/08/30/a-facebook-reusable-class/
I'm having 2 problems, the first is posted here this is the second:
I want a button to post to Facebook, but if the user isn't logged in then they need to login first then post (without having to press a separate login button first).
I can log in fine, and I can post fine, however I can't do both together.
If not logged in, the post code shows the login screen, but doesn't goto the post screen after logging in. you have to press post again.
If you try to login but are already logged in, then nothing happens.
So on the button I use code to login then post, as the login is just skipped if already logged in.
The problem i'm having, is the post code is being run instantly after the login code, so before the user has had a chance to login. This results in 2 popups being opened (1 login and 1 post which displays login as not logged in yet).
How can I get my code to wait for the user to login before moving onto the next line in the code to post?
FacebookHelper.h
#interface FacebookHelper : NSObject <FBSessionDelegate, FBRequestDelegate, FBDialogDelegate, FBLoginDialogDelegate> {
Facebook *_facebook;
NSArray *_permissions;
}
#property (nonatomic,strong) Facebook *facebook;
+(FacebookHelper *) sharedInstance;
+(void)fbDidLogin;
#pragma mark - Public Methods
-(BOOL) isFBSessionValid;
-(void) login;
-(void) logout;
-(void) postToWallWithDialogNewHighscore:(int)highscore;
#end
FacebookHelper.m
#implementation FacebookHelper
#synthesize facebook;
#pragma mark -
#pragma mark Singleton Variables
static FacebookHelper *singletonDelegate = nil;
#pragma mark -
#pragma mark Singleton Methods
+(FacebookHelper *)sharedInstance
{
#synchronized(self) {
if (singletonDelegate == nil) {
singletonDelegate = [[self alloc] init]; // Assignment not done here
}
}
return singletonDelegate;
}
-(id)init
{
self = [super init];
if (self) {
_facebook = [[Facebook alloc] initWithAppId:kAppId andDelegate:self];
// Restore previous session
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"] && [defaults objectForKey:#"FBExpirationDateKey"]) {
_facebook.accessToken = [defaults objectForKey:#"FBAccessTokenKey"];
_facebook.expirationDate = [defaults objectForKey:#"FBExpirationDateKey"];
}
//
}
return self;
}
+(id)allocWithZone:(NSZone *)zone
{
#synchronized(self) {
if (singletonDelegate == nil) {
singletonDelegate = [super allocWithZone:zone];
// assignment and return on first allocation
return singletonDelegate;
}
}
//on subsequent allocation attemps, return nil
return nil;
}
-(id)copyWithZone:(NSZone *)zone
{
return self;
}
#pragma mark - Facebook Delegate Methods
-(void)fbDidLogin
{
NSLog(#"fbDidLogin");
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[_facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[_facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
-(void)fbDidLogout
{
NSLog(#"fbDidLogout");
// Remove saved authorisation information if it exists
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
if ([defaults objectForKey:#"FBAccessTokenKey"]) {
[defaults removeObjectForKey:#"FBAccessTokenKey"];
[defaults removeObjectForKey:#"FBExpirationDateKey"];
[defaults synchronize];
}
}
#pragma mark - Public Methods
-(NSMutableDictionary *) buildPostParamsWithHighScore:(int)highscore
{
NSString *customMessage = [NSString stringWithFormat:kCustomMessage, highscore, kAppName];
NSString *postName = kAppName;
NSString *serverLink = [NSString stringWithFormat:kServerLink];
NSString *imageSrc = kImageScr;
//Final params build
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
//#"message", #"message",
imageSrc, #"picture",
serverLink, #"link",
postName, #"name",
#" ", #"caption",
customMessage, #"description",
nil];
return params;
}
-(BOOL) isFBSessionValid
{
// Check if there is a valid session
//_facebook = [[Facebook alloc] initWithAppId:kAppId andDelegate:self];
_facebook.accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:#"FBAccessTokenKey"];
_facebook.expirationDate = [[NSUserDefaults standardUserDefaults] objectForKey:#"FBExpirationDateKey"];
NSLog(#"accessToken=%# expirationDaate=%#",_facebook.accessToken,_facebook.expirationDate);
if (![_facebook isSessionValid]) {
NSLog(#"FacebookHelper isFBSessionValid = NO");
return NO;
} else {
NSLog(#"FacebookHelper isFBSessionValid = YES");
return YES;
}
return NO;
}
-(void) login
{
NSLog(#"FacebookHelper login");
_permissions = [NSArray arrayWithObjects:#"publish_stream", nil]; //#"read_stream", #"offline_access"
[_facebook authorize:_permissions];
}
-(void) logout
{
[_facebook logout];
}
-(void) postToWallWithDialogNewHighscore:(int)highscore
{
NSMutableDictionary *params = [self buildPostParamsWithHighScore:highscore];
NSLog(#"Post Feed");
[_facebook dialog:#"feed" andParams:params andDelegate:self];
}
#end
Button Action:
- (IBAction)facebookTest:(id)sender {
[[FacebookHelper sharedInstance] login];
[[FacebookHelper sharedInstance] postToWallWithDialogNewHighscore:123];
}
I have updated the singleton class to post scores to Facebook Wall. Check out the new version: http://indiedevstories.com/2012/04/11/facebookscorer-post-highscores-to-users-facebook-wall/
This new version handles correctly the internal state when authorization and login is required.
HTH
What you need to do is have your postToWallWithDialogNewHighscore call the login, if necessary, and then wait to hear back from the FBSession delegate. Then you need to setup your facebook fbDidLogin delegate so that when it is done it sends back a message. There are a number of ways to do this (a post-login selector, NSNotificationCenter, etc). Something like this should work (note I am assuming an ivar of NSMutableDictionary *postParams for convenience):
-(void)doPost {
NSLog(#"Post Feed");
[_facebook dialog:#"feed" andParams:postParams andDelegate:self];
}
-(void)postToWallWithDialogNewHighscore:(int)highscore
{
postParams = [self buildPostParamsWithHighScore:highscore];
if (_facebook.isSessionValid) {
[self doPost];
} else {
//register an observer for FB login messages
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(postToWallObserver:) name:#"FBLoginComplete" object:nil];
[self login];
}
}
-(void)fbDidLogin {
NSLog(#"token granted until %#", [_facebook expirationDate]);
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:[_facebook accessToken] forKey:#"FBAccessTokenKey"];
[defaults setObject:[_facebook expirationDate] forKey:#"FBExpirationDateKey"];
[defaults synchronize];
[[NSNotificationCenter defaultCenter] postNotificationName:#"FBLoginComplete" object:nil];
}
-(void)fbDidNotLogin:(BOOL)cancelled {
//do nothing as they didn't login
}
-(void) postToWallObserver:(NSNotification *) notification {
if ([[notification name] isEqualToString:#"FBLoginComplete"]) {
if ([_facebook isSessionValid]) {
[self doPost];
}
}
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
Note: I have not compiled this code so there may be typos, etc.