Class Accessibility Throughout Project - ios

When I first began working on a long iOS project, my first, I had need for a small class that was readily accessible throughout the project. At first I passed it around as a property and it became way too much of a headache.
So, even though I've seen posts here advising against it, I created that class in the AppDelegate and access it as needed through a pointer to the AppDelegate. Then, I would revisit it later.
So, it is now later, I'm approaching release of the project, and I want to deal with this issue. It works just fine as it is but if it is lousy practice I want to fix it before release.
I don't understand why it is lousy practice. Sometimes you just need a class that is readily available and these seems like as good a way as any to get it. But there could be some downside I'm not understanding.
Assuming I need this class instance (it is very lightweight but heavily used) to be accessible throughout the project (probably about 50 VCs, total), what would be a good alternative to just referencing it via the App Delegate?
TIA for comments. I hope it doesn't start a war.

There's no hard-fast rule for for this and hundreds of opinions to be had. Here's my take on it.
I don't understand why it is lousy practice. Sometimes you just need a class that is readily available and these seems like as good a way as any to get it. But there could be some downside I'm not understanding.
You're right to feel this way and yes sometimes you need a class readily available with your data. It's lousy because it is not how AppDelegate should be used. In an ideal world it shouldn't contain lots of unrelated state-data and should serve a singular purpose: delegating system calls to your app. The trick is where do you put your model so that everyone can have access to it?
Assuming I need this class instance (it is very lightweight but heavily used) to be accessible throughout the project (probably about 50 VCs, total), what would be a good alternative to just referencing it via the App Delegate?
Put your state in a class using the singleton pattern. It will ensure that only one copy of it is ever created and all your classes should be able to access it. This is a well accepted pattern in the iOS SDK (NSUserDefaults, UIApplication, etc..). Just beware of this class growing too large or doing too many things. Try your best to keep it simple and focused and the Object-Oriented Police will leave you alone.
Other resources and opinions worth considering:
http://www.cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html
Is it a bad practice to use your AppDelegate as your Singleton?
Is it good practice to use AppDelegate for data manipulation and Handling?

Related

Good or bad idea to prefix all classes with same abbreviation?

So in practically all my programs I wrote I always prefixed every class I created with the same abbreviation that was in relation to the program. So for instance say I wrote an app called GasStationDeluxe. I would make a class called GSDGasStation or GSDGasPump etc. Now I always thought that is a good idea because it would group together all thelse classes I created in intellisense to make it easier for me and other programmers to find the classes I created.
Yet, I'm reading a book called "Clean Code: A Handbook of agIle software craftsmanship" and I just read a part in a chapter where it says it's not a good idea to do that becasue auto complete will bring you back a list of tons of classes. So who else codes this way? Do you think it's a good or bad idea to code with the same prefix before each class? If yes or no, then why?
I have never done this, but you will sometimes see it done in solutions with multiple projects like GSD.App or GSD.Core
I was always that in a class called Customer.cs, you might not want to make the name field CustomeName but just Name as your already in the customer class so what is it adding. I suppose the same is true in your case of classes.
What if you want to reuse your classes elsewhere? I would say from the vast majority of code examples I come across and other peoples code I read, this isn’t common practice.
I suppose really it’s up to you and any team you work with, as long as it’s consistent.
I wonder what .net would look like if Microsoft prefixed everything!

Best Practise for storing data in an iOS app?

