Initialize properties in Singletons in objective-c - iphone

So I'm kind of unsure about something. What I want is one class to know about the data through all my different view controllers. This one class should have an array of my objects so that if I have a detailViewController, I would just be looking at one instance in my array that the DataManager would hold. I thought that this DataManager would be a singleton. I followed Apple's documentation on creating a singleton, but now I'm a bit confused on the properties.
static DataManager *sharedDmgr = nil;
+ (id)sharedInstance {
if (sharedDmgr == nil) {
sharedDmgr = [[super allocWithZone:NULL] init];
}
return sharedDmgr;
}
If I want an NSMutableArray property, what is the proper way to initialize it? Do I do something like
+ (id)sharedInstance {
if (sharedDmgr == nil) {
sharedDmgr = [[super allocWithZone:NULL] init];
[self sharedInit];
}
return sharedDmgr;
}
- (void)sharedInit {
// initialize all my properties for the singleton here?
}
Thanks!

Let's say a DataManager object has a NSMutableArray attribute named "array", then your objective is to be able to do [DataManager sharedDataManager].array in all your code.
The way to do it would be to:
Declare the NSMutableArray *array as an attribute on the DataManager.h #interface block.
Declare a #property for that attribute.
On the - [DataManager init] method initialize the mutable array. Something like self.array = [NSMutableArray array];
Then your sharedInstance method would be:
static DataManager *sharedDmgr = nil;
+ (id)sharedInstance {
if (sharedDmgr == nil) {
sharedDmgr = [[DataManager alloc] init];
}
return sharedDmgr;
}
All done. Let me know if you need some example code.

You can use the same lazy initialization pattern for your property getters. So for a mutable array...
#interface DataManager ()
#property (strong, nonatomic) NSMutableArray *array;
#end
#implementation DataManager
#synthesize array=_array;
// shared instance method like #fbernardo's suggestion
- (NSMutableArray *)array {
if (!_array) {
_array = [[NSMutableArray alloc] init];
}
return _array;
}

Related

How to declare constant values in nsarray in ios

