Singleton Integer Issue - iphone

I have a singleton which I hold a single integer in, my score. However when I load it form the singleton in a another view it doesn't show what I want but instead sticks at a wired 6592960. Any ideas why? Something to do with how I am using #property Im thinking, what the correct way to #property an int?
Thanks.
EDIT:
Code:
Singleton .h
#import <Foundation/Foundation.h>
#interface scoreData : NSObject {
int score;
}
#property int score;
+ (scoreData *)sharedData;
#end
Singleton .m
#import "scoreData.h"
static scoreData *sharedData = nil;
#implementation scoreData
#synthesize score;
#pragma mark -
#pragma mark Singleton Methods
+ (scoreData *)sharedData {
if(sharedData == nil){
sharedData = [[super allocWithZone:NULL] init];
}
return sharedData;
}
+ (id)allocWithZone:(NSZone *)zone {
return [[self sharedManager] retain];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (id)retain {
return self;
}
- (unsigned)retainCount {
return NSUIntegerMax;
}
- (void)release {
//do nothing
}
- (id)autorelease {
return self;
}
#end
Inside my other view, I access like this and then try and change the number and of course I import the singleton:
scoreData *score = [scoreData sharedData];
score.score = 0;

MySingleton.h
#import <Foundation/Foundation.h>
#interface MySingleton : NSObject {
}
#property(nonatomic,assign) int score;
+ (MySingleton*) sharedInstance;
#end
MySingleton.m
#import "MySingleton.h"
static MySingleton *_instance;
#implementation MySingleton
#synthesize score;
+ (MySingleton*)sharedInstance
{
#synchronized(self) {
if (_instance == nil) {
_instance = [[super allocWithZone:NULL] init];
}
}
return _instance;
}
#pragma mark Singleton Methods
+ (id)allocWithZone:(NSZone *)zone
{
return [[self sharedInstance]retain];
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain
{
return self;
}
- (unsigned)retainCount
{
return NSUIntegerMax;
}
- (void)release
{
}
- (id)autorelease
{
return self;
}
#end
See this xcode-template to simplify singleton-generation.

If it's a true singleton, then you can have your getter and setter simply directly access an initialized static global variable, and skip all the runtime alloc and zone busywork.

I would write the #property like this:
#property (nonatomic,assign) int score;
Also i would change sharedData:
+ (scoreData *)sharedData {
if( sharedData == nil ){
sharedData = [[self alloc] init];
}
return sharedData;
}
Edit: I tried your code and got EXC_BADACCESS because it went recursive here:
+ (id)allocWithZone:(NSZone *)zone {
return [[self sharedManager] retain];
}
When i removed that method everything worked as expected.

Related

how to implement Singleton Pattern in my IPhone project?

i am working on a project in wich i want to use Singleton Pattern model.
i want to any data model of my this project fallow Singleton Pattern.
i study the apple documentation regarding this
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaDesignPatterns/CocoaDesignPatterns.html#//apple_ref/doc/uid/TP40002974-CH6-SW6
and
http://www.oodesign.com/singleton-pattern.html
http://www.daveoncode.com/2011/12/19/fundamental-ios-design-patterns-sharedinstance-singleton-objective-c/
now i know my custom object classes should fallow the main rule of allocing a object but the i need the complete implementation like using of this class object
i am new in iphone app development so if i am wrong in any place in this Question please guide
Try this:
#implementation Singleton
+ (Singleton *)sharedInstance
{
static Singleton *obj = nil;
if (obj == nil)
obj = [[self alloc] init];
return obj;
}
#end
static MyClass *_sharedInstance;
+ (MyClass *)sharedMyClass
{
#synchronized([MyClass class]) {
if (_sharedInstance == nil)
[[self alloc] init];
return _sharedInstance;
}
return nil;
}
+(id) alloc
{
#synchronized([MyClass class]) {
NSAssert(_sharedInstance == nil, #"Attempted to allocate a second instance of MyClass.");
_sharedInstance = [super alloc];
return _sharedInstance;
}
return nil;
}
+ (id) allocWithZone:(NSZone *)zone
{
#synchronized([MyClass class]) {
NSAssert(_sharedInstance == nil, #"Attempted to allocate a second instance of MyClass.");
_sharedInstance= [super allocWithZone:zone];
return _sharedInstance;
}
return nil; //on subsequent allocation attempts return nil
}
- (id) copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain
{
return self;
}
- (NSUInteger)retainCount
{
return NSUIntegerMax;
}
- (oneway void)release
{
// Do nothing
}
- (id)autorelease
{
return self;
}
If you can target iOS 4 or above, I will take the following way:
//.h
+(MySingletonClass *)mySharedInstance;
-(void)doSomething;
//.m
+(MySingletonClass *)mySharedInstance {
static dispatch_once_t pred;
static MySingletonClass *shared = nil;
dispatch_once(&pred, ^{
shared = [[MySingletonClass alloc] init];
});
return shared;
}
-(void)doSomething
{
}
// override also the init if you want
To access it, do an #import MySingletonClass.h and use it wherever you want like the following:
MySingletonClass* mySharedInstance = [MySingletonClass mySharedInstance];
[mySharedInstance doSomething];
I want to any data model of my this project fallow Singleton Pattern.
Based on my experience, I would not abuse on singletons. The application could become difficult to maintain. To avoid this, put the data models within your singleton. You can access data model directly (creating properties around them) or using public methods (like for example doSomething) as wrappers.
Hope this helps.
This might be a useful reference: http://cocoasamurai.blogspot.com/2011/04/singletons-your-doing-them-wrong.html
Typically I create the object in the
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
method and have it live in that object. I make it available to the rest of the app with a macro:
#define APPLICATION ((AppDelegate*)([UIApplication sharedApplication].delegate))
as a readonly property of the app delegate
The benefit of this type of approach if you are in to mocking is that it is just another object property rather than a hidden static object.
I use:
#import <Foundation/Foundation.h>
#interface iCode_Framework : NSObject
#property (readonly, nonatomic) unsigned int iBufCapacity;
#property (readonly, nonatomic) unsigned int iPort;
#property (readonly, nonatomic) NSString * urlStr;
#end
#import "iCode_Framework.h"
static iCode_Framework * instance;
#implementation iCode_Framework
#dynamic iBufCapacity;
#dynamic iPort;
#dynamic urlStr;
- (unsigned int)iBufCapacity
{
return 1024u;
};
- (unsigned int)iPort
{
return 1978u;
};
- (NSString *)urlStr
{
return #"localhost";
};
+ (void)initialize
{
if (!instance) {
instance = [[super allocWithZone:NULL] init];
}
}
+ (id)allocWithZone:(NSZone * const)notUsed
{
return instance;
}
#end
Which is used exactly like a normal class, you call alloc and init! It is often convenient to assign to a variable to give a shorthand, because alloc and init are long to type, e.g.:
#import "iCode_FrameworkTests.h"
#import "iCode_Framework.h"
static iCode_Framework * c;
#implementation iCode_FrameworkTests
+ (void)initialize
{
c = [[iCode_Framework alloc] init];
}
- (void)setUp
{
[super setUp];
// Set-up code here.
}
- (void)tearDown
{
// Tear-down code here.
[super tearDown];
}
- (void)testSingletonNotNil
{
STAssertNotNil(c, nil);
}
- (void)testSingletonProperty
{
STAssertEqualObjects(c, [iCode_Framework alloc], nil);
}
- (void)testIBufCapacity
{
STAssertEquals(c.iBufCapacity, 1024u, nil);
}
#end
The advantage of this approach is it is used exactly like any other class and can therefore be mocked for testing.

