Variable returning unexpected 0 in xcode - ios

The variable 'bubbleBankCapacity' is expected to return as 500 and be compared to the 'regularBubbleCount' variable in the comparison below, but instead returns as 0 which effectively makes the condition false given that the regularBubbleCount is greater than 0. Why is this returning a 0 when it has been set to initialize as 500?
AppDelegate.m
#import "AppDelegate.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
-(void)timerCalled
{
NSLog(#"Timer Called");
if ([RWGameData sharedGameData].bubbleFactoryUpgradeTier > 0) {
if ([RWGameData sharedGameData].regularBubbleCount < [RWGameData sharedGameData].bubbleBankCapacity) {
NSLog(#"bubbleFactoryUpgradeTier: %li", [RWGameData sharedGameData].bubbleFactoryUpgradeTier);
[RWGameData sharedGameData].regularBubbleCount += [RWGameData sharedGameData].bubbleFactoryTickValue;
NSLog(#"bubbleFactoryTickValue: %i", [RWGameData sharedGameData].bubbleFactoryTickValue);
[[RWGameData sharedGameData] save];
} else {
NSLog(#"Capacity Reached! Capacity: %li", [RWGameData sharedGameData].bubbleBankCapacity);
}
} NSLog(#"Regular Bubble Count: %li", [RWGameData sharedGameData].regularBubbleCount);
}
RWGameData.h
#import <Foundation/Foundation.h>
#interface RWGameData : NSObject <NSCoding>
#property (assign, nonatomic) long regularBubbleCount;
#property (assign, nonatomic) long premiumBubbleCount;
#property (assign, nonatomic) long megaBubbleUpgradeTier;
#property (assign, nonatomic) long bubbleFactoryUpgradeTier;
#property (assign, nonatomic) long bubblersUpgradeTier;
#property (assign, nonatomic) long mysteryBubbleUpgradeTier;
#property (assign, nonatomic) long bubbleBankUpgradeTier;
#property (assign, nonatomic) int megaBubblePopValue;
#property (assign, nonatomic) int bubbleFactoryTickValue;
#property (assign, nonatomic) long bubbleBankCapacity;
+(instancetype)sharedGameData;
-(void)reset;
-(void)save;
#end
RWGameData.m
#import "RWGameData.h"
#implementation RWGameData
static NSString* const SSGameDataRegularBubbleCountKey = #"regularBubbleCount";
static NSString* const SSGameDataPremiumBubbleCountKey = #"premiumBubbleCount";
static NSString* const SSGameDataMegaBubbleUpgradeTierKey = #"megaBubbleUpgradeTier";
static NSString* const SSGameDataBubbleFactoryUpgradeTierKey = #"bubbleFactoryUpgradeTier";
static NSString* const SSGameDataBubblersUpgradeTierKey = #"bubblersUpgradeTier";
static NSString* const SSGameDataMysteryBubbleUpgradeTierKey = #"mysteryBubbleUpgradeTier";
static NSString* const SSGameDataBubbleBankUpgradeTierKey = #"bubbleBankUpgradeTier";
static NSString* const SSGameDataMegaBubblePopValueKey = #"megaBubblePopValueKey";
static NSString* const SSGameDataBubbleFactoryTickValueKey = #"bubbleFactoryTickValueKey";
static NSString* const SSGameDataBubbleBankCapacityKey = #"bubbleBankCapacityKey";
+ (instancetype)sharedGameData {
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [self loadInstance];
});
return sharedInstance;
}
-(void)reset {
self.regularBubbleCount = 0;
self.premiumBubbleCount = 0;
self.megaBubbleUpgradeTier = 0;
self.bubbleFactoryUpgradeTier = 0;
self.bubblersUpgradeTier = 0;
self.mysteryBubbleUpgradeTier = 0;
self.bubbleBankUpgradeTier = 0;
self.megaBubblePopValue = 1;
self.bubbleFactoryTickValue = 1;
self.bubbleBankCapacity = 500;
}
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeDouble:self.regularBubbleCount forKey: SSGameDataRegularBubbleCountKey];
[encoder encodeDouble:self.premiumBubbleCount forKey: SSGameDataPremiumBubbleCountKey];
[encoder encodeDouble:self.megaBubbleUpgradeTier forKey: SSGameDataMegaBubbleUpgradeTierKey];
[encoder encodeDouble:self.bubbleFactoryUpgradeTier forKey: SSGameDataBubbleFactoryUpgradeTierKey];
[encoder encodeDouble:self.bubblersUpgradeTier forKey: SSGameDataBubblersUpgradeTierKey];
[encoder encodeDouble:self.mysteryBubbleUpgradeTier forKey: SSGameDataMysteryBubbleUpgradeTierKey];
[encoder encodeDouble:self.bubbleBankUpgradeTier forKey: SSGameDataBubbleBankUpgradeTierKey];
[encoder encodeDouble:self.megaBubblePopValue forKey: SSGameDataMegaBubblePopValueKey];
[encoder encodeDouble:self.bubbleFactoryTickValue forKey: SSGameDataBubbleFactoryTickValueKey];
[encoder encodeDouble:self.bubbleBankCapacity forKey: SSGameDataBubbleBankCapacityKey];
}
- (instancetype)initWithCoder:(NSCoder *)decoder
{
self = [self init];
if (self) {
_regularBubbleCount = [decoder decodeDoubleForKey: SSGameDataRegularBubbleCountKey];
_premiumBubbleCount = [decoder decodeDoubleForKey: SSGameDataPremiumBubbleCountKey];
_megaBubbleUpgradeTier = [decoder decodeDoubleForKey: SSGameDataMegaBubbleUpgradeTierKey];
_bubbleFactoryUpgradeTier = [decoder decodeDoubleForKey: SSGameDataBubbleFactoryUpgradeTierKey];
_bubblersUpgradeTier = [decoder decodeDoubleForKey: SSGameDataBubblersUpgradeTierKey];
_mysteryBubbleUpgradeTier = [decoder decodeDoubleForKey: SSGameDataMysteryBubbleUpgradeTierKey];
_bubbleBankUpgradeTier = [decoder decodeDoubleForKey: SSGameDataBubbleBankUpgradeTierKey];
_megaBubblePopValue = [decoder decodeDoubleForKey: SSGameDataMegaBubblePopValueKey];
_bubbleFactoryTickValue = [decoder decodeDoubleForKey: SSGameDataBubbleFactoryTickValueKey];
_bubbleBankCapacity = [decoder decodeDoubleForKey: SSGameDataBubbleBankCapacityKey];
}
return self;
}
+(NSString*)filePath
{
static NSString* filePath = nil;
if (!filePath) {
filePath =
[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
stringByAppendingPathComponent:#"gamedata"];
}
return filePath;
}
+(instancetype)loadInstance
{
NSData* decodedData = [NSData dataWithContentsOfFile: [RWGameData filePath]];
if (decodedData) {
RWGameData* gameData = [NSKeyedUnarchiver unarchiveObjectWithData:decodedData];
return gameData;
}
return [[RWGameData alloc] init];
}
-(void)save
{
NSData* encodedData = [NSKeyedArchiver archivedDataWithRootObject: self];
[encodedData writeToFile:[RWGameData filePath] atomically:YES];
}
#end

You need to initialize the bubbleBankCapacity variable in AppDelegate.m inside your method.

Solved.
I went ahead and declared a boolean property to RWGameData and tasked the reset method to set it to true when the reset method had been called. Then I went ahead and adjusted - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions like so:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
if (![RWGameData sharedGameData].dataIsInitialized) {
[[RWGameData sharedGameData] reset];
}
NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerCalled) userInfo:nil repeats:YES];
return YES;
}
Thank you to everyone who offered a solution to this problem. I greatly appreciate it!

