Best way to have an application-wide array? - objective-c

I have a class which contains a method to download data from my server. This is in the form of JSON, but is parsed and put into an array. As this is a 'model' file, what would be the best way to make it so that multiple 'controllers' can access this data?

Hang it off the app delegate, stick it in a global variable, or declare a class method in appropriate spot that returns it.
Better yet, start thinking now about having a proper model layer that, among other things, can manage this data. That will make refactoring easier in the future as your application evolves.

You can create singleton object of class with array object. and by using class method you can get that array any where in app.
e.g.
in Cardnames.h file
#import <Foundation/Foundation.h>
#interface CardNames : NSObject
#property (nonatomic, retain) NSMutableArray *CardNamesArray;
+(CardNames*) getCardsList;
#end
in Cardnames.m file
#import "CardNames.h"
#implementation CardNames
#synthesize CardNamesArray;
static CardNames *cards = nil;
+(CardNames*) getCardsList
{
#synchronized(self)
{
if(cards == nil)
{
cards = [[self alloc] init];
cards.CardNamesArray = [[NSMutableArray alloc] init];
/// code to fill array
}
return cards;
}
}
#end
and in other classes u can use like this
#import "CardNames.h"
.
.
.
NSMutableArray *CardsArray = [[CardNames getCardsList] CardNamesArray];

Related

Objective-C class as NSMutableArray

