importing AppDelegate - ios

Often times I initialize my model class variables in my AppDelegate so they can be used by different ViewControllers without passing their instance across class files. However, every time I import AppDelegate into a .m file to access these variable's data I feel like I'm doing some wrong.
Is this the the correct way for accessing these variables or should I be doing something differently?
EDIT:
My problem isn't how to access the variables. I currently use this line of code to get my appDelegate instance:
id appDelegate = [[UIApplication sharedApplication] delegate];
Conceptually, I want to know if this is the accepted way to interact with an application's model classes. It seems, to me, that an application's AppDelegate manages the application overall. So it seems counterintuitive to import this class into other classes further down an application's class chain.

Is this the the correct way for accessing these variables or should I
be doing something differently?
You'll find that different people have different opinions about this. The style that I prefer is to have the app delegate pass the necessary information to the first view controller, and have that view controller pass it on to whatever view controllers it creates, and so on. The main reason for this is that it prevents child view controllers from depending on things that they have no business knowing about.
If you have some detail editor, for example, you want to be able to pass that editor exactly what it needs to do its work. If you give it that information, the editor is completely flexible -- it'll edit any information that you give it. If the editor knows that it should get its data from some external object, like the app delegate, then it loses some degree of flexibility -- it can only get data from the thing that it knows about.
So, it's fine to set up your data model in the app delegate. But when it comes to providing access to the model, think: tell, don't ask. That is, have the app delegate tell the first view controller what model object to use, and have that controller tell the next one, and so on. If you have to ask, you have to know who to ask, and that's where the dependencies start heading in the wrong direction.
every time I import AppDelegate into a .m file to access these
variable's data I feel like I'm doing some wrong.
Trust that instinct. Think about why it feels wrong.