I've looked through a lot of answers on stack overflow but haven't found anything that answers this question.
I have an app where you download data in a downloadVC (there are many other VC's). I want to be able to access the currentUser and the downloaded data in the downloadVC whenever I go to the downloadVC without re-downloading the data.
The options I've looked at so far are:
Making a singleton with data that I could access at all points of the app (feels like the easiest way but people have warned me singletons aren't good).
Making a class var of download VC. (This is the solution I understand the least, what is the scope of a class var? Is it just the same as making a singleton?)
Passing it around (This wouldn't work for me as the app is too big to have it passed between every VC)
Saving it to user defaults, (how quick is accessing something user defaults?)
Please tell me if this questions doesn't fit the stack overflow rules?
Singletons are usually implemented using a static variable, so your first and second options are quite similar.
There is a "singletons are evil" sect that's very vocal in the development community lately.
Personally, I think they have their place and can sometimes clean up your design. I recently worked on a project that had been designed by a member of the "Singletons are evil" cult who then went to absurd lengths to pass a data manager object around to every other object in the project, resulting in a lot of overhead and more than a few bugs when the object got dropped.
There is no one answer. You need to weigh the pros and cons of different approaches for your app.
I would caution against over-using UserDefaults though. That's intended for saving small bits of data like user preference settings, not big data objects.
Basically, adding any networking logic inside the view controller is a first big mistake that you could make. So move that to another class that is responsible only for sending network requests and handling the responses.
Then, when you have the data downloaded, you'll probably need something to manage the cache - no matter whether it is a set of big files or a couple of small strings, the logic would be the same - to have all this cache controlled by one object. This cache manager could save the objects to local files, use CoreData or simply keep those objects in memory - this is for you to decide, depending on what kind of app are you creating.
Now, the cache manager could basically be your endpoint for view controllers, since it will either download the data and return it to view controller after the request's success, or return it immediately. The view controllers don't really have to know about any networking at all.
But, how the view controllers will find out about the cache manager?
You could either pass around the reference to it, but you've already said that this is impossible in your app. So basically another solution would be to use the hated singleton pattern. I too personally think this is a bad pattern, however you cannot create any app without it, since you always must have at least one singleton, which is AppDelegate.
Anyway, a good idea might be to create a singleton class (or maybe even use the AppDelegate for that purpose), that would be responsible for handling the dependencies between the classes responsible for networking, the cache manager, and any other classes that you might need to perform some logic behind your app. This is actually a pattern called Dependency Injection Container. It would allow you to easily access your model classes through this container, without neither having a ton of singletons that will eventually make you confused, nor creating some ridiculous logic of passing around the model objects.
The simple answer is, yes, you use a singleton.
That's exactly correct.
Note that whether you use
SQLite.swift,
core data,
realm.io,
write to a text file,
a baas such as Firebase or Back4app (aka Parse),
or literally just "keep it in an array" ("in memory"),
Yes, the answer to your question is you'll have singleton which is where you "keep - access" that stuff. Exactly correct.
That seems to be what you are asking here.
Given that ...
... if you are then additionally asking "what's the easiest / best / most modern way ("in my data singleton") to store data locally in my app", the real-world answer in 2017 is
realm.io
Previously you used Apple's core data. Which is (a) spectacular (b) extremely difficult. Importantly though: realm.io and SQLite are identically available on both Android and iOS; in very many cases, on real world projects today, this eliminates Core Data from consideration.
However. All of this is somewhat moot. Don't forget ...
We now live in a "baas world"
You can't eg. "get a job programming iOS or Android" any more. You get a job because of how good you are / your specific expertise areas in either Firebase, Parse, PubNub, Cloudbase, or whatever. For better or worse, being able to move buttons and tables around in Xcode, Studio, is not really a thing anymore. (There are a minuscule number of hyper-specialities, like GPU programming, dynamic mesh, or the like, that are exceptions to this.) Similarly, say you're a hobbyist making your own app or startup: again in that case, it's just entirely and totally about what backend you work with. (And that applies equally to games or business/social apps.) There are simply no "local, static" apps any more. (Again, applies equally to games or business/social apps.)
(Note indeed that realm.io, which is "the" simple, obvious way to keep data on apps these days - indeed, those guys have/are moving to becoming, indeed, a OCC cloud baas-paas-whatever service themselves. We'll probably all just use realm.io instead of Firebase in a year.)
So in a sense the answer to your question is something like Firebase or back4app. But: then within your app, you centralize that to a singleton, indeed (the first part of your question).
But note....................
it is extremely unlikely, at the beginner level, that any of this will be relevant: Just keep the data in an array! That's all there is to it. OK, once in a billion years when a user happens to literally restart the device or your app, the app will reload data. So what?
Note that a common name for your "get data here" Singleton is
Local
So,
import Foundation
often .. import SQLite, Realm, Firebase or whatever
public let local = Local.shared
open class Local {
static let shared = Local()
fileprivate init() {
print("'Local' singleton running AOK")
}
// could be this simple..
var clients:[String:[Blah]] = [:]
var stock:[String:String] = [:]
func loadStockInfoFromWWW() { ... }
func calculateQuantityInfoOrWhatever() { ... }
// or it could be more like this..
func reloadClientsFromParse() { ... }
func sendNewDataToFirebaseParse() { ... }
.... etc
you then just access it from anywhere in your app like
local.updateFromWeb()
height = local.stock["ladders"][idNumber].size.h
and so on.
That's all there is to it.
(A word on singleton code style.)
It depends on file complexity & size. If you don't need to parse the contents, or they're simple to parse, but it's large in size then I'd recommend using the Documents folder and retrieving it from there, if it's small or involves complex processing then a singleton acting as a manager would be my approach as it feels appropriate.

AppDelegate property or Singleton Object?

This is more of a design best practice question:
When you are designing the structure of lets say a location based app. The location Manager is obviously an important instance and should be given easy access for other objects.
Should you have it as a property of appDelegate? or a singleton on its own?
Under what scenario would you prefer one over the other?
I understand both would work, but I want to make sure I'm doing things the right way, not just hacking everything together.
Your inputs are much appreciated!
Neither.
Pass in a location manger object via a custom init method or property where ever you need it.
This will conform with the SOLID principals S, O & D (single responsible, open-close, dependency inversion).
Also testing with mocks will be possible more easily.
The worst choice IMO is to store things in the app delegate. See What describes the Application Delegate best? How does it fit into the whole concept? for much more on that. In short, the app delegate is the Application Delegate. It is not "the Application Dumping Ground for Globalish Things."
Singletons are a long-established approach in ObjC, via the shared... pattern. After decades of popularity, and extensive use within the core Cocoa frameworks (NSUserDefaults, NSNotificationCenter, NSApplication, NSFontManager, NSWorkspace, UIDevice, etc. etc. etc.), they have in recent years fallen into some disregard in favor of other techniques, particularly "dependency injection," which is just to say "assigning to a property."
After years of using singletons in ObjC, I am coming around to the DI way of thinking. The improvements in testability and the improved clarity of dependencies are quite nice. That said, sometimes DI can lead to awkward transitions, particularly when dealing with storyboards.
So, I would say:
When practical, just construct objects and assign them to properties on the objets that need them.
If you have a lot to pass around, consider collecting them into a single "configuration" object and pass that around (but this hurts modularity somewhat).
If DI creates chaos (particularly if it leads to a lot of passing objects to things just so they can pass the object on to something else), or if it forces a lot of storyboard segue code that you could otherwise avoid, singletons are a well-established and well-respected pattern in Cocoa and are not wrong. They are a Cocoa Core Competency.
If you ever find yourself calling (MyAppDelegate *)[[UIApplication sharedApplication] delegate], then you're doing something wrong.
Make another singleton for location management. Single responsibility is a first principle of SOLID.
Think about do you really need it in AppDelegate ?
For Location Manager for example, no you don't. You better keep the location manager with all its related methods in a separate class to keep the singularity principle as #vladimir said, and to be able to reuse it later.
AppDelegate is responsible for handling what happens when the app launch and/or going to the background, initializing core data, registering to push notification and other 3rd party libraries like parse,...
Adding other things to appDelegate will make it grow larger by time and it would be very hard to maintain.
When to add things that don't belong to AppDelegate to it? I think when the app is small, you know it won't scale up, and you are required to favor time over clean code.
Check the AppDelegate responsibilities , and this answer by Matt
You can create multiple instances of CLLocationManager and use them wherever you need them.
If you create one instance and try to share it then you'll have trouble trying to forward the delegate methods around or try to re-implement them as notifications leading to a big mess.

Data Accessor object singleton or some other pattern? (Objective C)

It seems to satisfy the three requirements here: On Design Patterns: When to use the Singleton?
I need it to exist only once.
I need to access it from all over the source base.
It handles concurrent access, i.e. Locks for writes, but can handle concurrent reads.
Hi all,
I've been reading a lot of no doubt intelligent educated and wise gems of advice that Singletons are 'Evil' and singletons are anti patterns or just plain bad news.
With the argument that logging makes sense but not much else.
Just interested to know if the case of essentially a persistent data store context makes sense for a singleton, i.e. Reading/Writing from disk to memory and referencing an object graph.
And if not, how do people normally tackle this issue, I don't currently have any problem with it, I know it's created only once, it's fast and the accessor logic is in one place. Meaning it takes me one line of code to do anything data model related.
Which leaves the only argument that it's bad for testing, in that it's a hard coded production implementation to data, but couldn't I just write a method swizzle through a category or in the test code to create the test version of the singleton?
And the final argument from DI testers, is that it is a hard coded implementation, rather than simply an interface to something, which I do get but I don't really have a major drive to use a DI framework given that I can use protocols for implementation, and use separate init methods for setting up an objects state in testing. There's only ever going to be two types of state for the singleton, or realistically one type...production.
Making it (in my opinion) much easier to read and faster to develop.
Change my view SO?
Yup, for some singletons are Evil. For the new developers who has little MRC knowledge and more ARC it sounds scary because they need to mess with memory,volatile,synchronize etc.
However it is not against to use them, they indeed has their own purpose to use with some are below.
when sharing large data models like arrays and dictionaries etc between multiple screens (VC's) we can't prefer storing them in UserDefaults (because userdefaults is permanent storage and storing such large entries make app start lazily) instead singletons are best since they stay only current app context and restarting app creates new one.
when we need a stable db connection to be accessible allover the app without messing up with connecting and closing in every business classes we can go for it.
when we wanted an ability to app for theming itself dynamically we would need to create a singleton class which holds all the color,image instances etc. and use that instance in application VC/Views etc so no code duplication and re-processing theme occurs in all places.
You dont have to change your view but tweak it a bit to get some positive intention towards singletons.
Hoping this clears it out, thanks

Why does Apple documentation that getting ManagedObjectContext from UIApplicationDelegate is bad?

Just curious why ManagedObjectContexts should be passed to UIViewControllers when they are created, rather than just grabbing them from a UIApplicationDelegate?
The docs say that this makes your applications more rigid, but I am failing to see the nuances of when to use which pattern.
Thanks!
Imagine that I ask you to do some task, like painting a room. If I just tell you "go paint a room," you'll need to ask me a lot of questions, like:
Which room?
Where's the paint?
Where are the brushes?
Should I use a dropcloth?
In short, you won't be able to complete the task without help from me. If you have to depend on me every time, you won't be a very flexible painter. One way to deal with that problem is for me to give you all the stuff you need at the outset. Instead of "go paint a room," I'll say "please paint room number 348 using this bucket of paint and this brush, and don't bother with a dropcloth." Now, you've got everything you need, and you can get right to work with no further help from me. You're a much more flexible worker because you no longer depend on me.
The same thing applies to view controllers (and objects generally); it's better to give them everything they need than to have them depend on a particular object like the app delegate. It's true not just for managed object contexts, but for any information they need to do their job.
This is mainly because you want to use dependency injection with your UIViewControllers instead of just grabbing everything from UIApplication, this keeps your delegate clean instead of full of reference hacks.
This is also to keep with the MVC pattern:
Model
View Controller (Only for view logic)
Controller (For coordinating between the view and the model)
I tend not to agree with this pattern.
First of all I try to treat Core Data as an implementation detail, and as any implementation detail it should be hidden behind a good facade. The facade is the interfaces I expose for my model objects. For example if I have two model objects; Cource and Student, any cource can have a number of students. I do not want to let the controller take upon the duty to setup predicates and sort descriptors, and jump through all Core Data hoops just to get a list of students for a particular class. There is a perfectly valid way to expose this in the model:
#interface Cource (StudentAccess)
-(NSArray*)studentsStortedByName;
#end
Then implement the ugly stuff once and for all in the Model class. Hiding all the complex details of Core Data, and no need to pass around managed object contexts. But how would I find the sources, it has to start somewhere right? Yes, it does but you need not expose it to the controller. Adding methods such as these are perfectly reasonable as well:
#interface Cource (CourceAccess)
+(Cource*)caurceByID:(NSString*)courceID;
+(NSArray*)allCources;
+(NSArray*)courcesHeldByTeacher:(Teacher*)teacher;
#end
This also helps in minimizing dependencies between controllers. And reducing he dependencies between the model and controller. Assuming I have a CourceViewController and a StudenViewController is I did not hide the Core Data details behind a facade and wanted to pass around the managed object context as well, then I would end up with a designated initializer like this:
-(id)initWithManagedObjectContext:(NSManagedObjectContext*)moc
student:(Student*)student;
Whereas with good a good facade I end up with this:
-(id)initWithStudent:(Student*)student;
Minimizing dependencies behind facades, in favor of dependency injection also makes it much easier to change the internal implementations. Passing around the managed object context encourages each controller to implement their own logic for basic stuff. Take for example studentsSortedByName method. At first it might be sorter by last/first name, if later changed to last/first name sort you would have to go to each and every controller that has sorted students and make the change. Where a good facade method requires you to change in one method, and all controller automagically get the update for free.
The Apple Docs try to foster the most widely applicable and sustainable design patterns.
Dependency injection is preferred because it allows for the most flexible, expandable, reusable and maintainable design.
As apps grow in complexity, using a quasi-singleton like parking the context in the app delegate breaks down. In more complex apps, you may have multiple context tied to multiple stores. You might want the same view-controller/view pair to display data from different context at different times or you may end up with multiple context on different threads/operations. You can't pile all those context up in the app delegate.
If you have a simple app with a single context then using the quasi-singleton with the app delegate can work well. I've used it on several smaller apps in the past without immediate issue but I did hit scalability problems on a couple of apps when the apps grew overtime.
Which pattern to use depends on your shipping constraints and you best guesses about of the evolution app over its entire lifecycle. If its a small one shot app, then the app delegate quasi-singleton will work fine. If the app is more complex, might grow more complex or might spawn other related apps that will reuse existing components, then dependency injection is the way to go.

Resources