Very simple question. Is it possible to create a class which is a list by it self? I mean:
I do
taskList *taskList1 = [[taskList alloc] init];
And than simply:
taskList1 addObject:[task1]
May seem stupid, but I'm totally new to O-C syntax
I'd need two methods:
-(instancetype) init;
which just initialize as an empty list
+(instancetype)taskList;
to allocate taskList instance
and last thing:
In interface i use:
#interface taskList : NSObject
or
#interface taskList : NSMuttableArray
I got stuck on something specific, didn't I? I'm sorry that I bother you with my programming level.
Alright, I gave up, just last question, because I have to finish it very soon.
I changed my approach I added
#property NSMutableArray *list;
Why does this:
taskList *TL1 =[taskList initTaskList];
task *task1 = [[task alloc] init];
task *task2 = [[task alloc] init];
TL1.list addObject:[task1];
doesn't work, I have "Expected identifier" Error
If you read the subclassing notes on NSArray / NSMutableArray you'll see that Apple recommend against subclassing them because they are a class cluster. (i.e. what you really get when you ask for one is an undocumented subclass, and the initialiser decides which undocumented subclass to return to you based on some undocumented qualifiers..
So just make an NSObject subclass which owns a (private) strong property of type NSMutableArray, and publish an api to access that array..
eg
#import "modelList.h"
//dont worry header is empty, its up to you to do that.. this is a subclass on NSObject
#interface modelList()
#property (strong, nonatomic) NSMutableArray *backingArray;
#end
#implementation modelList
#synthesize backingArray = _backingArray;
-(instancetype )init{
if (self = [super init]) {
[self setBackingArray:[[NSMutableArray alloc]init]];
}
return self;
}
//public API (the stuff that is prototyped in the header..)
-(id)objectAtIndex:(NSUInteger )index{
return [self.backingArray objectAtIndex:index];
}
-(BOOL )containsObject:(id)object{
return [self.backingArray containsObject:object];
}
-(void )addObject:(id)object{
//example application, qualifying object..
if ([object conformsToProtocol:#protocol(NSCoding)]) {
[self.backingArray addObject:object];
}
}
-(NSUInteger )count{
return [self.backingArray count];
}
//etc etc declare publicly the things you need to get the job done
#end
so far this is just a face for a mutable array obviously, but it gives you a place for whatever other model logic you need. good luck

communicating between classes with pointers

Hi all,
I'm having a hard time understanding how to use pointers
(my first time using them) hoping someone can point me in the right
direction (no pun intended) :P
(it controls the sound,pagenumber,bg,audio int, and text to be displayed)
(NSString *)textFromPlist pointer which points to the plist containing the text for #"Page01Text"
I want to take #"Page01Text" and use it in the HighLighter class
I am able to log the output for the sound,pagenumber,bg,audio int, and text etc in the hello world layer (its logging the TextManagerWithpageNum) so I know that the plist is reading,
but for some reason I cant link textFromPlist I'd like to be able to use the textFromPlist from the TextManagerWithpageNum class and let the hilighter class work with it (this class will hilight the text and work with the audio intervals supplied by the plist)
this piece of code it returns (NULL)
#interface HighLighter.h
TextManagerWithpageNum *myClassAccess;
//declaring the TextManagerWithpageNum class so I can access textFromPlist
#implementation HighLighter.m
-(NSString *)Sentance01
{
NSString *textFromTextManager = myClassAccess.textFromPlist;
NSString *storyText = [NSString stringWithFormat:#"%#",textFromTextManager];
return [[[NSString alloc]initWithString:StoryText]autorelease];
//doesn't crash but doesn't load text
NSLog(#"text form plist #%",storyText);
}
What is it that I am doing wrong? (I have an int array I also wish to link, but thought I'd start with the NSString as I thought this would be simpler.)
any help would be wonderful, kind regards,
Natalie.
#interface TextManagerWithpageNum : CCLayer
NSString* textFromPlist_Pntr;
#property(nonatomic, readonly) NSString* textFromPlist;
//NSString* textFromPlist is an item on the plist #"page01" which contains text for the page
#property(nonatomic, readonly) NSString* audioInterval;
//NSString* AudioInterval is an array on the plist #"AudioTimings_PG01"
#implementation TextManagerWithpageNum
#synthesize textFromPlist = textFromPlist_Pntr;
#synthesize audioInterval = _audioInterval;
There are a couple of options when communicating any data between classes. I will show both, using an example SomeData object that is being sent from ObjectA to ObjectB. You can also use class level methods to, for example, send or receive data in a pointer to a singleton object. I won't show you how to do that because it doesn't sound like that fits your problem.
Option 1
Define a receiving message in ObjectB.
#interface ObjectA
{
SomeData *someDataPointer;
ObjectB *someObjectB;
}
#end
#implementation ObjectA
-(void)someMethod
{
someDataPointer = [[SomeData alloc] init]; // Or whatever way you want to create and set someDataPointer
[someObjectB receiveData:someDataPointer];
// Note: if you will be calling receiveData on someObjectB much later than the
// time of creation of someDataPointer, you should retain someDataPointer to
// hold onto it until you need to pass it on.
// ie)
// [someDataPointer retain];
}
#end
#interface ObjectB
-(void)receiveData:(SomeData *)dataPtr;
#end
#implementation ObjectB
-(void)receiveData(SomeData *)dataPtr
{
// Here the data from someDataPointer will also be pointed to by dataPtr
// Use dataPtr now
[self doSomethingWithData:dataPtr];
}
#end
Option 2
Define a sending message in ObjectA.
#interface ObjectA
{
SomeData *someDataPointer;
}
#property (nonatomic, retain) SomeData *someDataPointer;
#end
#implementation ObjectA
#synthesize someDataPointer = someDataPointer_;
#end
#interface ObjectB
{
ObjectA *someObjectA;
}
#end
#implementation ObjectB
-(void)someMethod
{
SomeData *dataPtr = [someObjectA getSomeDataPointer];
// Now do something with dataPtr
}
#end
I hope that helps. I wanted to show you these two techniques generally so that you can learn to apply it to your case specifically. Let me know if you have questions.

Objective-c: Singleton - passing variables

I have a singleton that I'd like to use to manage the onscreen animation of my views. Here's my.
#import <Foundation/Foundation.h>
#interface OAI_AnimationManager : NSObject {
NSMutableDictionary* sectionData;
}
#property (nonatomic, retain) NSMutableDictionary* sectionData;
+(OAI_AnimationManager* )sharedAnimationManager;
- (void) checkToggleStatus : (UIView* ) thisSection;
#end
.m file
#import "OAI_AnimationManager.h"
#implementation OAI_AnimationManager
#synthesize sectionData;
+(OAI_AnimationManager *)sharedAnimationManager {
static OAI_AnimationManager* sharedAnimationManager;
#synchronized(self) {
if (!sharedAnimationManager)
sharedAnimationManager = [[OAI_AnimationManager alloc] init];
return sharedAnimationManager;
}
}
- (void) checkToggleStatus : (UIView* ) thisSection {
//get the section data dictionary
NSLog(#"%#", sectionData);
}
#end
You'll see in the .h file I added a NSMutableDictionary and am using #property/#synthesize for it's getter and setter.
In my ViewController I instantiate the animation manager as well as a series of subclasses of UIView called Section. With each one I store the data (x/y w/h, title, etc.) in a dictionary and pass that to the dictionary delcared in animation manager. In the Section class I also instantiate animation manager and add a UITapGestureRecognizer which calls a method, which passes along which section was tapped to a method (checkToggleStatus) in animation manager.
As you can I see in the method I am just logging sectionData. Problem is I am getting null for the value.
Maybe my understanding of singletons is wrong. My assumption was the class would only be instantiated once, if it was already instantiated then that existing object would be returned.
I do need all the other Section classes data as if one animates others animate in response and I can get around it by passing the tapped Section to the animation manager and doing [[Section superview] subviews] and then looping and getting the data from each that way but it seems redundant since that data is available in the ViewController when they are created.
Am I doing something wrong in trying to transfer that data? Is there a better solution? I am open to suggestions and criticisms.
Thanks
h file
#interface OAI_AnimationManager : NSObject
#property (nonatomic, retain) NSMutableDictionary* sectionData;
+(OAI_AnimationManager* )sharedAnimationManager;
- (void) checkToggleStatus : (UIView* ) thisSection;
#end
m file
static OAI_AnimationManager* _sharedAnimationManager;
#implementation OAI_AnimationManager
#synthesize sectionData = _sectionData;
+(OAI_AnimationManager *)sharedAnimationManager {
#synchronized(self) {
if (!_sharedAnimationManager) {
_sharedAnimationManager = [[OAI_AnimationManager alloc] init];
}
}
return _sharedAnimationManager;
}
- (void) checkToggleStatus : (UIView* ) thisSection {
//get the section data dictionary
NSLog(#"%#", _sectionData);
}
#end
Notice I moved your sectionData variable from the header and moved it to the implementation file. A while back, they changed it to where you can synthesize properties and specify their instance variable names along side it... hence:
sectionData = _sectionData;
I also added and underscore to the instance variable... this is a universal convention for private variables and it also will throw a compile error now if you try to type just sectionData as you did in the return statement of checkToggleStatus:. Now you either have to type self.sectionData or _sectionData.
You didn't include the code that creates an instance of your dictionary but I bet you didn't set it as self.sectionData = [[NSDictionary alloc] init] which means it would not retain the value and you would get null the next time you called it. Classic memory management mistake... I know it well because I learned the hard way hehehe

Structure (struct) in Xcode as Array, and global

I'm trying to create a structure, which should be used as an array.
Then at the same time I need to access it from a different view, so I'm guessing I need to make it global for now, until I learn a better way (have tried many suggestions from google searches)
But how do I declare a variable twice?
I mean both as my structure, and as an array?
Sometimes "global variables" can be appropriate, but not simply as "global variables". The proper way to do it in Objective C is with singletons.
Here is part of the .h implementation below:
#interface MySingleton : NSObject
#property (nonatomic, strong) NSMutableArray *myArray;
+ (MySingleton *)sharedSingleton
#end
And here is what the .m implementation would look like:
#implementation MySingletion
#synthesize myArray;
static MySingleton *shared = nil;
- (id)init
{
self = [super init];
if(self)
{
myArray = [[NSMutableArray alloc] init];
}
return self;
}
+ (MySingleton *)sharedSingleton
{
if(shared == nil)
{
shared = [[MySingleton alloc] init];
}
return shared;
}
Then, whenever you wanted to access this from a given class, you would #import "MySingleton.h" and access your array like so:
[MySingleton sharedSingleton].myArray
Edit: However, this does not mean that every time you need to pass data it should be done with a singleton. Singletons are correct in certain situations, but as others have mentioned, you should pass the data to the next class yourself in most situations.
Well i just created a new h and m fil, where i put a lot of varibales
using extend in the.h file
and alloc init in the .m file
Then i just include this file where i need the variables. Probably there is a much better way, but this was the only one i could figure out.

Variable access in multiple classes

I have a Cocoa project with an object that holds information from a SQLite database.
By now the information is stored in memory by this object and is used in the user interface to read and write new information.
But now I came to a small problem... I decided to create a new controller class to handle the actions of an NSTableView and I want to access this same database object that was declared elsewhere.
Which is the best option to access this information? I wish to avoid loading the information more than once in memory and also avoid use pure C/C++ codes with global variables.
It is better to understand my point by looking at the code.
I accept other solutions as well, naturally.
My idea of code is currently like this:
FirstClass.h
#import <Foundation/Foundation.h>
#import "DatabaseModel.h"
#interface FirstClass : NSObject {
IBOutlet NSScrollView *informationListTable;
NSMutableArray *informationList;
}
#end
FirstClass.m
#import "FirstClass.h"
#implementation FirstClass
- (void)awakeFromNib{
DatabaseModel *list = [[DatabaseModel alloc] init];
informationList = [[NSMutableArray alloc] initWithArray:[list loadList]];
[list release];
[machinesListTable reloadData];
}
SecondClass.h
#import <Foundation/Foundation.h>
#interface SecondClass : NSObject {
IBOutlet NSTextField *labelName;
NSString *name;
}
- (IBAction)showName:(id)sender;
#end
SecondClass.m
#import "FirstClass.h"
#import "SecondClass.h"
#implementation SecondClass
- (IBAction)showName:(id)sender{
/*
Here name must get something like:
[[FirstClass.informationList objectAtIndex:3] name]
Here labelName must display name.
*/
}
#end
you can either create the object once then pass the object around, with each controller retaining it as needed. Or you can use a singleton instance. I would say the singleton instance is easier to read, but it depends on the application
One solution would be to make FirstClass a singleton. Then, anywhere else in your code, you could call [FirstClass sharedInstance] (replace sharedInstance with the name you'll give to your class method) and use this object. You'll have to be careful about concurrency issues though.