Passing Objects Between Classes
In my AppDelegate, I download some data from the internet and store it into an array. I want one of my ViewControllers to access that array. How would I go about in doing so? Is this a good situation to implement a delegate or a protocol? If so, can someone recommend a good tutorial for that?
Thank you
EDIT:
Please note that the data refreshes upon each launch so there is no need for Core Data or plists. Furthermore, the d开发者_如何转开发ata are custom objects which I created so they can't be stored in a plist for example.
You have 2 options:
- Implement a delegate protocol
- Use NSNotifications
The advantages/disadvantages of each is set out well in this question and answer: Delegates v Notifications
As notifications are easier to implement and may well be sufficient for your needs, you can implement it with the following steps:
- In the class where you download the data: When the data has been downloaded and the array populated, include the following lines:
NSDictionary *dict = [NSDictionary dictionaryWithObject:array forKey:@"Data"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"DataDownloaded" object:self userInfo:dict];
- In the class where you want to receive the data:
2.1 Add the following line to your viewDidLoad method:
`[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dataDownloaded:) name:@"DataDownloaded" object:nil];
2.2 Create the dataDownloaded selector:
(void)dataDownloaded:(NSNotification *)note {
NSDictionary *dict = note.userInfo; NSArray *dataArray = [note.userInfo objectForKey:@"DataDownloaded"];
2.3 Add the following line to dealloc and viewDidUnload:
[[[NSNotificationCenter defaultCenter] removeObserver:self];
You can store data in plist file and use it in all view controllers. This way, you need not worry about the size of data (as you will load it on demand and free it immediately).
if you want to store your array in delegate then in any view you have to create reference of your delegate and you can access your array in that view like :
in your other view you have to write : in .h file
#import "YourDelegateFile.h"
and declare a varialble
YourDelegateFile *appDelegate ;
in your .m file :
- (void) viewDidLoad
{
appDelegate = (YourDelegateFile *)[UIApplication sharedApplication] delegate];
NSArray *aArray = [appDelegate yourArrayName]; //yourArrayName is an array that you have declare in delegate
}
hope it helps you.
you just need to access the data stored within the appdelegate. I dont think this is the best solution to your problem but in order to do things the way you want.
so declare you property in your Appdelegate .h file
NSMutableArray* myArray_;
then add a property to the same file
@property (nonatomic, retain) NSMutableArray* myArray;
in the .m file
make sure you synthesize your property
@synthesize myArray = myArray_;
somewhere in your appdelegate .m file you will set the value
then, elsewhere in your code you can access the property in the appdelegate like so
MyAppDelegate *appDelegate = (MyAppDelegate *)[UIApplication sharedApplication].delegate
NSMutableArray* localArray = appDelegate.myArray;
Note, for good encapsulation you should really use an NSArray but i used mutable to keep the code short.
Also, using the appdelegate as a global store for program data is not a good idea, it breaks a lot of rules you shouldnt break, single responsibility principle being a good one to start with. You should ideally be storing application data in a dedicated class, perhaps a singleton or for much better testability a single instance class served by a factory class. This way you data is accessible from a known well defined entity, it is testable and it honours good design principles
You can send notification if app delegate got new data and all interested controllers will know that they need to update views. For this you can use NSNotificationCenter
. For example
- (void)newDataLoaded {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:arrayOfData forKey:@"data"];
[[NSNotificationCenter defaultCenter] postNotificationName:@"data updated notification name" object:nil userInfo:userInfo];
}
If some controller interested in data updates it should subscribe for this notification as soon as possible:
- (void)viewDidLoad {
...
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(dataUpdatedNotificationHandler:) name:@"data updated notification name" object:nil];
...
}
Do not forget to unsubscribe from notifications if you don't need it. For this use [[NSNotificationCenter defautCenter] removeObserver:self]
in viewDidUnload
and dealloc
methods.
- (void)dataUpdatedNotificationHandler:(NSNotification*)notification {
NSArray *data = [[notification userInfo] objectForKey:@"data"];
// update your view here
}
精彩评论