I agree that sometimes it seems like the AppDelegate is the logical place to put things that you only want implemented once but may need from several places. Creating a singleton for each one is fine, if those things are complicated, but it does create a lot of additional files and confusion to the project. I also agree with the majority of answers here, that building dependencies on the AppDelegate is a really poor design.
I think the best solution is to create a Protocol! Then put an IBOutlet to a property to do what you need to have done in each of the controllers that need the function. Protocols are the standard objective-C way to uncouple classes.
So, as an example, maybe I have a database URL that I may need from a bunch of places. Probably the best way would be to set a property with it each step along the way. But in some situations that may be cumbersome because of using a stock controller and not wanting to subclass it. Here is my solution:
Create file: MainDatabasePovider.h
#import <Foundation/Foundation.h>
#protocol MainDatabaseProvider <NSObject>
#required
#property (nonatomic, readonly) NSURL *applicationDocumentsDirectory;
#property (nonatomic, weak) NSURL *mainDatabase;
#end
Now "anyone" (i.e., any class) that says it implements the MainDatabaseProvder protocol is guaranteed to provide the two methods above. This could be the AppDelegate or ANY object.
Now if I want my AppDelegate to provide the information I change the AppDelegate.h file to have:
#import "MainDatabaseProvider.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate, MainDatabaseProvider>
#property (strong, nonatomic) UIWindow *window;
#end
(The only change is to add the MainDatabaseProvider protocol to the #inteface line, again this could be done to ANY class that you want to provide the function).
In my AppDelegate.m file I have to write the two methods...
#implementation AppDelegate
...
#synthesize mainDatabase = _mainDatabase;
...
- (NSURL *) applicationDocumentsDirectory {
return [[[NSFileManager defaultManager] URLsForDirectory: NSDocumentDirectory inDomains: NSUserDomainMask] lastObject];
}
- (void) setMainDatabase: (NSURL *) mainDatabase {
if( _mainDatabase != mainDatabase ) {
_mainDatabase = mainDatabase;
}
}
- (NSURL *) mainDatabase {
if( !_mainDatabase ) {
NSURL *docURL = self.applicationDocumentsDirectory;
self.mainDatabase = [docURL URLByAppendingPathComponent: #"My Great Database"];
}
return _mainDatabase;
}
...
#end
Now in my controllers or other classes that have need of getting the MainDatabase I add the following:
In their .h files:
#import "MainDatabaseProvider.h"
...
#interface myGreatViewController: UIViewController
#property (nonatomic, weak) IBOutlet id <MainDatabaseProvider> mainDatabaseProvider;
...
#end
This property can be set in what was formerly known as InterfaceBuilder by control-dragging or can be set in code in prepareForSegue or I like to provide a custom getter that default it to the AppDelegate in case I am lazy or forgetful and don't do either of the above. In their .m file is would look like:
#implementation myGreatViewController
#synthesize mainDatabaseProvider = _mainDatabaseProvider;
...
- (id <MainDatabaseProvider>) mainDatabaseProvider {
id appDelegate = [[UIApplication sharedApplication] delegate];
if( !_mainDatabaseProvider && [appDelegate conformsToProtocol: #protocol(MainDatabaseProvider)] )
return appDelegate;
return _mainDatabaseProvider;
}
// To get the database URL you would just do something like...
- (void) viewWillAppear: (BOOL) animated {
NSLog( #"In %s the mainDatabaseProvider says the main database is \"%#\"", __func__, self.mainDatabaseProvider.mainDatabase.path );
}
Now the mainDatabaseProvider can be ANY object. I have the ability to set it in InterfaceBuilder or my StoryBoard (although I don't really think of this is a user-interface item so I typically wouldn't but it is pretty typical to do it that way), I can set it in code outside my controller before it gets loaded in prepareForSegue:sender: or tableView:didSelectRowAtIndexPath:. And if I don't set it at all it will default to the AppDelegate if I have configured it properly.
I can even put some safe guards in for when I forget to do things in my old age by changing the getter listed above to help me out with something like:
- (id <MainDatabaseProvider>) mainDatabaseProvider {
if( !_mainDatabaseProvider ) {
id appDelegate = [[UIApplication sharedApplication] delegate];
if( ![appDelegate conformsToProtocol: #protocol(MainDatabaseProvider)] ) {
NSLog( #"Hey!! The mainDatabaseProvider is not set and the AppDelegate does not conform to the MainDatabaseProvider protocol. How do you expect me to figure out where the database is!" );
} else {
return appDelegate;
}
return _mainDatabaseProvider;
}

You should seriously avoid importing the AppDelegate everywhere and you should feel like you are doing something wrong each time you do it (+1 for that). You are essentially creating a Big Ball of Mud and should reconsider your design. If for example you are using CoreData for your models consider a framework such as Magical Panda Active Record to retrieve data. I work on an enterprise application and the AppDelegate.h is only include in AppDelegate.m.

I'm importing them too and use it like this:
AppDelegate *delegate = (AppDelegate*)[[UIApplication sharedApplication] delegate];
[delegate variable];
Another way can be to use a Singleton.

Put this method in your AppDelegate class
+ (AppDelegate *)get {
return (AppDelegate *) [[UIApplication sharedApplication] delegate];
}
And when you need to call your AppDelegate use:
[AppDelegate get];

That is one way of doing it, yes, however it is not very elegant. Singletons are a way too, yes, however not very elegant :) - and reeealy NOT easy to test your code, if you have to mock out all your singletons.
Instead what I probably would do is to have one singleton for a service provider, and ask this service provider for an instance your model provider.
Say, your service provider class is a singleton and you need to access the model for the view user details. I would do it in the following manner:
JMUserDetailModel *myModel = [[[JMServiceProvider sharedInstance] modelProvider] userDetailModel];
This means that you would create a JMServiceProvider class for registering services, and being able to retreive these services. These services act a bit like a singleton, however if you need to unit test your code, then registering a different service that acts in the same way as the original is just a piece of cake.
Hope this answers your question.
EDIT: And read this article: http://martinfowler.com/articles/injection.html - a very good one explaining service oriented architectures as well ...

Look in to singletons. They can be a more elegant way to manage global data.

Related

Reference variables stated in other classes

It's a very basic question.
In AppDelegate.m,
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.stationInfos = [StationDB database].stationInfos;
}
return YES;
}
and I want to be able to use stationInfos from inside my ViewController.m. What is the most conventional way to do it?
I would state that it is generally frowned upon to store such data in the AppDelegate (either the .m or .h file).
If you need to access the data from multiple places, then a Singleton object is generally the recommended approach. A singleton is an object-oriented concept where only a single instance of an object is maintained in order to allow access from multiple locations to the same data source.
Or, if [StationDB database].stationInfos is already a singleton (I'm not familiar with the object), then it's possible you might be able to just access it anywhere you need it. There's nothing that says you need to define it in the .h or the .m file - you can define it just in the method where it is needed as well.
General guidelines might be:
Define in .h >> If a limited # of other objects may need to access it.
Define in .m >> If only that class needs to access it.
Define in a specific method >> If only that method needs to access it.
Define as a Singleton >> If many objects need to access it.
Don't >> Define it in the AppDelegate. It's best to place your logic in your appropriate model, view, or controller class files.
You would set variable up in the .h instead of the .m. From there, inside your ViewController.m you should import the AppDelegate.h.
Then, when you want the variable do:
AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
variableType *stationInfos = appDelegate.stationInfos;

Pass data from UIViewController to AppDelegate

I need to pass the data from the UIViewController to AppDelegate. But should not with NSUserDefaults. I could not find an alternative for it even i don't want it.
if you need access to your delegate, I always create my singleton access in the next way :
// your imports...
#define appDelegate ((YourAppDelegate*)[UIApplication sharedApplication].delegate)
#class YourAppDelegate
//...
in the .h file of YourAppDelegate.
It´s helpful and useful, but do not abuse of the delegate to access to particular things, try to use a different way. Anyway, you can access in that way.

NSObject's category is available for every NSObject subclass even without any import of this category's .h file anywhere

Background.
Please consider the following steps:
1) In Xcode create a new "Single View Application".
2) Create a category NSObject+Extension.h and .m files:
// .h
#interface NSObject (Extension)
- (void)someMethod;
#end
// .m
#implementation NSObject (Extension)
- (void)someMethod {
NSLog(#"someMethod was called");
}
#end
3) Ensure that NSObject+Extension.m file is included into a main target.
4) Add the following line to AppDelegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[[NSString new] performSelector:#selector(someMethod)];
return YES;
}
5) Ensure that #import "NSObject+Extension.h line does not exists anywhere in the app!
6) Run Application.
The output is
2013-08-27 04:12:53.642 Experimental[32263:c07] someMethod was called
Questions
I wonder if there is no any #import of this category anywhere in the app, how is it even possible that NSString does still have NSObject+Extension available? This behavior makes me feeling very bad about every Objective-C category I declare because I want the categories I declare to be available only in the scopes they are declared within. For example, I want NSObject to be extended by Extension only in some class but not in the whole app because its globalspace becomes "polluted" otherwise.
Is there a way to avoid this behavior? I do want my categories to work only when I explicitly import them, not when I just have them linked to a target I use to run.
I wonder if there is no any #import of this category anywhere in the app, how is it even possible that NSString does still have NSObject+Extension available? This behavior makes me feeling very bad about every Objective-C category I declare because I want the categories I declare to be available only in the scopes they are declared within. For example, I want NSObject to be extended by Extension only in some class but not in the whole app because its globalspace becomes "polluted" otherwise.
There are no namespaces on Objective-C objects. If you declare that a class has a method (whether via a category or on the primary #interface) then every instance of that class will have that method.
The way that Objective-C deals with "private" methods is by choosing not to tell other people about the methods in question (which is accomplished by not #import-ing the file that declares those methods). This, coupled with -Wundeclared-selector (warn if you use a selector that the compiler doesn't know about) is about as good of a guard as you're going to get.
But regardless, if you compile the .m file into your final binary, the method will exist, even if no one else "knows" about it.
Are there way to avoid this behavior? I do want my categories to work only when I explicitly import them, not just when I have them linked to a target I use to run.
Yeah, use -Wundeclared-selector, and Xcode will warn you.
Including the header just makes it so the compiler knows about it. It compiles it regardless because xCode compiles every file included in a target. At runtime, the method will be there, so even if you didn't include it for compile time checking, the object will still respond to that category method.

Should I be storing a singleton as an ivar?

I'm creating a wrapper class for an existing singleton class. Since I'll be accessing the singleton several times, I'd like to store it as an ivar in my wrapper class...
#interface WrapperClass ()
#property (nonatomic, strong) SingletonClass singletonObj;
#end
...so that I don't have to constantly write [[SingletonClass sharedInstance] methodName]. Instead I can write [singletonObj methodName]. It just feels cleaner to me.
I'm new to iOS development, so I'm wondering if there's anything fundamentally wrong with this approach.
Also, with ARC, should I be storing the singleton with a strong reference?
Unless your doing something crazy the likelihood is the extra retain/release should cause no issue.
Therefore there is no real issue with storing it in an ivar...
A better reason for doing this would not be to save your typing but to improve the testability /reusability of the class. By making it an ivar it allows you to inject a different class in to change the behaviour.
I would consider making an accessor that will by default give me the singleton but still allow me to inject a different class if I choose like this
- (SingletonClass *)singletonObj;
{
return _singletonObj = _singletonObj ?: [SingletonClass sharedInstance];
}
Update:
It's also worth thinking about "why would you make using this singleton different from using an ivar?". If you use it throughout your class like it was an ivar then why do you access it in a completely different way?
For example often when I use a managedObjectContext there is only one in my whole app. A lot of people use the app delegate as a singleton and access it that way but I prefer to pass it along as an ivar. Conceptually the managedObjectContext is just another object that I am using like any other ivar so why should I have to mentally switch how I access it?
This is bad
[(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
Good
self.managedObjectContext;
This now gives me two advantages.
If my class is littered with calls to [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; then it is hard to rip it out of this project and place it in another without a risky search and replace. If I access the singleton in one place the "accessor" then I only have one place to change the code.
In my production app I probably want my data to be persistant so I would give the object access to a managedObjectContext with a persistant store, whereas in my tests I don't want state to be persisted between tests so I would give the object a non persistant store instead.
It makes sense.
Just initialize your singleton and store it in the ivar.
That said, your code is actually defining a property, which is not the same thing of an ivar.
For instance you could define your singleton i var like follows
#implementation WrapperClass {
SingletonClass * _singleton;
}
and then initialize the singleton in the default constructor
- (id)init {
self = [super init];
if (self) {
//...
_singleton = [SingletonClass sharedInstance];
//...
}
return self;
}
You can just define a macros, like this:
#define _SINGLETON(method) { [[SingletonClass sharedManager] method]; }
Then you can use it in your code like this:
_SINGLETON(methodName);
You can define this macros in the SingletonClass.h, and then you will have possibility to use it anywhere, there your header is imported.
This way you don't need to think about iVars.

Delegates in IOS - Some clarification required

I'm only really beginning IOS development but have a few years dev of ASP.net through C#. To be honest I've never had a real need to understand delegates / events etc. before, I know that I'm using them when programming web.forms but a lot of the functionality is taken care of by the framework, behind the scenes.
So now that I'm developing in IOS I'm forced to try to understand how they function (I'm presuming here that the theory of delegates / events is the same across languages, maybe I'm wrong). Anyway, the following line of code in IOS:
if ([self.delegate respondsToSelector:#selector(startImporting:)])
{
[self.delegate startImporting:self];
}
Am I right in thinking that, in pseudo code, it means something along the lines of:
If the method/class calling this method has a method in it called 'startImporting' then call the method 'startImporting' within the calling class.
Hope that's clear. If that's the case then would it essentially be the same as having a static method in C# that you could call with something like:
myImportClass.startImporting();
Presumably not, or that's how it would be done. So, am I missing the whole point of delegates, their benefits etc? I've read what they are over and over and while it makes sense, it never clicks, I never (in web forms anyway) have really seen the benefit of using them.
This becomes increasingly important as I'm moving to using lambda expressions in .net and they're closely linked to delegates in C# so while I can just start using them, I'd prefer to know why and what benefit delegates actually are.
The delegation pattern in Cocoa is used to inform (report progress, etc.) or query (ask for credentials, etc.) another object without knowing much about it.
Typically, you use a protocol to define what methods you will call on the delegate and the delegate then needs to conform to that protocol. You can also add methods that the delegate doesn't need to implement (optional). When you do so, you'll have to call -respondsToSelector:, because you don't know whether the delegate wants the particular method to be called or not.
An example:
You have a class that produces something, let's call it Machine and a worker of the class Worker. The machine needs to be adjusted for the task:
Machine *machine = [[Machine alloc] init];
[machine prepareWithParameters:myParameters];
Now that we have the machine we want to produce a massive amount of Stuff:
[machine produceStuff];
Okay, we're done. But how do we know when an unit of Stuff has been produced? We could have our worker constantly standing beside our machine and wait:
while (![machine isFinished]) {
if ([machine didProduceStuff]) {
Stuff *stuff = [machine producedStuff];
[self doSomethingWithStuff:stuff];
}
else {
// Get a very large coffee...
}
}
Wouldn't it be great if the machine did inform us automatically, when it's done with producing an unit of Stuff?
#protocol MachineDelegate <NSObject>
#optional
- (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff;
#end
Let's add the worker as a delegate of machine:
Worker *worker;
Machine *machine = [[Machine alloc] init];
[machine prepareWithParameters:myParameters];
[machine setDelegate:worker]; // worker does conform to <MachineDelegate>
[machine produceStuff];
When Machine is done producing something, it will then call:
if ([[self delegate] respondsToSelector:#selector(machine:didProduceStuff:)])
[[self delegate] machine:self didProduceStuff:stuff];
The worker will then receive this method and can do something:
- (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff {
[self doSomethingWithStuff:stuff];
if ([machine isFinished])
[self shutDownMachine:machine];
}
Isn't that much more efficient and easier for the worker? Now he can do something more productive than standing besides the machine while the machine is still producing. You could now add even more methods to MachineDelegate:
#protocol MachineDelegate <NSObject>
#required
- (void) machineNeedsMaintenance:(Machine *)machine;
- (void) machine:(Machine *)machine fatalErrorOccured:(Error *)error;
- (BOOL) machine:(Machine *)machine shouldContinueAfterProductionError:(Error *)error;
#optional
- (void) machineDidEnterEcoMode:(Machine *)machine;
- (void) machine:(Machine *)machine didProduceStuff:(Stuff *)stuff;
#end
Delegates can also be used to change the behavior of an object without subclassing it:
#protocol MachineDelegate <NSObject>
#required
- (Color *) colorForStuffBeingProducedInMachine:(Machine *)machine;
- (BOOL) machineShouldGiftWrapStuffWhenDone:(Machine *)machine;
#end
I hope I could help you understand the benefit of abstracting your code using delegates a little bit.
Understanding the MVC model and the use of Protocols and notifications is critical to grasping the use and purpose of delegates. Think of them as types of responders for different events related to a specific action.
Hera are some useful links in stackOverflow:
Delegate and notifications
Protocols and delegates
Hope it helps
delegates are useful in getting callbacks from other class
so why to use delegate:
that is we call a method on a class... that's normal... if we want the instantiated class to let us call back... that's where delegates comes in handy...
simple example:
You download songs from a site using a method on one class
once the class completes downloading you want the class to let you know.
//protocol declaration
#protocol DownloadProtocol <NSObject>
-(void)OnFinish;
#end
//SOng download class
#interface songs
#property(Strong,nonatomic) id<DownloadProtcol> delegate;
-(void)Download;
#end
#implementation songs
-(void)Download
{
///the code to download goes here
[self callTheCallingClass];
}
-(void)CallTheCallingClass
{
[self.delegate OnFinish];
}
#end
//
#interface mainclass<DownloadProtocol>
#end
#implementation mainclass
-(void)viewDidload
{
Songs *s=[[SOngs alloc]init];
s.delegate=self;
[s download];
}
-(void)OnFinish
{
NSlog(#"Called");
}
#end
see the delegation is achieved through protocol in objective c. I think you can understand the syntax of it.
In the songs class we create a property for that protocol. we keep it the type as ID... because the type is not known at compile time.
in the songs class once we complete the download we call the protocol method...
In the main class first we adopt the protocol syntax
class
the above is syntax of that
the we instantiate the songs class
then assign the main class object(self) to delegate of songs class
then we have to apply the protocol class in .m by adding method name from protocol
so from now on whenever songs class call the protocol method through delegate instance variable....out protocol method adoption on main class gets run
try this code hope it helps...
if you want more info on this topic google it as delegate design pattern
the main benefit is
it promotes loosely coupled programming...

Resources