I had declared constant NSArray like the below way.
static NSArray* const myArray = [NSArray arrayWithObjects:#"obj1",#"obj2",#"ibj3",#"obj4",#"obj5",nil];
But it shows an error "Initiliser elements are Not Compile time constants".
So I declared like this.But I got the error.
Please help This Case.
Thanks.
Since NSArrays are heap-allocated objects, you cannot create them in a static context. You can declare the variables, and then initialize them in a method.
So, you can do this way :-
static NSArray *myStaticArray = nil;
- (void) someMethod
{
if (myStaticArray == nil)
{
myStaticArray = [[NSArray alloc] init...];
}
}
Hope it helps you..
I don't see why you cannot use this to solve your problem. it is 100% constant, because the NSArray is immutable, and it is also 100% static.
GlobalConstant.h file:
#import <Foundation/Foundation.h>
// EDITED : __unused static NSArray *_myGlobalArray;
#interface GlobalConstant : NSObject
+ (NSArray *)myGlobalArray;
#end
GlobalConstant.m file:
#import "GlobalConstant.h"
#implementation GlobalConstant
+ (NSArray *)myGlobalArray {
static NSArray *_myGlobalArray = nil; // EDITED
#synchronized (_myGlobalArray) {
if (_myGlobalArray == nil) {
_myGlobalArray = [NSArray arrayWithObjects:#"1", #"2", nil]; // here is your array...
}
return _myGlobalArray;
}
}
#end
...and your array will be available in every class which includes the GlobalConstant.h file, you can reach the array like
NSArray *_globalArray = [GlobalConstant myGlobalArray];
To create the static array you can make use of the initialize method. This is a special class method that every class has. It is called the first time a class is referenced in any way and before any other code in the class is executed.
static NSArray* myArray = nil;
#implementation SomeClass
+ (void)initialize {
if (self == [SomeClass class]) {
myArray = #[ #"obj1", #"obj2", #"obj3", #"obj4", #"obj5" ];
}
}
// rest of methods
#end
and, to save typing, you can use NSArray* myArray = #[ #"obj1", #"obj2", #"ibj3", #"obj4", #"obj5" ];

NSMutableArray within singleton class always returns count 0 / never retains its objects

My simplified singleton looks like this:
#interface MyClass : NSObject {
NSMutableArray * myArray;
}
+ (MyClass*) instance;
#property(nonatomic,retain)NSMutableArray *myArray;
Then in the implementation
static MyClass * myinstance;
#synthesize myArray;
+ (MyClass*) instance {
if(myinstance == nil)
myinstance = [[MyClass alloc] init];
return myinstance;
}
- (id) init {
if(self = [super init]) {
myArray = [[NSMutableArray alloc] initWithCapacity:2];
[myArray addObject:#"Trauma"];
}
return self;
}
However when I try to access it for a tableview this always returns 0:
[[[MyClass instance] myArray] count];
Little unsure about what I'm doing wrong
The method that returns the instance of your singleton is named +instance, but when attempting to access your singleton, you are using +myinstance. Your instance of MyClass is most likely nil.

how do I build up a global like integer array?

How do I build up a global like integer array?
I tried variations of the following:
#interface
int *iArray; //this space will vary depending upon need in the implementation
#implementation
...
int iArrayInit[4] = {1,2,3,4};
iArray = iArrayInit;
-bottom line: I need to keep index values in array that I can access easily, and use of [NSArray intValue] maybe to slow.
thanks
If it needs to be static you can declare an NSMutableArray as static in the implementation file and expose static methods to access it. When using an NSArray the values need to be of type id which NSNumber can do. Here is an example which currently is not thread safe.
//.h file
#interface Foo : NSObject
{
}
+(NSArray*)iArray;
+(void)addiArrayValue:(NSNumber*)value;
#end
//.m file
#implementation Foo
static NSMutableArray *_iArray;
+(void)initialize
{
if([Foo class] == self)
{
_iArray = [[NSMutableArray alloc] init];
}
}
+(NSArray*)iArray
{
return [[_iArray copy] autorelease];
}
+(void)addiArrayValue:(NSNumber*)value
{
[_iArray addObject:value];
}
#end
//Use
[Foo addiArrayValue:[NSNumber numberWithInt:10]];
[Foo addiArrayValue:[NSNumber numberWithInt:12]];
NSLog(#"%#", [Foo iArray]);

invalid CFArrayRef problem with Singleton object

I've built a singleton object to manage some data in my app
#interface MyCommon : NSObject {
NSArray *quizz;
int iCurrentQuestion;
};
+ (MyCommon *)singleton;
#property (retain) NSArray *quizz;
#property (assign) int iCurrentQuestion;
#end
MyCommon.m
#import "MyCommon.h"
// MyCommon.m:
#implementation MyCommon
static MyCommon * MyCommon_Singleton = nil;
#synthesize iCurrentQuestion;
+ (MyCommon *)singleton
{
if (nil == MyCommon_Singleton)
{
MyCommon_Singleton = [[MyCommon alloc] init];
NSLog(#"allocating MyCommon_Singleton at %#",MyCommon_Singleton);
}
else {
NSLog(#"accessing singleton : %#", MyCommon_Singleton);
}
return MyCommon_Singleton;
}
- (NSArray*) getQuizz{
return quizz;
}
- (void) setQuizz:(NSArray *)array {
quizz = [NSArray arrayWithArray:array];
NSLog(#"setQuizz : %#",quizz);
}
There is no problem for writing the quizz object (setQuizz), however when I try to access it for reading, I get a crash : the quizz looks invalid and Xcode notify me an invalid CFArrayRef
I don't know what's wrong with my code.
You provide a custom setter for quizz but it doesn't comply with how the property is declared.
You're not retaining quizz when you're setting a new value. It's likely to be released just after, leading to a crash when you access it.
You should write
- (void)setQuizz:(NSArray *)array {
if (quizz != array) {
NSArray *tmp = quizz;
quizz = [array retain]; // retain the new value
[tmp release]; // release the old one
}
NSLog(#"setQuizz : %#",quizz);
}
this is way more code than it needs to be. First if you are going to be providing your own method you should declare so in the #property declaration which you didn't. Also your not properly retaining your variables. Additionally you should be using dispatch_once() for a thread safe & fast way to guarantee the singleton is only created once.
#interface MyCommon : NSObject {}
#property(nonatomic, retain) NSArray *quiz;
#property (assign) int iCurrentQuestion;
+ (MyCommon *)singleton;
#end
#implementation MyCommon
#synthesize quiz;
#synthesize iCurrentQuestion;
-(id)init {
self = [super init];
if(self) {
quiz = [[NSMutableArray alloc init];
iCurrentQuestion = 0;
}
return self;
}
+ (MyCommon *)singleton {
static MyCommon *singleton = nil;
static dispatch_once_t pred;
dispatch_once(&pred, ^{
singleton = [[MyCommon alloc] init];
});
return singleton;
}
#end
then you just do
[MyCommon singleton].quiz = //some array

As for iPhone Application Development, it is a question

I am developing iPhone Application.
MyApplicationData.h
#import <Foundation/Foundation.h>
#interface MyApplicationData : NSObject {
NSMutableArray* appData;
}
#property (retain) NSMutableArray* appData;
-(void)loadData;
-(void)addAppDataItemPrice:(NSString*)price itemCategory:(NSString*)category itemDate:(NSDate*)date;
-(void)forDebug;
+(id)instance;
#end
MyApplicationData.m
#import "MyApplicationData.h"
#implementation MyApplicationData
+ (id)instance
{
static MyApplicationData* _instance = nil;
if (!_instance) {
_instance = [[MyApplicationData alloc] init];
}
return _instance;
}
-(void)loadData{
appData = [NSMutableArray array];
NSLog(#"%#",appData);
}
-(void)forDebug{
}
-(void)addAppDataItemPrice:(NSString*)price itemCategory:(NSString*)category itemDate:(NSDate*)date{
NSLog(#"%#", appData);
[appData addObject:#"1"];
NSLog(#"%#", appData);
}
#end
another class
[[MyApplicationData instance] loadData];
one another class
[[MyApplicationData instance] addAppDataItemPrice:price itemCategory:category itemDate:date];
log
[Session started at 2009-11-03 21:04:41 +0900.]
2009-11-03 21:04:44.742 XXX[24002:207] (
)
2009-11-03 21:04:46.612 XXX[24002:207] (null)
It is not executed. What is the cause?
I think this line might be the cause:
appData = [NSMutableArray array];
try this instead:
appData = [[NSMutableArray alloc] init]
You'll want to make sure you release it as well when your MyApplicationData instance is destroyed (not critical in this case since it's a singleton, but still good practice)
It looks like your array is getting autoreleased after the method:
[[MyApplicationData instance] loadData];
I think it should be a member of the class, you can use the property syntax to help.
Set it up in the header file as:
#property (nonatomic, retain) NSMutableArray *appdata;
Then in the implementation:
#synthesize appdata;
Assign it as follows:
-(void)loadData{
self.appData = [NSMutableArray array];
}
Don't forget to release it in your dealloc method
When you set it in your code you can call it like the following:
[self.appData addObject:#"1"];