How to call an instance method of a different class from AppDelegate? - ios

I have designed a web service application and fetch app's data from my server via some GET requests.. In my login class i enter userdefaults and save them to NSUSerDefaults, then in viewDidLoad of my login class i made a control, if the userdefaults are saved, i assing them to the text property of textfield. What i want is to call that method(login method) of my login class from the applicationDidFinishLaunchingWithOptionsdelegate method. Below is some peoudo code:
//LoginClass.m
#implementation LoginClass
....
//needed things...
-(ibaction)LoginMethod{
//the assingments&data fetchings ect
}
And i want to call this method in my appdelegate class like below
//....Appdelegate class
#import "LoginClass.h"
//.....other things....
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
LoginClass *myObj= [[LoginClass alloc]init];
[myObj LoginMethod];
}
How can i do this? Shortly over all, how can i call a method of other classes from AppDelegate class?
Note: I use NSURLConnections and its delegate methods to fetch data, handle errors ect..
NOTE-2: I tagged with NSUserDefaults too because i use it too(in controlling i control its content)
EDIT After controlling defaults in my loginViewController's viewDidLoad, if there is a value in defaults i want to automatically call my login action, with no need to user's clicks.

Since the AppDelegate is usually the first class created this is where you can create the objects that you want to send messages. If this object creates them, then this objects knows about them and it can send it messages.
A word of caution, though:
Loading everything in your AppDelegate is going to take time. If you take too long then the Springboard will terminate your app.
I also think your design is a bit unsophisticated. If you are going to create everything in the AppDelegate then I suspect the control flow will be bouncing back to the AppDelegate to get references to other objects. Which doesn't make for modular code.

Related

Relation between Singleton class & AppDelegate class in iOS Objective-C

I have a variable declared in AppDelegate class(.h file) whose value gets changed from multiple ViewController classes.Also,single application-wide instance for my AppDelegate class is shared throughout my application as follows :
AppDelegate *AppD = (AppDelegate *)[[UIApplication sharedApplication] delegate];
As I could access this variable declared in AppDelegate from any ViewController class, is AppDelegate class as an example of Singleton class in this scenario?
Can anyone help to site out the usage of singleton class with real-life example ?
AppDelegate is however a singleton class but you show only use it for declaring things that applies globally in your application.For ex: If you want to change the color of navigation bar in your entire application you can use app delegate and set the color of navigation bar. Also app delegate is an object that handles different state transition in your app. So if you want to create a variable that can be changed from multiple View controllers you should create a singleton class and declare that variable in that class.
The app delegate is not supposed to be a repository for all kinds of global variables. The app delegate is supposed to be used for things that affect the whole of the application, like launch / app termination, entering the background and returning from the background, that kind of thing.
If there is state that is shared by multiple view controllers, that should exist only once, but doesn't affect the application as a whole, then you could consider creating a singleton for that state. Then again, global state that is just an artefact of how you write your code should be avoided.
AppDelegate can be used just like singleton, but I don't recommend it. It's like you can put all your classes declarations and definitions in a class.h and a class.m file. Simply import the class.h file can invoke all classes. But it will be very inconvenient to read, understand and manage.
AppDelegate is mainly used for all kinds of app itself event, through UIApplicationDelegate method. Do not recommend deal with too much logic about global data here. Such as classes named XXManager, XXService, PublicData, is proposed to manage all kinds of singleton data.

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;

How to save custom object data in AppDelegate?

I have a custom object called UserSettings. Its a subclass NSObject with a few properties.
It has a method called saveSettings and all it does is save the properties to NSUserDefaults.
Everything works fine when I instantiate it and call the save method in my ViewController class. But I also need to save the settings in AppDelegate when application goes into background or terminates.
What would be the best practice for this typical scenario?
Should I use instantiate the object in AppDelegate and use UIApplication sharedApplication to access it as the TS here? Saving data in custom class via AppDelegate
Or should I create a static object?
Ignore my suggestions if it sounds weird as I'm still trying to get familiar with the design patterns.

