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

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.

Related

Best way to avoid singleton

For our iOS programming class we must make a framework for Swift iOS. We had the idea of a framework simplifying CoreData manipulation. I began by creating a class where you put the NSManagedObjectContext created in AppDelegate at the beginning, so you don't have to write this long (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext anymore.
open class SimpleCoreData {
var context: NSManagedObjectContext
init(context: NSManagedObjectContext) {
self.context = context
}
func delete(entity: NSManagedObject) /*-> Bool*/ {
// some code
}
func getAll(entityClass: NSManagedObject.Type) throws -> [NSManagedObject]? {
// some code
}
func create(entityDescr: NSManagedObject.Type) -> NSManagedObject? {
// some code
}
But I would like it to be accessible from everywhere in the application, and this simplification would be useless if you have to instantiate this each time.
I was first thinking about a singleton, but I recently learned it wasn't a good practice.
So do you know any solution to make this accessible from everywhere in the client app? Or maybe singleton is okay in this case?
Keeping Rob Napier's excellent comments in mind, if you decide to avoid a singleton in this case, a common approach would be
Create an instance of your SimpleCoreData class in the app delegate when the app launches.
Have the app delegate pass this to your initial view controller. That view controller would have a SimpleCoreData property but would not create the instance-- it would expect one to be assigned by whichever code creates it, which here is the app delegate.
Repeat this pattern everywhere you need a SimpleCoreData. That is, when you create an object that needs a SimpleCoreData, make sure it has a property with that type, and assign a value when you create it. For view controllers, a good place to do this is in prepare(for:sender:), if you're using segues.
It's not necessary to create the SimpleCoreData in the app delegate, though. You could create it at the first point in the app hierarchy where it's needed, and pass it along from there. So if it's only needed in the second view controller in the hierarchy and in other objects loaded from there, create it in that view controller.
This doesn't make your SimpleCoreData instance available everywhere automatically, it means that you're creating one and then passing it around. Often that works fine, but as Rob notes it's not always the best approach. It can lead to passing an object along to an object that doesn't need it, because some other object that gets created later on does. For example if you need SimpleCoreData in your initial view controller but then not again until five levels down the hierarchy, you still need to pass it along every step of the way. That's an example of when a shared instance can be useful. It's not a singleton since other instances are allowed, but it's a default instance that can be used as needed.
I finally learned thanks to you that singletons aren't so evil, they can be used in some case, including this one, and it seemed in my case that it was a good choice. Maybe I will change it for a shared instance pattern.
So the singleton works well. Thank you everybody for your advices, I learned a lot in design patterns.

how are protocol methods in iOS automatically invoked?

Im trying to understand the high level implementation of protocols without delegates in Apple frameworks. When a subClass conforms to and implements a protocol method, how is that method called? Lets consider the NSCoder protocol methods (encodeWithCoder: and initWithCoder:) for instance.
Without delegates, could you provide any uses cases for protocols (other than achieving polymorphism? I see that some methods could be abstracted away from base classes and grouped into an interfaces but without any implementation (as mixins for instance), what is the significant use?
First, protocol methods are not special in any way. They, like every other Objective-C method, gets called by a message sent to an object. There's nothing special about that part of things. Protocols are basically just a hint to the compiler, though you can query whether an object conforms to one at runtime and make decisions based on that.
You can verify this by implementing a protocol method (or the entire protocol) without declaring that fact in a classes' interface, and call the function on an instance of that object after casting it to be id<YourProtocol>, and it will work.
You can (and sometimes should) call NSCoding methods yourself -- you may decide that you want to persist objects to the disk, and that this is the best way to do it.
NSCoding is actually a great example of why protocols are still useful even though they do not provide any implementation -- the implementation of initWithCoder: and encodeWithCoder: will be different for every class that implements them -- there is no sense in providing an implementation.
Building on that, consider the datasource property of a UICollectionView; as there is no multiple inheritance in Objective-C, it would be undesirable for the datasource to be a class itself, as that would prevent you from using a UIViewController as the data source, and force you to make a whole new class for that express purpose.
Protocols can also be used to implement multiple inheritance in a type safe way without redeclaring the interface of the giver in the inheritor. If the entire interface of the class being inherited from is a protocol, then the inheritor can simply conform to that protocol as well.
Objective-C does provide mixins in the form of Categories, which can implement protocols on existing classes.
For a full throated defense of protocols (in Swift), see the Protocol-Oriented Programming WWWDC 2015 talk.
Taking the example of the NSCoding Protocol, the two required methods in the protocol, basically implement the steps an object should perform to encode itself to be archived. It also implements the initWithCoder to recreate the object from the archive.
Lets say you create a custom object, only your object knows which properties it needs to archive.
When you call a method to archive your custom object, the method call ultimately flow to your encodeWithCoder or initWithCoder to take action specific to your class.
***** Updated ****
Looking at this with an example :
Lets say our data structure looks like this
someArray = [String,CustomObject,aDictionary]
When we want to archive someArray, we call the archiveRootObject method on it. Now inorder for someArray to archive itself, it needs all its contained items to inturn archive themselves. The Array simply instructs the sub items to archiver themselves calling the encodeWithCoder method on them.
By adopting and conforming to the NSCoding protocol, you are just confirming to the root array that Yes, I know how to archive and unarchive myself.
Hope this helps.

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.

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.

Resources