where to store "global" objects in iOS [duplicate] - objective-c

This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
How or where should I store object instances that I require globally within my iOS app?
I have some global object (uses in almost all Application Screens) and mostly they are created right after application starts. I want to have access to this objects from all my ViewControllers (nothing else, only ViewControllers). Where to store it?
I think about #property in AppDelegate but i think (but I can be wrong) this is a ugly solution.
Objects can be quite complex, this is not a simple types.

You can make global objects accessible by placing them in a class with class methods for accessing global objects, implementing +(void)load to prepare these objects, and storing them in static variables.
Header:
#interface GlobalObjects
+(void)load;
+(MyObject1*)myObject1;
#end
Implementation:
#import "GlobalObjects.h"
static MyObject1* _myObject1 = nil;
#implementation GlobalObjects
+(void)load {
_myObject1 = [[MyObject1 alloc] init];
}
+(MyObject1*)myObject1 {
return myObject1;
}
#end
Usage:
MyObject1 *shared = [GlobalObjects myObject1];
You could also make the variable static inside its method for lazy initialization.

Yeah I use properties of the App Delegate, then access them by casting the sharedApplication delegate property.
__weak AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
Hope this helps,
Jonathan

#property in AppDelegate is a good solution. You could also use a singleton.

You app delegate is fine if you just have a bunch of objects.
Otherwise you might build a sort of "model object" containing all of your global data.
Or, you might store them with Core Data, if they have any structure at all.
But, as I said, if you have just a couple of objects, the app delegate will just do fine.

if it's only used among view controllers, you might consider storing it in the highest level view controller which actually needs access to the shared object (when creating/pushing new controllers, set that reference counted property).
in this way, you might think of the master view controller populating the detail view controllers with their content/models.
that's really stepping away from qualification as (and burdens of) a global.

Related

Difference of private variable and property declared in class extension [duplicate]