Casting of [UIApplication sharedApplication].delegate

I've got a test project to use the private data object on several view controller.
(I've downloaded it from web & git-hub)
- (ExampleAppDataObject*) theAppDataObject;
{
id<AppDelegateProtocol> theDelegate = (id<AppDelegateProtocol>) [UIApplication sharedApplication].delegate;
ExampleAppDataObject* theDataObject;
theDataObject = (ExampleAppDataObject*) theDelegate.theAppDataObject;
return theDataObject;
}
First question is, theDelegate was casted with AppDelegateProtocol, even this applications UIApplication delegate name was ViewControllerDataSharingAppDelegate, and there's no warning. I can't under stand why, maybe it's because that was a id type?
(AppDelegateProtocol is a custom delegate protocol he declared in the AppDelegate.)
Second, it shows this kind of code on every view controller, and it seems like just a single-ton pattern.
I don't think this is not the best way to transfer data between view controller.
Which is the best way to transfer object data type?
Thanks.
Creating a protocol decouples the code somewhat from the specific implementation. You could conceivably have several applications, each of which uses its own custom class as an app delegate, but all implementations conform to the AppDelegateProtocol.
I used to use the app delegate to hold global data and methods a lot when I first started in iOS.
However, that fills your app delegate with app-specific code.
I've shifted away from that approach recently, and use a data container singleton (and perhaps a utility methods singleton as well.) As is typical for a singleton, I define a class method that lets me fetch the singleton. I add properties to my singleton as needed to store data, and then just use the class method to get a pointer to the singleton. I write my class method to lazy load the singleton.
Its also easy to make your data container singleton persistent by making it conform to NSCoding. Then every time you get moved to the background, just save your singleton somewhere. On app launch, read it in.

Can I get the iOS Startup Notification after the application has started?

I'm looking for a way to retrieve the UIApplicationLaunchOptionsLocalNotificationKey on iOS that doesn't involve using the application delegate, i.e. I don't want to have to implement the following:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UILocalNotification *localNotification = [launchOptions objectForKey: UIApplicationLaunchOptionsLocalNotificationKey];
if (localNotification != nil)
{
// Process notification
}
}
I'm trying to create a helper library that needs information about the startup notification. Is there anyway of doing this? Can I retrieve the launch options via another method at a later point in the application process?
You can add yourself as an observer of the UIApplicationDidFinishLaunchingNotification notification which will be posed by the application and contains the information you are looking for.
As #Stavash suggests, there are limitations. For the first launch you won't be able to pick this notification up because the instance of your library won't be created (your class would need to be in the root XIB). But, this notification will also be sent when the app is re-opened for local / remote notifications.
Use a AppDelegate category and inside the +load method of your category add an observer for UIApplicationDidFinishLaunchingNotification. For the observer class you cannot use "self" but you will have to use a singleton object. Here are exact steps to get it done.
Add a category for your AppDelegate. Eg : #interface AppDelegate
(notification).
Implement the +load method in your category. When
the app is launched, it will start calling +load method of all the
classes that get loaded. This includes your categories also.
Create
a Singleton class with a method that will receive the
NSNotification. So implement a signature like this -
(void)appDidLaunch:(NSNotification *)notification; in your singleton
class.
Inside the +load method, add an observer for the notification
"UIApplicationDidFinishLaunchingNotification".
Make the singleton
object as your observer for this notification.
Add your breakpoints
in your +load and appDidLaunch methods to see the sequence of
methods being called. You will get the launchOptions also in your
observer callback method.
The other way to do it would be to Swizzle the AppDelegate's init method with a swizzle_init method. That way you can avoid the Singleton object and define your "appDidLaunch" observer method inside your AppDelegate's category. In that case you can set 'self' as your notification's observer.

Resources