How to save custom object data in AppDelegate? - ios

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.

Related

(UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext

I read that this line of code gets the managed object context from AppDelegate.
let managedObjectContext = (UIApplication.sharedApplication().delegate as AppDelegate).managedObjectContext
I read the Apple documentation of each word to try to reconstruct the right overall output sense mentioned above.
Who can explain in a clear and detailed way the meaning of this line syntax ?
First you access the UIApplication class.
This is a singleton. There is only one instance of it which is created upon application start by the cocoa touch framework.
Then you access its one and only instance by calling the class method sharedApplication. "shared(classname)" is a common name for the method reurning the instance of a singleton. Another common name is "sharedInstance".
Then you access its delegate. That follows the usual delegation pattern that you see quite often in iOS app development using cocoa touch. But this is a very special delegate which you own. It is the AppDelegate class.
When you let Xcode create a new app project using core data, then it creates some standard methods into your AppDelegate class for your convenience.
One of these is a (computed) getter for managedObjectContext.
However, UIApplication knows its delegate only as any object that implements the UIApplicationDelegate protocol. The additional methods for core data are not known to UIApplication.
That is why you have to cast the output of .sharedApplication() to your implementaion named AppDelegate. as is the cast operator in Swift.
After it was casted you can actually access the getter managedObjectContext.
That's it.

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.

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.

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

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.

How to control data flow between ViewControllers

I'll start by saying I'm new to Objective-C and iPhone but I have history in C++, Java, AS3, ...
I'm trying to build some sort of RSS Reader, and I have an array for all my feeds. How is the best approach to save new feeds to this array? I have a navigation based project, and I have an add button which pushes a viewController on top to enter new feed URL.
But how do I save this back to the array in my other ViewController? Do I need to research more into SQLLite? Or set some delegates? Or Core Data?
I prefer the singleton method myself but Apple recommends dependency injection i.e. passing a data model object from view controller to view controller as needed.
If you look at a Core Data utilizing template navigation project in Xcode, you can see how this works. The managedObject context is the data model and it is initialized and held by the app delegate. You can then access it two ways:
(1) Since the Application instances itself is a singleton, you can ask it for its delegate and then ask the delegate for its managedObjectContest property. So, in a view controller you would have a property managedObjectContext with a custom getter defined like:
(NSManagedObjectContext *) managedObjectContext{
if (managedObjectContext !=nil){
return managedObjectContext;
}
// this is basically applicationObject.delegate.managedObjectContext
self.managedObjectContext=[[[NSApplication sharedApplication] delegate] managedObjectContext];
return managedObjectContext
}
(2) Alternatively, whenever a view opens another view, it just sets the next view's managedObjectContext property to it's own. So that every view opens with a context. This is useful if you actually have multiple data objects for some reason.
If your just using an array or a custom data model class just substitute its name for the managedObjectContext in the code above.
Check out this question. I recommend using a singleton class and creating some listener pattern to signal when the data has changed (or just reload, always, before your view becomes visible).
You might want to store your feed items in memory by using the a singleton
Something similar to what is being used: Singleton shared data source in Objective-C

Resources