This question already has answers here:
Is there any reason to declare ivars if you're using properties exclusively in Objective-C?
(4 answers)
Closed 8 years ago.
I'm new to Objective-C, and I saw some open sourced code like below:
DetailedViewController.m:
#interface DetailedViewController()
#property(nonatomic, strong) UITableView *dynamicTable;
#end
#implementation DetailedViewControll
-(void)viewDidLoad
{
[super viewDidLoad];
self.dynamicTable=[[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
//configure dynamicTable
}
#end
if I declare the dynamicTable variable and use it as below:
#interface DetailedViewController()
{
// private tableview variable
UITableView *dynamicTable;
}
#end
#implementation DetailedViewControll
-(void)viewDidLoad
{
[super viewDidLoad];
dynamicTable=[[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
//configure dynamicTable
}
#end
I think the the above two ways of using dynamicTable variable are equal, Am I right?
if not, Does using property is better than using private variable?
Quote from Apple docs, explaining properties:
Practically speaking, properties reduce the amount of redundant code you have to write. Because most accessor methods are implemented in similar ways, properties eliminate the need to implement a getter and setter method for each property exposed in the class. Instead, you specify the behavior you want using the property declaration and then synthesize actual getter and setter methods based on that declaration at compile time.
In your case above two ways are equal. But if you want to use some advanced technics, such as Lazy Instantiation or Key-Value Observing, you'll definitely need properties.
Accessing a variable is faster than accessing a property. However, a property gives you some advantages like key-value observing (another object or your object can register to be notified once someone changes the value of the property). Which one to use is a matter of taste and use-case.
If you declare a property in your public .h file, other objects can access it. If you declare your variable in your public .h file, other objects can access it as well (object->variable) but this very, very bad, don't do that.
So strictly speaking, your two examples are not equal. They are, however, similar. Quite often it doesn't really matter which one you use. Use whichever suits you more. The fact that variable access is faster is not a good reason to chose one over the other except if you measured and know that a property is causing a performance problem (I have yet to see that, and I work on multimedia apps that need to be fast).

Saving UIViewController in appDelegate

I am using Xcode 4.3 and need to know the parent view controller of the current view.
I am also using storyboard.
self.parentViewController always returns nil.
I saw different answers to save the parent view controller in AppDelegate class as a property. E.g., To create a variable: UIViewController parentViewController in AppDelegate and in the code write:
appDelegate.parentViewController = self;
I am afraid that it will consume memory - as this is a heavy object.
What is the best approach to know aretnViewController when using story board?
Whether or not an object is "heavy" does not matter as long as you store only a reference to it (in your case in the application delegate). Creating a second object would make a difference, but the line
appDelegate.parentViewController = self;
does not do that, it merely stores a reference to the object.
I know that this does not answer your direct question, but I think you should go ahead with the "store a reference in the app delegate" approach.

NSUserDefaults IOS Accessible Everywhere?

I am wondering if the NSUserDefaults object is shared and can be accessed from within the app delegate as well as within several of my view controllers. Basically I need to pass data from the app delegate back and forth to the view controllers. I don't want to use a singleton. I was wondering if the NSUserDefauflts object was a way to do this.
If this is possible, how would I initialize the object so that is possible?
Thanks!
If you just use [NSUserDefaults standardUserDefaults], the same instance will be returned every time. Different classes can then use it to store data that is persistent across sessions.
If you're just trying to pass data between parts of the app, but not store it, user defaults are not the appropriate way to do so. You should expose methods or properties on your classes that take as input the data you need to pass.
Well, it is but that's not really what it's designed for. The normal design pattern is to pass the objects back and forth between your view controllers "manually." You want your view controllers to be as independent -- reusable -- from the rest of your application as possible. Tying them to NSUserDefaults isn't a good way to do that!
You should not be doing any processing in your app delegate. Ideally, you should initialise your window, root view controller (if not doing it by storyboard) and model and that's it. All processing should be done elsewhere (mostly in view controllers talking to the model classes).
Make your root model class a singleton so that all your view controllers can talk to it via an interface of your choosing.
Making a singleton is not hard:
#interface MyModel: NSObject
+ (MyModel *)sharedModel;
#end
and the implementation:
#implementation MyModel
+ (MyModel *)sharedModel
{
static MyModel* modelSingleton = nil;
static dispatch_once_t once;
dispatch_once(&once, ^{
modelSingleton = [[MyModel alloc] init];
});
return modelSingleton;
}
#end
And then you just use:
[MyModel sharedModel]
to access it.

What are NSManagedObjectContext best practices?

I'm working with a Navigation Controller based iOS app. There are multiple tableView screens that pull and save data from a Core Data persistent store. Most of the data for the different table views comes from NSFetchedResultsController instances or NSFetchRequests.
The app works as intended but I have been getting a few random crashes and glitches that seem to be related to Core Data. For example sometimes when I save the context the app will crash but not always. Another thing I've been seeing is the very first tableView doesn't always update the reflect the data that was modified in it's detail view.
Currently I'm passing around a single Managed Object Context that was created in the app delegate to each of the different view controllers by setting the context property of the view controller just before I push it onto the navigation stack.
This seems like a clunky, hacky way of getting the job done. Is there a better design pattern to use?
I noticed in one of the WWDC sessions using delegation but I've never used creating my own delegates before and haven't been able to puzzle it out of the WWDC session.
Thanks.
=)
Use singleton NSManagedObjectContext for all Controllers isn't a best practice.
Each Controller should have your own Context to manage specific, sometimes atomic, operations at document store.
Think if you can edit a NSManagedObject attached to Controller that pass the same Context to other Controller that will select another instance to delete or edit.. you can lost the controll about modified states.
When you create a view controller, you pass it a context. You pass an
existing context, or (in a situation where you want the new controller
to manage a discrete set of edits) a new context that you create for
it. It’s typically the responsibility of the application delegate to
create a context to pass to the first view controller that’s
displayed.
http://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/CoreDataSnippets/Articles/stack.html
1)
Use a singleton for your CoreData setup (NSPesistentStoreCoordinator, NSManagedObjectModel & NSManagedObjectContext). You can use this singleton to execute the fetch requests you created in your Models and to add or delete Entities to your Context.
2)
Delegates are not that hard. Following is a sample:
#class SomeClass
#protocol SomeClassDelegate <NSObject> //Implements the NSObject protocol
- (void) someClassInstance:(SomeClass *)obj givesAStringObject:(NSString *)theString;
- (BOOL) someClassInstanceWantsToKnowABooleanValue:(SomeClass *)obj //Call to delegate to get a boolean value
#optional
- (NSString *) thisMethodIsOptional;
#end
#interface SomeClass : NSObject {
id<SomeClassDelegate> delegate;
//Other instance variables omitted.
}
#property (assign) id<SomeClassDelegate> delegate;
#end
#implementation SomeClass
#synthesize delegate;
- (void) someMethodThatShouldNotifyTheDelegate {
NSString *hello = #"Hello";
if (self.delegate != nil && [self.delegate respondsToSelector:#selector(someClassInstance:givesAStringObject:)]) {
[self.delegate someClassInstance:self givesAStringObject:hello];
}
}
#end
Option 1 could be something like this, you will have to setup the variables in the init of the object (and implement the singleton ofcourse):
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#interface CoreDataUtility : NSObject {
#private
NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;
NSPersistentStoreCoordinator *persistentStoreCoordinator;
}
+ (CoreDataUtility *)sharedCoreDataUtility;
- (NSEntityDescription *) entityDesctiptionForName:(NSString *)name;
- (NSMutableArray *) executeRequest:(NSFetchRequest *)request;
- (id) getInsertedObjectForEntity:(NSString *)entity;
- (void) deleteAllObjects:(NSString *) entityName;
- (void) deleteManagedObject:(NSManagedObject *)object;
- (void) saveContext;
#end
Currently I'm passing around a single Managed Object Context that was
created in the app delegate to each of the different view
controllers...This seems like a clunky, hacky way of getting the job
done. Is there a better design pattern to use?
There's nothing particularly special about a managed object context in this respect, it's just another object that your view controller may need to do its job. Whenever you're setting up an object to perform a task, there are at least three strategies that you can use:
Give the object everything it needs to get the job done.
Give the object a helper that it can use to make decisions or get additional information.
Build enough knowledge about other parts of the application into the object that it can go get the information it needs.
What you're doing right now sounds like the first strategy, and I'd argue that it's often the best because it makes your view controllers more flexible, less dependant on other parts of the app. By providing the MOC to your view controllers, you leave open the possibility that you might someday use that same view controller with a different context.
Jayallengator makes the helpful observation that every managed object has a reference to its context, and if you're passing around specific managed objects you don't also need to pass along the context. I'd take that a step further: if you're passing specific managed objects to your view controller, the view controller often won't need to know about the context at all. For example, you might keep Game objects in your data store, but a GameBoardViewController will probably only care about the one Game that's being played, and can use that object's interface to get any related objects (Player, Level, etc.). Perhaps these observations can help you streamline your code.
The second strategy is delegation. You'll usually use a protocol when you use delegation, so that your object knows what messages it can send its helper without knowing anything else about the helper. Delegation is a way to introduce a necessary dependency into your code in a limited, well-defined way. For example, UITableView knows that it can send any of the messages defined in the UITableViewDelegate protocol to its delegate, but it doesn't need to know anything else about the delegate. The delegate could be a view controller, or it could be some other kind of object; the table doesn't care. The table's delegate and data source are often the same object, but they don't have to be; again, the table doesn't care.
The third strategy is to use global variables or shared objects (which is what people usually mean when they talk about singletons). Having a shared object that you can access from anywhere in your code is certainly easy, and you don't have that "klunky" extra line of code that configures your object, but it generally means that you're locking your view controllers in to using that shared object and no other. It's a lot like gluing a hammer to your hand because you know for certain that that hammer is the tool you need. Works great for pounding nails, but it can be painful if you later discover that you'd like to use the same hand for driving screws or eating dinner.
The singleton approach seems to be best-practice, but another trick I found useful was that in cases where you're passing a NSManagedObject from one view controller to the next anyway (usually as an instance variable), you don't need to also pass the NSManagedObjectContext since you can get the context from the object you passed in by invoking [myManagedObject managedObjectContext]. This can be a handy shortcut when there's maybe only one or two methods where you need the context and you don't want the overhead of creating yet another NSManagedObjectContext ivar/property.

access an integer and string globally in iphone?

i want to access a integer and a string from a class to all the other classes?
what is the best way to do it?
i want to increase the values any where in the program and then want to update them in the class declared....
any idea how to achieve this???
Here's a question (and good answers) about singletons.
You could also use the app delegate, as frankodwyer suggested, and access it from anywhere using:
id delegate = [[UIApplication sharedApplication] delegate];
For ease of use and type safety I use a category like this:
// put his in your delegate header file
#interface UIApplication(MyAppAdditions)
+ (MyAppDelegate*)sharedDelegate;
#end
// put his in your delegate implementation file
#implementation UIApplication(MyAppAdditions)
+ (MyAppDelegate*)sharedDelegate {
return (MyAppDelegate*)[[self sharedApplication] delegate];
}
#end
Now you can access your app delegate from everywhere: [UIApplication sharedDelegate]
You could make the integer and string properties of your app delegate and pass references to the delegate around to your views. I do something like this myself, though to be honest it is a pain and also a little error prone to make the app delegate available to all the views.
Or (and this is probably better), you could declare a singleton class (google the singleton pattern) as one of your data classes, and have your integer/string be properties of that. Then you could access the getters/setters of your singleton from anywhere in your program. You will need to take extra care if you have multiple threads however,