Related

Trouble setting long value in singleton IOS

I'm having trouble with setting and accessing long properties on a Singleton object. Every time I try to access a long property it returns -1.
My singleton interface file is as follows:
#interface gameData : NSObject <NSCoding>
#property (assign, nonatomic) long score;
#property (assign, nonatomic) long level;
#property (assign, nonatomic) long riddlesCompleted;
#property (assign, nonatomic) long hints;
#property (assign, nonatomic) long firstLetters;
#property (assign, nonatomic) long answers;
+(instancetype)sharedGameData;
-(void)reset;
-(void)save;
#end
Then the implementation file sets up the encoders and decoders as follows:
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeDouble:self.score forKey:gameDataScoreKey];
[aCoder encodeDouble:self.level forKey:gameDataLevelKey];
[aCoder encodeDouble:self.riddlesCompleted forKey:gameDataRiddlesCompletedKey];
[aCoder encodeDouble:self.hints forKey:gameDataHintsKey];
[aCoder encodeDouble:self.firstLetters forKey:gameDataFirstLettersKey];
[aCoder encodeDouble:self.answers forKey:gameDataAnswersKey];
}
-(instancetype)initWithCoder:(NSCoder *)decoder{
self = [self init];
if (self) {
_score = [decoder decodeDoubleForKey:gameDataScoreKey];
_level = [decoder decodeDoubleForKey:gameDataLevelKey];
_riddlesCompleted = [decoder decodeDoubleForKey:gameDataRiddlesCompletedKey];
_hints = [decoder decodeDoubleForKey:gameDataHintsKey];
_firstLetters = [decoder decodeDoubleForKey:gameDataFirstLettersKey];
_answers = [decoder decodeDoubleForKey:gameDataAnswersKey];
}
return self;
}
+(instancetype) sharedGameData{
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [self loadInstance];
});
return sharedInstance;
}
Values are initialised as follows:
-(id)init{
if(self = [super init]){
_score = 500;
_riddlesCompleted = 0;
_level = 1;
_hints = 3;
_firstLetters = 3;
_answers = 3;
}
return self;
}
and then the instance is loaded:
+(NSString*)filePath{
static NSString* filePath = nil;
if (!filePath) {
filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES) firstObject]
stringByAppendingString:#"gameData"];
}
return filePath;
}
+(instancetype)loadInstance{
NSData* decodeData = [NSData dataWithContentsOfFile:[gameData filePath]];
if (decodeData) {
gameData* gameData = [NSKeyedUnarchiver unarchiveObjectWithData:decodeData];
return gameData;
}
return [[gameData alloc] init];
}
Then elsewhere in the application when I try to access these values I am not able to access the values of hints, firstletters or answers.
If I try logging the values as follows:
NSLog([NSString stringWithFormat:#"%li", [gameData sharedGameData].score] );
NSLog([NSString stringWithFormat:#"%li", [gameData sharedGameData].hint] );
NSLog([NSString stringWithFormat:#"%li", [gameData sharedGameData].answers]);
NSLog([NSString stringWithFormat:#"%li", [gameData sharedGameData].firstLetters]);
The output I get is 500 for score but for all the others I get 0 even though they are initialised in the gameData.m file with values 3.
Just a guess:
In loadInstance() you read the values from the file, so if there is a file you won't get in the init() where you set the values.
To be sure there is no gamedata-file you should reset the simulator oder delete the app from the device and try again.

Create a reference to the selected tab in my TabViewController?

RWGameData.h
#import <Foundation/Foundation.h>
#class RWGameData;
#protocol RWGameStateProtocol <NSObject>
-(void)StateUpdateForGameData:(RWGameData*)data;
#end
#interface RWGameData : NSObject <NSCoding>
#property (weak) id<RWGameStateProtocol> delegate;
#property (assign, nonatomic) long regularBubbleCount;
#property (assign, nonatomic) long premiumBubbleCount;
#property (assign, nonatomic) long megaBubbleUpgradeTier;
#property (assign, nonatomic) long bubbleFactoryUpgradeTier;
#property (assign, nonatomic) long bubblersUpgradeTier;
#property (assign, nonatomic) long mysteryBubbleUpgradeTier;
#property (assign, nonatomic) long bubbleBankUpgradeTier;
#property (assign, nonatomic) int megaBubblePopValue;
#property (assign, nonatomic) int bubbleFactoryTickValue;
#property (assign, nonatomic) long bubbleBankCapacity;
#property (assign, nonatomic) int collectionBallsQuantity;
#property (assign, nonatomic) int collectionGlowsticksQuantity;
#property (assign, nonatomic) int collectionFlowersQuantity;
#property (assign, nonatomic) int collectionStuffedAnimalsQuantity;
#property (assign, nonatomic) int collectionEasterEggsQuantity;
#property (assign, nonatomic) int currentXP;
#property (assign, nonatomic) int targetXP;
#property (assign, nonatomic) int level;
#property (assign, nonatomic) BOOL dataIsInitialized;
+(instancetype)sharedGameData;
-(void)reset;
-(void)save;
-(void)timerSetup;
-(void)timerCalled;
#end
RWGameData.m
#import "RWGameData.h"
#implementation RWGameData
static NSString* const SSGameDataRegularBubbleCountKey = #"regularBubbleCount";
static NSString* const SSGameDataPremiumBubbleCountKey = #"premiumBubbleCount";
static NSString* const SSGameDataMegaBubbleUpgradeTierKey = #"megaBubbleUpgradeTier";
static NSString* const SSGameDataBubbleFactoryUpgradeTierKey = #"bubbleFactoryUpgradeTier";
static NSString* const SSGameDataBubblersUpgradeTierKey = #"bubblersUpgradeTier";
static NSString* const SSGameDataMysteryBubbleUpgradeTierKey = #"mysteryBubbleUpgradeTier";
static NSString* const SSGameDataBubbleBankUpgradeTierKey = #"bubbleBankUpgradeTier";
static NSString* const SSGameDataMegaBubblePopValueKey = #"megaBubblePopValueKey";
static NSString* const SSGameDataBubbleFactoryTickValueKey = #"bubbleFactoryTickValueKey";
static NSString* const SSGameDataBubbleBankCapacityKey = #"bubbleBankCapacityKey";
static NSString* const SSGameDataCollectionBallsQuantityKey = #"collectionBallsQuantityKey";
static NSString* const SSGameDataCollectionGlowsticksQuantityKey = #"collectionGlowsticksQuantityKey";
static NSString* const SSGameDataCollectionFlowersQuantityKey = #"collectionFlowersQuantityKey";
static NSString* const SSGameDataCollectionStuffedAnimalsQuantityKey = #"collectionStuffedAnimalsQuantityKey";
static NSString* const SSGameDataCollectionEasterEggsQuantityKey = #"collectionEasterEggsQuantityKey";
/*static NSString* const SSGameDataCollectionBallsModifierKey = #"collectionBallsModifierKey";
static NSString* const SSGameDataCollectionGlowsticksModifierKey = #"collectionGlowsticksModifierKey";
static NSString* const SSGameCollectionFlowersModifierKey = #"collectionFlowersModifierKey";
static NSString* const SSGameCollectionStuffedAnimalsModifierKey = #"collectionStuffedAnimalsModifierKey";
static NSString* const SSGameCollectionEasterEggsModifierKey = #"collectionEasterEggsModifierKey";*/
static NSString* const SSGameDataCurrentXPKey = #"currentXPKey";
static NSString* const SSGameDataTargetXPKey = #"targetXPKey";
static NSString* const SSGameDataLevelKey = #"levelKey";
static NSString* const SSGameDataIsInitializedKey = #"dataIsInitializedKey";
+ (instancetype)sharedGameData {
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [self loadInstance];
});
return sharedInstance;
}
-(void)reset {
self.regularBubbleCount = 0;
self.premiumBubbleCount = 0;
self.megaBubbleUpgradeTier = 0;
self.bubbleFactoryUpgradeTier = 0;
self.bubblersUpgradeTier = 0;
self.mysteryBubbleUpgradeTier = 0;
self.bubbleBankUpgradeTier = 0;
self.megaBubblePopValue = 1;
self.bubbleFactoryTickValue = 1;
self.bubbleBankCapacity = 500;
self.collectionBallsQuantity = 0;
self.collectionGlowsticksQuantity = 0;
self.collectionFlowersQuantity = 0;
self.collectionStuffedAnimalsQuantity = 0;
self.collectionEasterEggsQuantity = 0;
self.currentXP = 0;
self.targetXP = 83;
self.level = 1;
self.dataIsInitialized = true;
}
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeDouble:self.regularBubbleCount forKey: SSGameDataRegularBubbleCountKey];
[encoder encodeDouble:self.premiumBubbleCount forKey: SSGameDataPremiumBubbleCountKey];
[encoder encodeDouble:self.megaBubbleUpgradeTier forKey: SSGameDataMegaBubbleUpgradeTierKey];
[encoder encodeDouble:self.bubbleFactoryUpgradeTier forKey: SSGameDataBubbleFactoryUpgradeTierKey];
[encoder encodeDouble:self.bubblersUpgradeTier forKey: SSGameDataBubblersUpgradeTierKey];
[encoder encodeDouble:self.mysteryBubbleUpgradeTier forKey: SSGameDataMysteryBubbleUpgradeTierKey];
[encoder encodeDouble:self.bubbleBankUpgradeTier forKey: SSGameDataBubbleBankUpgradeTierKey];
[encoder encodeDouble:self.megaBubblePopValue forKey: SSGameDataMegaBubblePopValueKey];
[encoder encodeDouble:self.bubbleFactoryTickValue forKey: SSGameDataBubbleFactoryTickValueKey];
[encoder encodeDouble:self.bubbleBankCapacity forKey: SSGameDataBubbleBankCapacityKey];
[encoder encodeDouble:self.collectionBallsQuantity forKey: SSGameDataCollectionBallsQuantityKey];
[encoder encodeDouble:self.collectionGlowsticksQuantity forKey: SSGameDataCollectionGlowsticksQuantityKey];
[encoder encodeDouble:self.collectionFlowersQuantity forKey: SSGameDataCollectionFlowersQuantityKey];
[encoder encodeDouble:self.collectionStuffedAnimalsQuantity forKey: SSGameDataCollectionStuffedAnimalsQuantityKey];
[encoder encodeDouble:self.collectionEasterEggsQuantity forKey: SSGameDataCollectionEasterEggsQuantityKey];
[encoder encodeDouble:self.currentXP forKey: SSGameDataCurrentXPKey];
[encoder encodeDouble:self.targetXP forKey: SSGameDataTargetXPKey];
[encoder encodeDouble:self.level forKey:SSGameDataLevelKey];
[encoder encodeBool:self.dataIsInitialized forKey: SSGameDataIsInitializedKey];
}
- (instancetype)initWithCoder:(NSCoder *)decoder
{
self = [self init];
if (self) {
_regularBubbleCount = [decoder decodeDoubleForKey: SSGameDataRegularBubbleCountKey];
_premiumBubbleCount = [decoder decodeDoubleForKey: SSGameDataPremiumBubbleCountKey];
_megaBubbleUpgradeTier = [decoder decodeDoubleForKey: SSGameDataMegaBubbleUpgradeTierKey];
_bubbleFactoryUpgradeTier = [decoder decodeDoubleForKey: SSGameDataBubbleFactoryUpgradeTierKey];
_bubblersUpgradeTier = [decoder decodeDoubleForKey: SSGameDataBubblersUpgradeTierKey];
_mysteryBubbleUpgradeTier = [decoder decodeDoubleForKey: SSGameDataMysteryBubbleUpgradeTierKey];
_bubbleBankUpgradeTier = [decoder decodeDoubleForKey: SSGameDataBubbleBankUpgradeTierKey];
_megaBubblePopValue = [decoder decodeDoubleForKey: SSGameDataMegaBubblePopValueKey];
_bubbleFactoryTickValue = [decoder decodeDoubleForKey: SSGameDataBubbleFactoryTickValueKey];
_bubbleBankCapacity = [decoder decodeDoubleForKey: SSGameDataBubbleBankCapacityKey];
_collectionBallsQuantity = [decoder decodeDoubleForKey: SSGameDataCollectionBallsQuantityKey];
_collectionGlowsticksQuantity = [decoder decodeDoubleForKey: SSGameDataCollectionGlowsticksQuantityKey];
_collectionFlowersQuantity = [decoder decodeDoubleForKey: SSGameDataCollectionFlowersQuantityKey];
_collectionStuffedAnimalsQuantity = [decoder decodeDoubleForKey: SSGameDataCollectionStuffedAnimalsQuantityKey];
_collectionEasterEggsQuantity = [decoder decodeDoubleForKey: SSGameDataCollectionEasterEggsQuantityKey];
_currentXP = [decoder decodeDoubleForKey: SSGameDataCurrentXPKey];
_targetXP = [decoder decodeDoubleForKey: SSGameDataTargetXPKey];
_level = [decoder decodeDoubleForKey: SSGameDataLevelKey];
_dataIsInitialized = [decoder decodeBoolForKey: SSGameDataIsInitializedKey];
}
return self;
}
+(NSString*)filePath
{
static NSString* filePath = nil;
if (!filePath) {
filePath =
[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
stringByAppendingPathComponent:#"gamedata"];
}
return filePath;
}
+(instancetype)loadInstance
{
NSData* decodedData = [NSData dataWithContentsOfFile: [RWGameData filePath]];
if (decodedData) {
RWGameData* gameData = [NSKeyedUnarchiver unarchiveObjectWithData:decodedData];
return gameData;
}
return [[RWGameData alloc] init];
}
-(void)save
{
NSData* encodedData = [NSKeyedArchiver archivedDataWithRootObject: self];
[encodedData writeToFile:[RWGameData filePath] atomically:YES];
}
- (void)timerSetup { // to be called from delegate didFinishLaunching….
NSTimer *timer;
timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerCalled) userInfo:nil repeats:YES];
}
-(void)timerCalled
{
//NSLog(#"Timer Called");]
if ([RWGameData sharedGameData].bubbleFactoryUpgradeTier > 0) {
if ([RWGameData sharedGameData].regularBubbleCount < [RWGameData sharedGameData].bubbleBankCapacity) {
[RWGameData sharedGameData].regularBubbleCount += [RWGameData sharedGameData].bubbleFactoryTickValue;
[[RWGameData sharedGameData] save];
} else {
NSLog(#"Capacity Reached! Capacity: %li", [RWGameData sharedGameData].bubbleBankCapacity);
}
[self.delegate StateUpdateForGameData:self];
} NSLog(#"Regular Bubble Count: %li", [RWGameData sharedGameData].regularBubbleCount);
}
#end
PrimaryViewController.h
#import <UIKit/UIKit.h>
#import "RWGameData.h"
#interface PrimaryViewController : UIViewController <RWGameStateProtocol>
#property (strong, nonatomic) IBOutlet UILabel *regularBubLabel;
#end
I would like to be able to change the value of regularBubLabel from within the timerCalled method. Thank you for your time.
Included the entirety of my RWGameData class as it was requested. Thanks.
AppDelegate.h
#import <UIKit/UIKit.h>
#import "RWGameData.h"
#import "PrimaryViewController.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong,nonatomic) RWGameData *gameData;
#end
Then see +(instancetype)loadInstance of #RWGameData.m
If you can provide more details of what you are trying to achieve.
If I understand correctly you want to know which tab is active
all you have to do is get tab.selectedIndex property which will return back to you int representing the index of activTabView then you can do anything with it such as change the Text of the selected index
Hope this help.
From your code I can see that your PrimaryViewController is confirming the protocol for RWGameData i.e
#interface PrimaryViewController : UIViewController <RWGameStateProtocol>
so, set the delegate of RWGameData to PrimaryViewController Object, then implement this delegate method in PrimaryViewController.m like
-(void)StateUpdateForGameData:(RWGameData*)data
{
//now update label
self.regularBubLabel.text = #"asdasd";
}
Edit:
In PrimaryViewController.m viewDidLoad method add this line
[RWGameData sharedGameData].delegate = self;
timercalled method should be like
-(void)timerCalled
{
//NSLog(#"Timer Called");]
if ([RWGameData sharedGameData].bubbleFactoryUpgradeTier > 0) {
if ([RWGameData sharedGameData].regularBubbleCount < [RWGameData sharedGameData].bubbleBankCapacity) {
[RWGameData sharedGameData].regularBubbleCount += [RWGameData sharedGameData].bubbleFactoryTickValue;
[[RWGameData sharedGameData] save];
} else {
NSLog(#"Capacity Reached! Capacity: %li", [RWGameData sharedGameData].bubbleBankCapacity);
}
if(self.delegate && [self.delegate respondsToSelector:#selector(StateUpdateForGameData:)])
[self.delegate StateUpdateForGameData:self];
} NSLog(#"Regular Bubble Count: %li", [RWGameData sharedGameData].regularBubbleCount);
}

Change the value sent to variable in class A from AppDelegate in xcode

****What I am trying to do:****
I am attempting to increment the value of [RWGameData sharedGameData].regularBubbleCount by 1 for every second that passes. I have done this successfully. The problem is that I cannot call the following from within AppDelegate#timerCalled. How would I accomplish this?
_regularBubLabel.text = [NSString stringWithFormat:#"%li", [RWGameData sharedGameData].regularBubbleCount];
AppDelegate.h
#import <UIKit/UIKit.h>
#import "RWGameData.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
-(void)timerCalled;
#end
AppDelegate.m
#import "AppDelegate.h"
#interface AppDelegate ()
#end
#implementation AppDelegate
-(void)timerCalled
{
NSLog(#"Timer Called");
[RWGameData sharedGameData].regularBubbleCount++;
NSLog(#"%li", [RWGameData sharedGameData].regularBubbleCount);
[[RWGameData sharedGameData] save];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerCalled) userInfo:nil repeats:YES];
return YES;
}
#end
PrimaryViewController.h
#import <UIKit/UIKit.h>
#import "RWGameData.h"
#interface PrimaryViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *regularBubLabel;
#end
PrimaryViewController.m
#import "PrimaryViewController.h"
#interface PrimaryViewController ()
#end
#implementation PrimaryViewController
{
NSString *bubbleImage;
int r;
int i;
}
- (void)viewDidLoad {
[super viewDidLoad];
_regularBubLabel.text = [NSString stringWithFormat:#"%li", [RWGameData sharedGameData].regularBubbleCount];
_premiumBubLabel.text = [NSString stringWithFormat:#"%li", [RWGameData sharedGameData].premiumBubbleCount];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)increment {
if ([#"mysterybubble.png" isEqual:bubbleImage]) {
[RWGameData sharedGameData].premiumBubbleCount += 2;
_premiumBubLabel.text = [NSString stringWithFormat:#"%li", [RWGameData sharedGameData].premiumBubbleCount];
} else if ([#"megaBubbleLarge30.png" isEqual:bubbleImage]) {
[RWGameData sharedGameData].regularBubbleCount += 50000;
_regularBubLabel.text = [NSString stringWithFormat:#"%li", [RWGameData sharedGameData].regularBubbleCount];
} i++;
}
- (IBAction)save {
[[RWGameData sharedGameData] save];
}
- (IBAction)setBubbleStatus {
r = arc4random_uniform(300);
if (r <= 12) {
bubbleImage = #"mysterybubble.png";
[_megaBubbleButton setImage:[UIImage imageNamed:bubbleImage] forState:UIControlStateNormal];
NSLog(#"Roll SUCCESS. [%i] %i", i, r);
} else {
bubbleImage = #"megaBubbleLarge30.png";
[_megaBubbleButton setImage:[UIImage imageNamed:bubbleImage] forState:UIControlStateNormal];
NSLog(#"Roll FAIL. [%i] %i", i, r);
}
}
#end
RWGameData.h
#import <Foundation/Foundation.h>
#interface RWGameData : NSObject <NSCoding>
#property (assign, nonatomic) long regularBubbleCount;
+(instancetype)sharedGameData;
-(void)reset;
-(void)save;
#end
RWGameData.m
#import "RWGameData.h"
#implementation RWGameData
static NSString* const SSGameDataRegularBubbleCountKey = #"regularBubbleCount";
+ (instancetype)sharedGameData {
static id sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [self loadInstance];
});
return sharedInstance;
}
-(void)reset {
self.regularBubbleCount = 0;
}
- (void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeDouble:self.regularBubbleCount forKey: SSGameDataRegularBubbleCountKey];
}
- (instancetype)initWithCoder:(NSCoder *)decoder
{
self = [self init];
if (self) {
_regularBubbleCount = [decoder decodeDoubleForKey: SSGameDataRegularBubbleCountKey];
}
return self;
}
+(NSString*)filePath
{
static NSString* filePath = nil;
if (!filePath) {
filePath =
[[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]
stringByAppendingPathComponent:#"gamedata"];
}
return filePath;
}
+(instancetype)loadInstance
{
NSData* decodedData = [NSData dataWithContentsOfFile: [RWGameData filePath]];
if (decodedData) {
RWGameData* gameData = [NSKeyedUnarchiver unarchiveObjectWithData:decodedData];
return gameData;
}
return [[RWGameData alloc] init];
}
-(void)save
{
NSData* encodedData = [NSKeyedArchiver archivedDataWithRootObject: self];
[encodedData writeToFile:[RWGameData filePath] atomically:YES];
}
#end
Either you need the timer to invoke a selector on the PrimaryViewController instead of the AppDelegate, or else the AppDelegate needs to store a reference to the PrimaryViewController in order to call a method on the View Controller that updates the label.
A third (less recommended) method is to send out an NSNotification when the timer fires and have multiple VC's observe and respond to the notification, but that's harder to debug later.
You didn't show the code where the instance of PrimaryViewController gets created, but normally you'd store the reference in a property so you can access it later.
If there are many such view controllers, then the code which creates the ViewControllers (is this the AppDelegate?) should have a property which is an NSMutableArray of view controllers, say myTimerViewControllers. When the timer fires, inside timerCalled, iterate through them and tell each one to update its label.
To really do this with the best pattern, you'd create a simple #protocol with one method (say, handleTimer or updateTimerLabel). Each of the VC's would be declared as supporting this protocol, and the AppDelegate would have code something like:
for(UIViewController<TimerProtocol> *vc in myTimerViewControllers) {
[vc handleTimer];
}

iOS: Singleton returning null

I have a singleton and I pass data to it but it returns null can you please help me in my situation. Thanks in advance :)
Here's my code
Card.h
#property (weak,nonatomic) NSString *email;
#property (weak,nonatomic) NSString *fName;
#property (weak,nonatomic) NSString *lName;
#property (weak,nonatomic) NSString *category;
+(Card *)getCard;
Card.m
#synthesize email;
#synthesize fName;
#synthesize lName;
#synthesize category;
static csCard *instance;
+(Card *) getCard
{
#synchronized (self)
{
if(instance == nil)
{
instance = [[Card alloc]init];
}
}
return instance;
}
- (id) init{
self.email = [[NSUserDefaults standardUserDefaults]stringForKey:#"email"];
self.fName = [[NSUserDefaults standardUserDefaults]stringForKey:#"firstName"];
self.lName = [[NSUserDefaults standardUserDefaults]stringForKey:#"lastName"];
self.category = #"TestCategory";
return self;
}
and here's my test code to see if it's working
Test.m
Card *card = [Card getCard];
[card setEmail:self.emailField.text];
NSLog(#"%#",card.email);
but this code give me (null)
Modify your class like this.
Card.h
#property (strong,nonatomic) NSString *email; //Let the modal be strong property
#property (strong,nonatomic) NSString *fName;
#property (strong,nonatomic) NSString *lName;
#property (strong,nonatomic) NSString *category;
+(Card *)getCard;
Card.m
static Card *instance;
+(Card *) getCard
{
#synchronized (self)
{
if(instance == nil)
{
instance = [[Card alloc]init];
}
}
return instance;
}
- (NSString)email{
return [[NSUserDefaults standardUserDefaults]stringForKey:#"email"];
}
- (void)setEmail:(NSString)email{
[[NSUserDefaults standardUserDefaults] setString:email forkey:#"email"];
}
No need of overriding init
in your test class
Card *card = [Card getCard];
[card setEmail:self.emailField.text];
NSLog(#"%#",card.email);
static csCard *instance;
+(csCard *) getCard
{
#synchronized (self)
{
if(instance == nil)
{
instance = [[csCard alloc]init];
}
}
return instance;
}
Replace it with this code
static Card *instance;
+(Card *) getCard
{
#synchronized (self)
{
if(instance == nil)
{
instance = [[Card alloc]init];
}
}
return instance;
}
The Class name Of the instance Object was wrong and In singleton method,the return datatype was also wrong. I think u will understand what I am saying.
+ (Card *)instance {
static Card *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[Card alloc] init];
});
return sharedInstance;
}
It should be work
With the help of what βhargavḯ sujjested u can modify your code as below because
in the line static csCard *instance; u are using csCard i think it is typo so better u can do like this,
#import "Card.h"
static dispatch_once_t onceDispach;
#implementation Card
#synthesize email = _email;
#synthesize fName;
#synthesize lName;
#synthesize category;
static Card *instance = nil; //change this to Card because this instance which is of type Card
+(Card *)getCard
{
dispatch_once(&onceDispach, ^{
instance = [[self alloc] init];//careate Card shared object named instance
});
return instance;
}
- (id) init
{
self.email = [[NSUserDefaults standardUserDefaults]stringForKey:#"email"];
self.fName = [[NSUserDefaults standardUserDefaults]stringForKey:#"firstName"];
self.lName = [[NSUserDefaults standardUserDefaults]stringForKey:#"lastName"];
self.category = #"TestCategory";
return self;
}
#end
- (NSString *)email
{
return _email;
}
- (void)setEmail:(NSString *)email
{
_email = email;
NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
[userDefault setObject:email forKey:#"email"];
}
in the class where u are using this shared instance use like below
- (void)actionMathodCalled
{
Card *card = [Card getCard];
NSLog(#"before saving to defaults->%#",card.email);
[card setEmail:#"happyCoding#ymail.com"];
NSLog(#"after savng to defaults->%#",card.email);
}

Saving NSDictionary (with custom classes) to NSUserDefaults [duplicate]

This question already has answers here:
How to store custom objects in NSUserDefaults
(7 answers)
Closed 9 years ago.
I am trying to save an NSDictionary to my NSUserDefualts.
The dictionary consists of 3 different custom classes.
#interface PastOrder : NSObject <NSCoding>
{
NSDate *timeIn;
NSDate *timeOut;
NSString *status;
NSMutableArray *myItems;
}
#property (nonatomic, retain) NSDate *timeIn;
#property (nonatomic, retain) NSDate *timeOut;
#property (nonatomic, retain) NSString *status;
#property (nonatomic, retain) NSMutableArray *myItems;
#end
#implementation PastOrder
#synthesize timeIn, timeOut, status, myItems;
#define PastOrderTimeInKey #"PastOrderTimeInKey"
#define PastOrderTimeOutKey #"PastOrderTimeOutKey"
#define PastOrderStatusKey #"PastOrderStatusKey"
#define PastOrderMyItemsKey #"PastOrderMyItemsKey"
-(id)initWithCoder:(NSCoder*)decoder
{
self = [super init];
if(self)
{
self.timeIn = [decoder decodeObjectForKey:PastOrderTimeInKey];
self.timeOut = [decoder decodeObjectForKey:PastOrderTimeOutKey];
self.status = [decoder decodeObjectForKey:PastOrderStatusKey];
self.myItems = [decoder decodeObjectForKey:PastOrderMyItemsKey];
}
return self;
}
-(void)encodeWithCoder:(NSCoder*)encoder
{
[encoder encodeObject:self.timeIn forKey:PastOrderTimeInKey];
[encoder encodeObject:self.timeOut forKey:PastOrderTimeOutKey];
[encoder encodeObject:self.status forKey:PastOrderStatusKey];
[encoder encodeObject:self.myItems forKey:PastOrderMyItemsKey];
}
-(void)dealloc
{
self.timeIn = nil;
self.timeOut = nil;
self.status = nil;
self.myItems = nil;
}
#end
#interface PastOrderItem : NSObject <NSCoding>
{
NSNumber *itemID;
NSString *status;
NSMutableArray *itemChoices;
}
#property (nonatomic, retain) NSNumber *itemID;
#property (nonatomic, retain) NSString *status;
#property (nonatomic, retain) NSMutableArray *itemChoices;
#end
#implementation PastOrderItem
#synthesize itemID,status,itemChoices;
#define PastOrderItemItemIDKey #"PastOrderItemItemIDKey"
#define PastOrderItemStatusKey #"PastOrderItemStatusKey"
#define PastOrderItemItemChoicesKey #"PastOrderItemItemChoicesKey"
-(id)initWithCoder:(NSCoder*)decoder
{
self = [super init];
if(self)
{
self.itemID = [decoder decodeObjectForKey:PastOrderItemItemIDKey];
self.itemChoices = [decoder decodeObjectForKey:PastOrderItemItemChoicesKey];
self.status = [decoder decodeObjectForKey:PastOrderItemStatusKey];
}
return self;
}
-(void)encodeWithCoder:(NSCoder*)encoder
{
[encoder encodeObject:self.itemID forKey:PastOrderItemItemIDKey];
[encoder encodeObject:self.itemChoices forKey:PastOrderItemItemChoicesKey];
[encoder encodeObject:self.status forKey:PastOrderItemStatusKey];
}
-(void)dealloc
{
self.itemID = nil;
self.itemChoices = nil;
self.status = nil;
}
#end
#interface PastOrderItemChoice : NSObject <NSCoding>
{
NSNumber *modifierID;
NSNumber *modifierChoice;
}
#property (nonatomic, retain) NSNumber *modifierID;
#property (nonatomic, retain) NSNumber *modifierChoice;
#end
#implementation PastOrderItemChoice
#synthesize modifierID, modifierChoice;
#define PastOrderItemChoiceModifierIDKey #"PastOrderItemChoiceModifierIDKey"
#define PastOrderItemChoiceModifierChoiceKey #"PastOrderItemChoiceModifierChoiceKey"
-(id)initWithCoder:(NSCoder*)decoder
{
self = [super init];
if(self)
{
self.modifierID = [decoder decodeObjectForKey:PastOrderItemChoiceModifierIDKey];
self.modifierChoice = [decoder decodeObjectForKey:PastOrderItemChoiceModifierChoiceKey];
}
return self;
}
-(void)encodeWithCoder:(NSCoder*)encoder
{
[encoder encodeObject:self.modifierID forKey:PastOrderItemChoiceModifierIDKey];
[encoder encodeObject:self.modifierChoice forKey:PastOrderItemChoiceModifierChoiceKey];
}
-(void)dealloc
{
self.modifierID = nil;
self.modifierChoice = nil;
}
#end
Those are the three classes that will be inside this NSDictionary.
Here is how I Load and Save it.
-(void)SavePrefs
{
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSData* data=[NSKeyedArchiver archivedDataWithRootObject:self.myDictionary];
[prefs setObject:data forKey:#"SavedOrders"];
[prefs synchronize];
}
- (id)init
{
self = [super init];
if (self)
{
NSData* data = [[NSUserDefaults standardUserDefaults] objectForKey:#"SavedOrders"];
self.myDictionary = [NSKeyedUnarchiver unarchiveObjectWithData:data];
}
return self;
}
I have experimented with the code a bit, and best I have to far, is that when I save the dictionary, it was 135 bytes, same as when I loaded it, but it still didnt fill the dictionary up. So I am at a loss.
Your code seems to be good. I can't find a mistake so try to change line:
self.myDictionary = [NSKeyedUnarchiver unarchiveObjectWithData:data];
to
id unknownObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];
NSLog(#"%#",[unknownObject class]);
And look # the console. Maybe you should also try casting if the output will be dictionary. So try to change this to:
self.myDictionary = (NSDictionary*)[NSKeyedUnarchiver unarchiveObjectWithData:data];
EDIT
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:#"object1",#"key1",#"object2",#"key2",#"object3",#"key3", nil];
NSLog(#"before: %#",dictionary);
NSData *myData = [NSKeyedArchiver archivedDataWithRootObject:dictionary];
NSDictionary *myDictionary = (NSDictionary*) [NSKeyedUnarchiver unarchiveObjectWithData:myData];
NSLog(#"after: %#",myDictionary);
Output:
2013-11-13 14:32:31.369 DemoM[175:60b] before: {
key1 = object1;
key2 = object2;
key3 = object3;
}
2013-11-13 14:32:31.372 DemoM[175:60b] after: {
key1 = object1;
key2 = object2;
key3 = object3;
}

Resources