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,
Related
Ive been having problems with reloadData on a TableView. I've finally been able to establish that the variable I use to tell reloadData what to reload is resetting to NULL.
I've added the variable in ClassAppDelegate.h as follows:
#property (nonatomic, retain) id globalid;
and then synthesized in ClassAppDelegate.m as follows:
#synthesize globalid;
I then acces the variable in which ever class and method i need to use it with (in the method):
NDSClassAppDelegate *detailControllerAD = [[NDSClassAppDelegate alloc] init];
And then use it in this way to obtain the variable in that method:
NSLog(#"GlobalID at FetchTweets %#", detailControllerAD.globalid);
Why would my variable be resetting on reloadData?
You shouldn't be instantiating an app delegate object - your application is given one at launch as part of the UIApplicationMain() function, and it should live the lifetime of your application. Use [[UIApplication sharedApplication] delegate] to get the delegate, i.e. NDSClassAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]. Then, anywhere you need to set or read the globalid property, set it on this instance of the application delegate.
Instance variables (which properties are usually backed by) vary independently between instances of objects so you can't store a value in one object and then have the same value appear in another.
When you use this
NDSClassAppDelegate *detailControllerAD = [[NDSClassAppDelegate alloc] init];
new instance created of app delegate.
use this
[[UIApplication sharedApplication] delegate]
to get existing instance of app delegate.
You can use above way to share the data throughout the application . I was also have same requirement in one of my previous application . At two three forum i have read about the sharing the data though out the application . But according to them this is not a good practice to store the data at application level because using app delegate as a model object is non delegate related stuff. So the cleaner approach is to use the singleton class . Create one singleton class to preserve all the variables state. That will be the cleaner approach .
I read a post to use macro to reference AppDelegate. I wonder what I should use to replace (MyOwnAppDelegate*)
#define AppDelegate ((MyOwnAppDelegate*)[[UIApplication sharedApplication] delegate])
If you're referencing the UIApplicationDelegate so often that you need a special macro for it, then you're referencing it too often. The application delegate is the delegate of the main UIApplication object. It is not a general place to store "stuff." See the following discussions:
What describes the Application Delegate best? How does it fit into the whole concept?
Is it ok to place most logic and models in the appDelegate?
If it's a more recently started project, your delegate is probably called AppDelegate. To find out, you have to find the class in your project that implements NSApplicationDelegate or UIApplicationDelegate (depending on your target platform).
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.
I have a two different ways of representing data in my app: via UITableView or UIScrollView.
So I have 2 main classes: AppTableView: UITableView and AppScrollView: UIScrollView.
And I want to implement the same additions to both views. So I wrote two classes: SomeAdditionsTableView: UITableView and SomeAdditionsScrollView: UIScrollView. The code of this classes is the same.
Main classes now looks like
AppTableView: SomeAdditionsTableView and AppScrollView: SomeAdditionsScrollView.
How to avoid this code duplicate? Thanks in advance.
Yeah this is a problem with the lack of multiple inheritance in Objective-c. I had the same problem when needing certain methods on a subclass of UIView and UIScrollView separately here: Subclassing UIView vs UIScrollView. There are 3 possible solutions I know of:
If you don't need to store any kind of instance variable, simply declare a category on UIScrollView and make sure to import that category into the two subclasses. This is the easiest solution, but least likely to work since you probably need to store state information if you're subclassing anyway.
Only create a subclass of UITableView and simply don't use it as a UITableView when you don't want a UITableView. You can technically just use a UITableView as a UIScrollView without invoking any of the tableView's methods. Of course, you're going to end up carrying around the 'weight' of a tableView (all of it's instance variables) but there no reason you have to use a UITableView as a UITableView and not just a UIScrollView.
Delegate as much of your code to a separate object to minimize code duplication. In each separate subclass carry an instance variable that is the method delegate and forward method calls to that delegate. Now here's where it gets fun. You can use protocols to declare the delegate methods in your subclass and override a special NSObject method: - (id) forwardingTargetForSelector:(SEL)aSelector to make sure those method calls get sent to the delegate. You use a category on the subclass that conforms to the protocol declared in the delegate class. This will expose all the methods of the delegate class in the subclass without requiring you to actually implement those methods in the subclass. When the runtime can't find the declared method in the subclass, it will call - (id) forwardingTargetForSelector:(SEL)aSelector, which you can use to return your delegate/forwarded class. This will prevent you from needing forward each individual method. Depending on what those method calls do, this may take a little more 'wiring', but it'll save you a lot of code writing in the end. It essentially 'mimics' multiple inheritance in objective-c using protocols. See my question/answer here for more details: https://stackoverflow.com/a/9419587/1147934.
Of the three, the last option tends to work the best for me. It takes a little work to get your head around but will significantly reduce code duplication. I also use it when I want to subclass without subclassing. The biggest requirement, though, is any class that you want to do this with will have to move it's method declarations out of it's interface into a separate protocol. But it's really not a big deal and the benefits of getting 'multiple inheritance like behavior' is great.
Also, there are times you may need the forwarded class to access instance variables in the forwarding class (the subclass). You can achieve this by using a delegate pattern whereby the forwarded class maintains a weak reference to the forwarding class in order to access those instance variables. For example, in your case, if you're trying to delegate methods that operate on a UIScrollView, those methods may need to be able to access that view. If those methods are stuck in a delegate class, they won't have direct access to the view's variables unless you give it to them. As usual with any delegate pattern, be very careful you don't create a retain cycle.
If your additions don't need any state of their own, you can make them a category on UIScrollView. Then, since a UITableView is a type of UIScrollView, you can use the category methods on one of those too.
If they do need to define new variables, then I would make it an independent class and have a MyTableView : UITableView subclass with a SomeAdditions property and, similarly, MyScrollView : UIScrollView.
You can achieve a lot by using protocols and "has_a"-relationships, instead of inheritance's "is_a"-relationships.
One very common pattern is delegate, but protocols are also useful for forwarding methods calls to encapsulated or wrapped objects.
in the following example to classes, that are not related to each other, share a common object, but it is also possible, that objects of the same kind use objects of different classes, that all implement a common protocol, so equal objects could do very different stuff.
#interface ClassA : NSObject
#property (strong) id<BrainProtocol> *brain
#end
##implementation ClassA
#synthezise brain;
-(void)theMethod
{
[brain theMethod];
}
#end
#interface ClassB : NSObject
#property (strong) id<BrainProtocol> *brain
#end
##implementation ClassB
#synthezise brain;
-(void)theMethod
{
[brain theMethod];
}
#end
ClassA *a = [[ClassA alloc] init];
ClassB *b = [[ClassB alloc] init];
//A object, that implements the BrainProtocol
Brain *brain = [[brain alloc] init];
[a setBrain:brain];
[b setBrain:brain];
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.