How to set a BOOL value that can be used in other files of obj-c

I'm trying to set a BOOL value that needs to be checked within another file where I do the XML parching.
Its like this in filename.m:
if (internetConnectionStatus == NotReachable) {
//SET A BOOL VALUE TO FALSE
} else {
//SET A BOOL VALUE TO TRUE
}
And in XMLParserfile.m I need to check whether the BOOL value set in filename.m is TRUE or FALSE
if (BOOLVALUEORSOMETHING == TRUE) {
//DO THIS
} else {
//DO THAT
}
This could be a stupid question, but what is the best way to do this.
Use it as a property.
#property (nonatomic, assign) BOOL number;
Something like this should work. I'm not sure your entire goal, so it some cases you might actually want to use static classes or methods instead.
filename.h:
#import <Foundation/Foundation.h>
typedef enum {
NotReachable
} InternetConnectionStatus;
#interface filename : NSObject
{
BOOL isReachable;
}
#property BOOL isReachable;
#end
filename.m:
#import "filename.h"
#implementation filename
#synthesize isReachable;
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
InternetConnectionStatus internetConnectionStatus = NotReachable;
if (internetConnectionStatus == NotReachable) {
//SET A BOOL VALUE TO FALSE
self.isReachable = FALSE;
} else {
//SET A BOOL VALUE TO TRUE
self.isReachable = TRUE;
}
}
return self;
}
#end
XMLParserfile.h:
#import <Foundation/Foundation.h>
#interface XMLParserfile : NSObject
#end
XMLParserfile.m:
#import "XMLParserfile.h"
#import "filename.h"
#implementation XMLParserfile
- (id)init
{
self = [super init];
if (self) {
// Initialization code here.
filename *file = [[filename alloc] init];
if(file.isReachable == TRUE)
{
// DO THIS
}
else
{
// DO THAT.
}
}
return self;
}
#end
You can do this in one of several ways. I've discussed that in this answer to another question.

