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.
Related
I asked a question yesterday regarding my table view and linking unique detail views to each cell in the table view. I believe I got a good answer to my question here. (Hopefully you can read that post and see what I need). Basically I wanted to know if I am making my singleton correctly. Here is my code:
timerStore.h
#import "Tasks.h"
#interface timerStore : NSObject
{
NSMutableDictionary *allItems;
}
+(timerStore *)sharedStore;
-(NSDictionary *)allItems;
-(NSTimer *)createTimerFor:(Tasks *)t inLocation: (NSIndexPath *)indexPath;
-(void)timerAction;
#end
timerStore.m
#implementation timerStore
+(timerStore *)sharedStore{
static timerStore *sharedStore = nil;
if (!sharedStore)
sharedStore = [[super allocWithZone:nil]init];
return sharedStore;
}
+(id)allocWithZone:(NSZone *)zone{
return [self sharedStore];
}
-(id)init {
self = [super init];
if (self) {
allItems = [[NSMutableDictionary alloc]init];
}
return self;
}
-(NSDictionary *)allItems{
return allItems;
}
-(NSTimer *)createTimerFor:(Tasks *)t inLocation: (NSIndexPath *)indexPath {
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:t.timeInterval target:self selector:#selector(timerAction) userInfo:nil repeats:1.0];
[allItems setObject:timer forKey:indexPath];
return timer;
}
-(void)timerAction{
//custom properties here
}
#end
I'm kind of confused because I was under the impression that a cell's index path gets recycled as you scroll down (dequeue). I may be wrong though. Anyway, am I on the right path to making a singleton as the guy in the link suggested?
The best way to implement App Singleton is as follows
Header file
#import <Foundation/Foundation.h>
#interface AppSingleton : NSObject
#property (nonatomic, retain) NSString *username;
+ (AppSingleton *)sharedInstance;
#end
Implementation File
#import "AppSingleton.h"
#implementation AppSingleton
#synthesize username;
+ (AppSingleton *)sharedInstance {
static AppSingleton *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
// Initializing
- (id)init {
if (self = [super init]) {
username = [[NSString alloc] init];
}
return self;
}
#end
Note:
What this does is it defines a static variable (but only global to this translation unit) called sharedInstance which is then initialised once and only once in sharedInstance Method. The way we ensure that it’s only created once is by using the dispatch_once method from Grand Central Dispatch (GCD). This is thread safe and handled entirely by the OS for you so that you don’t have to worry about it at all.
Using Singleton To set value
[[AppSingleton sharedInstance] setUsername:#"codebuster"];
Using Singleton to get value.
NSString *username = [[AppSingleton sharedInstance] username];
Further Reference and Reading
#Interface
//
// Created by macbook on 31.05.12.
//
// To change the template use AppCode | Preferences | File Templates.
//
#import <Foundation/Foundation.h>
#interface CESettings : NSObject
+ (CESettings *)sharedInstance;
- (void)save;
#end
#Implementation
//
// Created by macbook on 31.05.12.
//
// To change the template use AppCode | Preferences | File Templates.
//
#import "CESettings.h"
#interface CESettings ()
#property(nonatomic, strong) NSUserDefaults *userDefaults;
#end
#implementation CESettings
#synthesize userDefaults = _userDefaults;
#pragma mark - Singleton
static CESettings *_instance = nil;
+ (CESettings *)sharedInstance {
#synchronized (self) {
if (_instance == nil) {
_instance = [self new];
}
}
return _instance;
}
- (id)init {
self = [super init];
if (self) {
self.userDefaults = [NSUserDefaults standardUserDefaults];
}
return self;
}
#pragma mark - Methods
- (void)save {
[self.userDefaults synchronize];
}
#end
I have a class used for settings in an app. The class has a method for creating singleton and an init method as well. What is the use for both..? I think if the sharedInstance method is there , there is no need for the init... please correct me if I am wrong..
Any help is appreciated.
The init method is what gets called by new in the call of [self new]. It is essentially the same as
_instance = [[CESettings alloc] init];
but takes less typing and avoids hard-coding the name of the CESettings class.
A better way of implementing singleton is using dispatch_once, like this:
+ (CESettings*)sharedInstance
{
static dispatch_once_t once;
static CESettings *_instance;
dispatch_once(&once, ^ { _instance = [self new]; });
return _instance;
}
From the documentation of NSObject:
+ (id)new
Allocates a new instance of the receiving class, sends it an init
message, and returns the initialized object.
You're calling [self new] in your singleton creator method, which in turn will allocate a new instance and send it an init message.
the sharedInstance class method is only responsible for allocating and initing ONE object and then always returning that.
BUT
you dont have go through that method you can call alloc init yourself and it will also work
so init is needed to keep the semantics of how alloc/init should work
I've reviewed (and tried) a bunch of the threads here regarding Singletons and NSMutableArrays. I'm new to Objective-C so please bear with me.
I simply want to create a few arrays that can be accessed from any view/.m file.
What is the best (or most concise) coding for a Singleton?
Below is what I have now and I get
1 warning at .m '#implementation' - "Incomplete implementation"
1 error at usage in a view .m file - "initializer element is not a compile-time constant"
This is the code I have now - my GlobalData.h file:
#import <Foundation/Foundation.h>
#interface GlobalData : NSObject {
NSMutableArray *listOfHeadings;
NSMutableArray *listOfItems1;
NSMutableArray *listOfItems2;
}
#property(nonatomic,retain)NSMutableArray *listOfHeadings;
#property(nonatomic,retain)NSMutableArray *listOfItems1;
#property(nonatomic,retain)NSMutableArray *listOfItems2;
+(GlobalData*)getInstance;
#end
My GlobalData.m file:
#import "GlobalData.h"
#implementation GlobalData
#synthesize listOfHeadings;
#synthesize listOfItems1;
#synthesize listOfItems2;
static GlobalData *instance=nil;
+(GlobalData *)getInstance
{
#synchronized(self)
{
if(instance==nil)
{
instance= [GlobalData new];
}
}
return instance;
}
#end
And in a view .m file (simplified):
#import GlobalData.h
GlobalData *globDat=[GlobalData getInstance]; //error occurs here
Can someone point out the trouble and if there's better coding, please enlighten me - thanks!
EDIT
Here's a few links I've tried to use:
Can i have a single NSMutableArray in my multiple views application?
iPhone help with singleton class
In this case, you might be doing more than you have to. Granted this certainly isn't always the best solution - but you can put your NSMutableArray as a property in your App Delegate and then easily refer to it from any view. By doing it this way - you aren't locking it in as a 'singleton' but there is a 'singleton instance' of it (this helps a great deal for testability).
I have simplified this process here:
YourAppDelegate.h
#property (nonatomic,retain) NSMutableArray *myArray;
YourAppDelegate.m
#synthesize myArray;
YourViewController.m
YourAppDelegate *appDelegate = (YourAppDelegate *)[[UIApplication sharedApplication] delegate];
NSMutableArray *myArrayFromAppDelegate = appDelegate.myArray;
From this point - you can do any manipulation on this value.
Here's the "modern" version of a single method to turn any class into a Singleton (in this case formatted as a code snippet). It works in iOS4.x or higher:
+(<#SingletonClassName#> *) sharedInstance
{
static <#SingletonClassName#> *_sharedClient = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_sharedClient = [[self alloc] init];
});
return _sharedClient;
}
But, do you really need a singleton of a single NSMutableArray? You could use the built-on singleton - your application delegate, which is got to by calling:
MyAppDelegate * appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
[appDelegate.myMutableArray addObject:...];
The error initializer element is not a compile-time constant is not related to how you create your singleton. The error is how you are accessing your singleton. You are doing this outside of a function:
GlobalData *globDat=[GlobalData getInstance];
This means that you are trying to initialize a global variable (globDat) as the value of the expression [GlobalData getInstance]. You can only initialize global variables to expressions that are "compile-time constants". That means things like 0 or "fred" or 8/2. The value of [GlobalData getInstance] cannot be computed at compile-time, so it cannot be used to initialize the global variable.
Instead, you need to just use [GlobalData getInstance] inside your function bodies wherever you are currently trying to use the globDat variable.
As for the warning, Incomplete implementation, I don't see what's missing. Perhaps you didn't post all of the code from GlobalData.h. Anyway, you should be able to click the warning (where it appears on the right side of the editor window) and have Xcode show you what's missing.
This is the way I create my Singleton:
Singleton.h
#import <Foundation/Foundation.h>
#interface Singleton : NSObject {
NSMutableArray *firstMutableArray;
NSMutableArray *secondMutableArray;
}
#property (nonatomic, retain) NSMutableArray *firstMutableArray;
#property (nonatomic, retain) NSMutableArray *secondMutableArray;
+ (id)sharedSingleton;
#end
Sigleton.m
#import "Singleton.h"
static Singleton *sharedMySingleton = nil;
#implementation Singleton
#synthesize firstMutableArray;
#synthesize secondMutableArray;
#pragma mark Singleton Methods
+ (id)sharedSingleton {
#synchronized(self) {
if (sharedMySingleton == nil) {
sharedMySingleton = [[super allocWithZone:NULL] init];
}
return sharedMySingleton;
}
+ (id)allocWithZone:(NSZone *)zone {
return [[self sharedSingleton] retain];
}
- (id)copyWithZone:(NSZone *)zone {
return self;
}
- (id)retain {
return self;
}
- (unsigned)retainCount {
return UINT_MAX;
}
- (oneway void)release {
// Never release
}
- (id)autorelease {
return self;
}
- (id)init {
if (self = [super init]) {
firstMutableArray = [[NSMutableArray alloc] initWithObjects:nil];
secondMutableArray = [[NSMutableArray alloc] initWithObjects:nil];
}
return self;
}
- (void)dealloc {
[firstMutableArray release];
[secondMutableArray release];
[super dealloc];
}
#end
Then, when you want to call your Singleton:
#import "Singleton.h"
Singleton *singleton = [Singleton sharedSingleton];
singleton.firstMutableArray = ...
singleton.secondMutableArray = ...
I want to have one object that is initialized in the delegate and I want to be able to use this object anywhere across view controllers (doesn't depend on what view I am currently at). I am guessing the solution to this would be to have a singleton class, so far I have the following:
#interface LocationManager : NSObject <CLLocationManagerDelegate>{
NSDate *enter;
NSDate *exit;
CLLocationManager * manager;
}
#property (nonatomic, retain) NSDate * enter;
#property (nonatomic, retain) NSDate * exit;
- (BOOL)registerRegionWithLatitude:(double)latitude andLongitude:(double)longitude;
+ (LocationManager *)instance;
#end
#import "LocationManager.h"
#implementation LocationManager
#synthesize enter;
#synthesize exit;
#pragma mark - CLLocationManager delegate
static LocationManager *gInstance = NULL;
+ (LocationManager *)instance
{
#synchronized(self)
{
if (gInstance == NULL)
gInstance = [[self alloc] init];
}
return(gInstance);
}
#end
Is this correct? So all I need to do to access this is just to call instance? Inside LocationManager I also want to have only one CLLocationManager, called manager.. however, where do I initialize it so I only have one? Can I do the following? Most other singleton examples doesn't have any variables in the class, so that's where I got confused
+ (LocationManager *)sharedLocationManager
{
#synchronized(self)
{
if (lm == NULL){
lm = [[self alloc] init];
lm.manager = [[CLLocationManager alloc] init];
lm.manager.delegate = lm;
}
}
return(lm);
}
Basically -- yes.
Just a couple of small things:
static LocationManager *gInstance = NULL;
instead of NULL, you should use nil, it's a convention in Objective-C.
You should also overwrite alloc, new, copyWithZone:, and mutableCopyWithZone:. From Buck/Yacktman: "Cocoa Design Patterns", p. 153:
+ (id)hiddenAlloc
{
return [super alloc];
}
+ (id)new
{
return [self alloc];
}
+ (id)allocWithZone:(NSZone *)zone
{
return [[self sharedInstance] retain];
}
- (id)copyWithZone:(NSZone *)zone
{
[self retain];
return self;
}
- (id)mutableCopyWithZone:(NSZone *)zone
{
return [self copyWithZone:zone];
}
This way, your singleton object cannot be copied. You need to call hiddenAlloc from your instance method (by the way, the method to access a Singleton object is often called sharedInstance in Objective-C).
For other singleton styles with their pros and cons, check out this question.
Personally, I prefer this style (copied from one of the answers on that link):
static MySingleton *sharedSingleton;
+ (void)initialize
{
static BOOL initialized = NO;
if(!initialized)
{
initialized = YES;
sharedSingleton = [[MySingleton alloc] init];
}
}
In fact, there's a tried-and-true method to create singletons already. Download the SynthesizeSingleton.h file (from a Cocoa with Love article). It contains a massive amount of pre-processor code which will generate any singleton for you. Hit the article for more details.
Since the factory method "instance" is a class-level method, the #synchronized block should be
#synchronized([LocationManager class]) {
//}
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.