I have create a SinglestonClass in my code but i have a problem.
My variable are initialized in the -init method but when i call the singlestonClass these variable are re-initialize.
Can you help me for create a single initialization for my variable?
thanks.
#implementation SingletonController
#synthesize arrayPosition;
#synthesize arrayMovement;
#synthesize actualPosition;
#synthesize actualMove;
#synthesize stopThread;
+(SingletonController*)sharedSingletonController{
static SingletonController *sharedSingletonController;
#synchronized(self) {
if(!sharedSingletonController){
sharedSingletonController = [[SingletonController alloc]init];
}
}
return sharedSingletonController;
}
//I don't want a re-initialization for these variables
-(id)init{
self = [super init];
if (self != nil) {
arrayPosition = [[NSMutableArray alloc]init];
arrayMovement = [[NSMutableArray alloc]init];
actualPosition = [[Position alloc]init];
actualMove = [[Movement alloc]init];
stopThread = FALSE;
}
return self;
}
-(void) dealloc {
[super dealloc];
}
#end
Your init method should not be called by anyone except for your singleton class itself. That's what the sharedSingletonController method is for. This is your factory method that is responsible for returning the same static instance of your class. I'd also suggest that you rename the static instance of your singleton object and/or the sharedSingletonController selector itself to disambiguate between the two and for cleaner design. In this particular case, it may confuse someone who has to read your code.
Without seeing how the client code is calling on your singleton factory method, it's difficult to decipher where your problem is. We'd need to see the rest of the code including how it's being called. In your client code, you should be using something such as:
SingletonController *sigController = [SingletonController sharedSingletonController];
DO NOT DO:
SingletonController *sigController = [[SingletonController alloc] init];
Read here for more information in the Cocoa Fundamentals Guide.
Related
This question already has answers here:
Using a singleton to create an array accessible by multiple views
(2 answers)
Closed 9 years ago.
I have created a singleton class in Objective C. Like the one below:
#interface SingletonClass : NSObject{
NSMutableArray *instanceArray;
}
#property(nonatomic,retain)NSMutableArray *instanceArray;
+(SingletonClass*)sharedInstance;
#end
#implementation SingletonClass
#synthesize instanceArray;
static SingletonClass *sharedInstance =nil;
+(SingletonClass*)sharedInstance
{
if(sharedInstance==nil){
sharedInstance=[[super allocWithZone:NULL]init];
}
return sharedInstance;
}
-(id)init{
self=[super init];
if(self){
instanceArray=[[NSMutableArray alloc]init];
[instanceArray addObject:#"One"];
[instanceArray addObject:#"Two"];
}
return self;
}
+(id)allocWithZone:(NSZone *)zone{
return [self sharedInstance];
}
#end
I know it can be accessed from anywhere with the following piece of code:
SingletonClass *singletonObject=[SingletonClass sharedInstance];
And the instanceArray can be accessed anywhere by singletonObject.instanceArray.
Now my question is, is is possible to modify the array by adding new objects to it ? Will that be persisted ? Because i tried to add an object from one class
[singletonObject.instanceArray addObject:#"Three"];
When i checked the array contents from another class, the array consisted of only two values which are initialized by default. The value which i added from another class didnt show up.
What could be the problem ? Am I missing something here ? Please help.
Drop the allocWithZone: implementation entirely. It is prone to error and a distinctly odd thing to do. The reality is that if you have code that is using your singleton class and not going through sharedInstance then that code is broken. Attempting to hide that brokenness is just going to cause pain later.
Just do this one:
+(instancetype)sharedInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[SingletonClass alloc] init];
});
return sharedInstance;
}
If you aren't seeing updates to the array in your other class, then there is some other bug.
Your implementation of allocWithZone: is never called because you are calling the [super allocWithZone:], also i don't think you need this method.
i would change your class method with this:
+(instancetype)sharedInstance
{
if(sharedInstance==nil){
sharedInstance = [[SingletonClass alloc]init];
}
return sharedInstance;
}
and if you want to be more secure that you are not going to create another instance of your object use dispatch_once:
+(instancetype)sharedInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[SingletonClass alloc] init];
}
return sharedInstance;
}
I think that you forgot the ! before self in init method :
-(id)init {
self = [super init];
if(!self) {
instanceArray=[[NSMutableArray alloc]init];
[instanceArray addObject:#"One"];
[instanceArray addObject:#"Two"];
}
return self;
}
That's why each time you get a new instance of your singleton
#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
Normally, you define init or initWith... methods and call them inside convenient constructors like this:
#implementation MyClass1 : NSObject
#synthesize n, s;
-(id)init
{
self = [super init];
if (self) {
self.n = 1;
}
return self;
}
-(id)initWithString:(NSString *)s
{
self = [self init];
if (self) {
self.s = s;
}
return self;
}
+(id)myClass
{
return [[self alloc] init];
}
+(id)myClassWithString:(NSString *)s
{
return [[self alloc] initWithString:s];
}
#end
But I think it is possible to define convenient constructors without defining init or initWith... methods like this:
#implementation MyClass2
#synthesize n, s;
+(id)myClass
{
MyClass2 *obj = [[self alloc] init];
obj.n = 1;
return obj;
}
+(id)myClassWithString:(NSString *)s
{
MyClass2 *obj = [self myClass];
obj.s = s;
return obj;
}
#end
Is it bad practice to define convenient constructors without defining init method?
If it is bad practice, could you tell me the disadvantage or problems?
I'm not sure if it's actually a bad practice. Generally, when I write convenience constructors they look like this:
+ (FSClub *)clubWithXMLElement:(SMXMLElement *)element;
{
FSClub *club = [[FSClub alloc] init];
if (club)
{
club.identifier = [element integerValueWithPath:#"id"];
club.name = [element valueWithPath:#"naam"];
club.referer = [element URLWithPath:#"referer"];
}
return club;
}
The code still takes into account possible memory issues (initialisation failure) like in a 'normal' init constructor. Values will only be set if initialisation is successful.
The interface file is defined as such:
#interface FSClub : NSObject
#property (nonatomic, assign, readonly) NSInteger identifier;
#property (nonatomic, copy, readonly) NSURL *referer;
#property (nonatomic, copy, readonly) NSString *name;
+ (FSClub *)clubWithXMLElement:(SMXMLElement *)element;
#end
Please note the properties are readonly. I prefer creating immutable objects, since they're easier to deal with in e.g. threaded code. The only way to have the properties set in this situation is by using the convenience constructor.
When I create the convenience constructors, these are generally the only methods I use to instantiate the objects. That is to say, the -init method will not be used most of the time. Also, writing lots of initialisers even if you don't use them takes lots of developer time. I wouldn't create methods that I don't use.
When you create code as part of a framework -code that you share with lots of people that you don't know- in such situations you might want to write both the convenience constructors as well as all the normal constructors, because you can't be sure how the code will be used in people's own project. For example creating lots of objects using convenience constructors in tight loops might be bad for performance, since the objects are added to the autorelease pool. I think this is also true in an ARC scenario. In such situations one might have the option to use 'normal' constructors to create objects.
//I think it is BAD. First of all, you confused CLASS and OBJECT, you get an object like this
// [[CLASSNAME alloc] init];
//not like this:
// [[OBJECT alloc] init];
//so, what you want to do shall be like this:
// +(id)myClass
// {
// MyClass2 *obj = [[[self class] alloc] init];
// obj.n = 1;
// return obj;
// }
PLEASE ignore above all, thanks to #W'rkncacnter.
however, here you are returning an object owned by yourself without autorelease, it's not recommended.
Maybe what you really want is something like factory method?
+(id)myObjectWithString:(NSString *)string
{
MyClass2 *obj = [[[MyClass2 alloc] init] autorelease];
obj.s = string;
return obj;
}
Doing it like you did with MyClass1 makes it easier to define a designated initializer. Apple recommends these; they help reducing code repetition.
suppose I got a singleton class MySingleton as coded below.
Now is a singleton class just like any other class. I can have instance variables that are nonatomic and retain?
I can have: #property (nonatomic, retain) NSString* instanceVar in the .h file
and #synthesize instanceVar in the .m file?
static MySingleton* _sharedMySingleton = nil;
+(MySingleton*)sharedMySingleton
{
#synchronized([MySingleton class])
{
if (!_sharedMySingleton)
[[self alloc] init];
return _sharedMySingleton;
}
return nil;
}
+(id)alloc
{
#synchronized([MySingleton class])
{
NSAssert(_sharedMySingleton == nil, #"Attempted to allocate a second instance of a singleton.");
_sharedMySingleton = [super alloc];
return _sharedMySingleton;
}
return nil;
}
Yes, the instance of a singleton class behaves the same as a standard class, there is just one instance.
The pattern you have is overly complicated, there is no need for +(id)alloc
Here is a simplier pattern:
#implementation MySingleton
static MySingleton* _sharedMySingleton = nil;
+(MySingleton*)sharedMySingleton
{
#synchronized([MySingleton class])
{
if (!_sharedMySingleton)
_sharedSingleton = [[MySingleton alloc] init];
}
return _sharedMySingleton;
}
You bet. To the rest of your application, your singleton looks and works just like any other class. The only difference is that when your application tries to create a new singleton it always receives back the same object. But the singleton can have instance methods and instance variables just like any other class.
Not familiar with the annotations you mentioned because I'm a C++ developer, but a singleton can certainly have instance data. That's one of its values.
Yes you can have instance variables, a singleton is simply a regular class, where there is only one instance at any given time.
I've been working through some objective-c/ iOS dev books and I've hit a stumbling block. I get the feeling that I'm missing something dumb here, so I'm sure you guys can help, because you're all so damn smart :-).
I've got a very simple app that consists of 1 button and 1 label. Pushing the button puts a message in the label. I've created a class that includes a method to create said message. Here is the problem:
#import "classTestViewController.h"
#implementation classTestViewController
#synthesize myLabel;
- (void)viewDidLoad
{
}
-(IBAction) pressGo:(id)sender{
MyClass * classTester = [[MyClass alloc] init];
classTester.count = 15;
NSString *newText = [classTester makeString ];
myLabel.text = newText;
}
- (void)dealloc
{
[classTester release];
[myLabel release];
[super dealloc];
}
The output of this app, in my label, is "Yay 15". So you can see the problem, the only way I can get this to work is to instantiate the class right there, in the "pressGo" method. This isn't desirable because another method can't access or change the class variable count. Also I get a warning that local declaration of classTester hides instance variable. If I move the class instantiation to the viewDidLoad method, which seems right, the other methods can't access it anymore.
#import "classTestViewController.h"
#implementation classTestViewController
#synthesize myLabel;
- (void)viewDidLoad
{
MyClass * classTester = [[MyClass alloc] init];
}
-(IBAction) pressGo:(id)sender{
classTester.count = 15;
NSString *newText = [classTester makeString ];
myLabel.text = newText;
}
- (void)dealloc
{
[classTester release];
[myLabel release];
[super dealloc];
}
The output of that is nada. If I try to access just one variable, classTester.count, for example, even after setting it, I get a 0 value. I also get the override warning here as well.
So my question is, how can i get access to that class instance throughout my app and not just in one method? I'm using a view based application.
Declare classTester in your interface file with:
#class MyClass
#interface classTestViewController : UIViewController
{
MyClass *classTester;
}
// Any other custom stuff here
#end
Then instantiate it in your viewDidLoad method with:
classTester = [[MyClass alloc] init];
And you should be able to access the ivar from any method within this class. If you want it to be accessible to your entire app, #Waqas link will point you in the right direction.
You need to create a singleton class which instantiate once and is available inside whole project
Have a look
http://projectcocoa.com/2009/10/26/objective-c-singleton-class-template/