boscarol
boscarol

Reputation: 1941

Using AppDelegate for global readonly data

I have a project on iPhone with iOS4.

A instance variable of app delegate is a dictionary with global readonly data loaded from a plist when app starts.

CalculatorAppDelegate.h

 #import <UIKit/UIKit.h>
 @class MainViewController;

 @interface CalculatorAppDelegate : NSObject <UIApplicationDelegate> {
 NSDictionary *RGBSpacesDictionary;
 }

 @property (nonatomic, retain) IBOutlet UIWindow *window;
 @property (nonatomic, retain, readonly) NSDictionary *RGBSpacesDictionary;
 @property (nonatomic, retain) IBOutlet MainViewController *mainViewController;
 @end

CalculatorAppDelegate.m

 #import "CalculatorAppDelegate.h"
 #import "MainViewController.h"
 @implementation CalculatorAppDelegate

 @synthesize mainViewController=_mainViewController;
 @synthesize RGBSpacesDictionary;

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
 {
     // load plist 
     NSString* plistPath1 = [[NSBundle mainBundle] pathForResource:@"RGBSpaces" ofType:@"plist"];
     RGBSpacesDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath1];

    etc.
 }

Then in MainViewController i am able to successfully reading the dictionary in viewDidLoad

MainViewController.h

 @class CalculatorAppDelegate;
 @interface MainViewController : UIViewController <FlipsideViewControllerDelegate> {
 CalculatorAppDelegate *appDelegate;
 }
 @property (nonatomic, retain) CalculatorAppDelegate *appDelegate;

 etc.
 }

MainViewCOntroller.m

 #import "CalculatorAppDelegate.h"
 @implementation MainViewController
 @synthesize appDelegate;

 - (void)viewDidLoad
 {
     [super viewDidLoad];
     appDelegate = [[UIApplication sharedApplication] delegate]; 
     RGBSpacesCount = (int) [appDelegate.RGBSpacesDictionary count];
 }

In viewDidLoad it is all OK, I can read my dictionary as appDelegate.REGSpaceDictionary.

The problem is with another method of MainVievController called when a button is pressed

- (IBAction) RGBSpaceButtonPressed {
     NSLog(@"appDelegate.RGBSpacesDictionary %@", appDelegate.RGBSpacesDictionary);

 etc.
 }

At this time calling the dictionary (for example with a NSLog) return in a crash.

Can someone help me? Thank you.

Upvotes: 1

Views: 835

Answers (2)

Paul.s
Paul.s

Reputation: 38728

In this line

RGBSpacesDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath1];

you are assigning an autoreleased object straight to the ivar so there is no guarantee how long it will stay around for. You should be assigning a non autoreleased object or going through the setter

// Going through the setter
self.RGBSpacesDictionary = [NSDictionary dictionaryWithContentsOfFile:plistPath1];

// OR
// Non assigning a non autoreleased object
RGBSpacesDictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath1];

To use the setter you would have to redeclare the property in an extension at the top of the app delegate's .m file like this

@interface CalculatorAppDelegate ()
@property (nonatomic, retain, readwrite) NSDictionary *RGBSpacesDictionary;
@end

...

The rest of your implementation

Upvotes: 3

user756245
user756245

Reputation:

Try to retain the dictionary in app delegate. It must be deallocated at some point, because you get an autoreleased one and you didn't use the property to set it.

// here you must retain the dictionary
[[NSDictionary dictionaryWithContentsOfFile:plistPath1] retain];

Of course don't forget to release it later in dealloc.

Upvotes: 1

Related Questions