Why wont my singleton property autocomplete?

Anyidea why autocomplete does not work on the spaceScene property?
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#class SpaceScene;
#interface SpaceSceneSingleton : NSObject
{
SpaceScene *spaceScene;
}
#property (assign) SpaceScene *spaceScene;
+(SpaceSceneSingleton*)sharedSpaceSceneSingleton;
-(void) addChildToSceneWith:(CCNode *) node andWithZindex: (int) zIndex;
-(void) runAction:(CCAction*) action;
-(void) setTouchIsEnabled:(BOOL) isEnabled;
-(void) removeChild: (CCNode *) child;
#end
#import "SpaceSceneSingleton.h"
#implementation SpaceSceneSingleton
#synthesize spaceScene;
static SpaceSceneSingleton* _sharedSpaceSceneSingleton = nil;
+(SpaceSceneSingleton*)sharedSpaceSceneSingleton;
{
#synchronized([SpaceSceneSingleton class])
{
if (!_sharedSpaceSceneSingleton)
[[self alloc] init];
return _sharedSpaceSceneSingleton;
}
return nil;
}
+(id)alloc
{
#synchronized([SpaceSceneSingleton class])
{
NSAssert(_sharedSpaceSceneSingleton == nil, #"Attempted to allocate a second instance of a singleton.");
_sharedSpaceSceneSingleton = [super alloc];
return _sharedSpaceSceneSingleton;
}
return nil;
}
-(id)init {
self = [super init];
if (self != nil) {
// initialize stuff here
}
return self;
}
-(void) addChildToSceneWith:(CCNode *) node andWithZindex: (int) zIndex
{
[self.spaceScene addChild:node z:zIndex];
}
-(void) runAction:(CCAction*) action
{
//[self.spaceScene add
}
-(void) setTouchIsEnabled:(BOOL) isEnabled
{
}
-(void) removeChild: (CCNode *) child
{
}
#end
You only declared #class SpaceScene; so within this scope nothing more is known than that a class called SpaceScene might exist. Maybe importing SpaceScene.h helps.
I would even say this should compile with warnings. Does it?

Trouble in Simple app for iOS

I have a problem. I have 2 classes "Rating" (with .h and .m), "RatingViewController" (with .h and .m).
Rating.h
#import
#interface Rating : NSObject {
int usrLyrics;
int usrMusic;
int usrTotal;
}
- (void) setUsrTotal;
#end
Rating.m
#import "Rating.h"
#implementation Rating
-(void) incUsrLyrics
{
usrLyrics = 5;
}
- (void) incUsrMusic {
usrMusic = 6;
}
- (void) setUsrTotal {
usrTotal = usrMusic + usrLyrics;
}
}
#end
RatingViewController.h
#interface RatingItudeViewController : UIViewController {
Rating *rating;
}
- (IBAction) submitRating;
RatingViewController.m
#import "RatingItudeViewController.h"
#implementation RatingItudeViewController
- (IBAction) submitRating {
[rating setUsrTotal];
NSLog(#"usrTotal is %i", [rating usrTotal]);
}
#end
It's looks simple, but doesn't work, in Console always "usrTotal is 0".
Help me please.
UPDATED
Just now, I add couple lines in RatingViewController.m
- (IBAction) submitRating {
[rating incUsrMusic];
[rating incUsrLyrics];
[rating setUsrTotal];
NSLog(#"usrTotal is %d", [rating usrTotal]);
}
and in Rating.h
-(void) incUsrLyrics;
- (void) incUsrMusic;
- (void) setUsrTotal;
- (int) usrTotal;
And when a press a button, in console again "usrTotal is 0".
That is correct, you need to put initialization of usrMusic and usrLyrics variables into init constructor message. By default they are assigned values of 0. 0+0 is 0, hence the result.
The methods incUsrLyrics and incUsrMusic don't ever get called anywhere, thus never setting their initial values. If these values are essential to the operation of the class then they should be established in that class's initializer.
In Rating.m
- (id)init
{
if (self = [super init])
{
usrLyrics = 5;
usrMusic = 6;
}
return self;
}
or better yet, a more specific initializer...
- (id)initWithUserLyrics:(NSInteger)lyricsValue music:(NSInteger)musicValue
{
if (self = [super init])
{
usrLyrics = lyricsValue;
usrMusic = musicValue;
}
return self;
}

How do I make a custom delegate protocol for a UIView subclass?

I'm making some tabs and I want to have my own delegate for them but when I try to send an action to the delegate nothing happens.
I also tried following this tutorial:
link text
But it doesn't work for me :(
Here is my code:
TiMTabBar.h
#protocol TiMTabBarDelegate;
#interface TiMTabBar : UIView {
id<TiMTabBarDelegate> __delegate;
...
int selectedItem;
...
}
//- (id)init;
- (id)initWithDelegate:(id)aDelegate;
- (void)setSelectedIndex:(int)item;
..
#property (nonatomic) int selectedItem;
#property(assign) id <TiMTabBarDelegate> __delegate;
..
...
#end
#protocol TiMTabBarDelegate<NSObject>
//#optional
- (void)tabBar:(TiMTabBar *)_tabBar didSelectIndex:(int)index;
#end
TiMTabBar.m:
#import "TiMTabBar.h"
...
#interface NSObject (TiMTabBarDelegate)
- (void)tabBar:(TiMTabBar *)_tabBar didSelectIndex:(int)index;
#end
#implementation TiMTabBar
#synthesize selectedItem;
#synthesize __delegate;
...
/*
- (id)init
{
...
return self;
}
*/
- (id)initWithDelegate:(id)aDelegate;
{
//[super init];
__delegate = aDelegate;
return self;
}
- (void)awakeFromNib
{
//[self init];
//[self initWithDelegate:self];
...
}
- (void)setSelectedIndex:(int)item {
selectedItem = item;
if (self.__delegate != NULL && [self.__delegate respondsToSelector:#selector(tabBar:didSelectIndex:)]) {
[__delegate tabBar:self didSelectIndex:selectedItem];
}
...
if (item == 0) {
...
} else if (item == 1) {
...
} else if (item == 2) {
...
} else if (item == 3) {
...
} else if (item == 4) {
...
} else {
...
}
}
/*
- (void)tabBar:(TiMTabBar *)_tabBar didSelectIndex:(int)index;
{
//[delegate tabBar:self didSelectIndex:index];
//if (self.delegate != NULL && [self.delegate respondsToSelector:#selector(tabBar:didSelectIndex:)]) {
//[delegate tabBar:self didSelectIndex:selectedItem];
//}
NSLog(#"tabBarDelegate: %d",index);
}
*/
#end
The delegate only works works inside itself and not in any other files like:
#interface XXXController : UIViewController <TiMTabBarDelegate> {
...
...
IBOutlet TiMTabBar *tabBar;
...
}
...
#end
XXXController.m:
#import "XXXController.h"
#import <QuartzCore/QuartzCore.h>
#implementation XXXController
- (void)viewDidLoad {
[super viewDidLoad];
[self becomeFirstResponder];
...
tabBar = [[TiMTabBar alloc] initWithDelegate:self];
//tabBar.__delegate = self;
...
}
#pragma mark TiMTabBar Stuff
- (void)tabBar:(TiMTabBar *)_tabBar didSelectIndex:(int)index;
{
NSLog(#"Controller/tabBarDelegate: %d",index);
}
#end
None of this seems to work in XXXController. Anyone know how to make this work?
In your XXXController viewDidLoad after you alloc and init a new TiMTabBar are you adding it to the controller's view? If not, perhaps the tab bar in your view that you are clicking on is one loaded from the nib that does not have the delegate set.
It looks like - In awakeFromNib, you are setting the delegate to itself. So whenever you try to send the delegate messages, you are actually sending them to your instance of TiMTabBar, not XXXController.