Central Data Source for all my View Controllers - ios

So I have an app with a bunch (like 25+) view controllers. And these vc's use a lot of data, most of which I could either store locally in the app, or store it on my server. I would rather store this data on my server to minimize app size, so in order to do that, I read somewhere that the best practice for doing that is to have a data class, which would be a special class that gets all the data from the internet at one time in one place, rather than just getting the individual data as needed, in like viewDidLoad or somewhere similar. So my question is, is it really better to make a central data source within my app and every class draw from it. And if so, could you provide an example of how I should set up that class. For example, how to make it run in the background (I guess a different thread) and how to pass NSDictionarys and NSArrays, etc. from the data source to individual class as needed. Thanks in advance. I can clarify if necessary.

You are talking about two different topics:
Accessing data from a main source from all the view controllers.
Accessing data from a server.
The best solution for you would be to create a new class that would hold variables that are used by some different classes. This tutorial explains how to do that - I think this would be one of the best solutions that you'll find on the internet.
For solving the second question, you should also create a class that execute SQLite statements and gets information from a database. You should use SQLite in order to do that, and if you won't like it, you could try to use Core Data, although SQLite in my opinion is much simpler.
This tutorial describes how to do that.
After you've done both of the things you can create an instance of the class that handles the database services for you in the class that shares information between the view controllers, and access that instance from different view controllers.
In the end, you could try to perform tasks like that on different threads. You should try doing it using NSOperationQueue objects - they will do most of the job for you. I suggest reading about them in the developer documentation provided by Apple in order to understand how it works.

Based on your replies in the comments, I would recommend this solution:
Transferring data from your server to the device - After downloading
your data from your server, store it into an SQLite database in the
device.
Accessing your data from your many view controllers - Use Core Data
to access the downloaded data in your database from any of your view
controllers.
If you don't know much about database programming, Core Data is an easy way to start. It encapsulates your tables into classes that you access like simple objective-c classes, so you don't have to learn SQL. You can also call them from any and all of your view controllers, whenever you need them, so you don't have to make a special class to handle your data. It is also better performance-wise and cleaner design-wise than passing your data through your view controller hierarchy. See the guide here.

Related

Pattern for handling Firebase models with relationships (iOS)

I'm looking for examples of patterns in existing iOS apps (Swift preferred, but I guess it doesn't matter) to get some ideas on how to handle models when working with Firebase (or any NoSQL DB). The complication is due to 1) the way in which Firebase listens for changes to data, and 2) keeping the db request logic out of the models.
So let's say I have something like this:
struct User {
let name: String
let checkin: Checkin
}
struct Checkin {
let name: String
let coordinates: Double
}
Now when I decide I want data in my view controller, I'll do something like Database.database()..reference()... and have a method on my model parse the JSON and insert it into the model. Now what happens when it gets to a relationship property (in this case, checkin when creating an instance of User)? If I want the full user model with all child relationships, I'm only going to get back something like { checkin: someRandomCheckinId } from Firebase. I could make another call to get the checkin by ID, but I'd have to do that logic in my model when parsing the data received from Firebase, which doesn't seem ideal - it seems that logic best belongs on the VC (or a separate data manager class called by the VC). Is there a better way?
Additionally, I want to be able to listen for changes given it's a main feature of Firebase. I can't imagine polluting my model with a bunch of listeners is a good thing. 🤔
Any examples of repos with a good pattern for this would be great to help wrap my head around an appropriate solution. Thanks in advance!
There are two parts to this question. The first is how to structure data in a NoSQL document store. The second is how to structure an application in a modern OO language. Both expand well past the reach of Firebase and Swift.
For the first part, the advice I would give you to start with is that you should keep related data together for fast access. There is normally a space penalty when working with these type of databases as data is duplicated. This is ok as space is relatively cheap compared to time. In your example, if you often want to get all the 'Checkins' when you get a 'User' then store the 'Checkins' for a user in that user. If you are used to working with RDBs then you need to remember that with this type of storage, you can store layers of data and an attribute can have multiple values. Make sure you read the Firebase documentation on how data is accessed as they have some recommendations for how data should be stored to avoid wasting time and space. The main idea is to keep data flatter rather than too many layers deep and remember that getting a parent also gets all its children. This usually involves some data duplication.
For the second part of the question, you are going to have to dig a little deeper. Start by reading up on the software engineering principles. The SOLID principles are the most important but there are many others that you should abide by. One principle states that you should keep related data and behaviour together. Another states that each module(class) should have a single responsibility(reason to change). Most iOS developers follow the very bad development practice of loading the ViewControllers with all the application logic which violates many principles. Model classes are not just for storing state, they should also contain behaviour related to that state. A ViewController should not be accessing a database and should not know anything about the database. This should happen somewhere in your application model. If data is accessed in a specific way for each type then store that logic with the type. If much of it is the same for all types then abstract that part out.

In which function to load tableView data when the data comes from remote API

I have a UITableViewController instance, which is the data source and the delegate.
The data is provided by a remote API, that takes some time to be called.
I know how to call and populate the cells for sure, but i don't know in which function i need to call the API that loads the data.
Typically i will have something like
var myData : [myOption]?
and when i populate the cells, i can ask if that array is nil or not and if not i can call the API, is this a good way?
Typically you're going to want to keep your data out of the view controller, and you absolutely want to keep your API calls out of the view controller. Create a "model" object that talks to the API. The simplest way to do this is to make the model a shared singleton. (There are some reasons not to use singletons here, but if you're new, I would absolutely do it this way.)
Again, to keep things simple, I recommend using NSNotification to let the model announce when data has changed. The view controller will observe this notification, and when it is posted, it'll call reloadData to refresh itself. All of the data source methods (numberOfRowsInSection, etc.) will be simple calls to the model.
This is the traditional way to build Cocoa apps, and the way I highly recommend people start. As you learn more, you'll probably find other tools that can be better than NSNotification, and you can learn other patterns that replace singletons. And you'll definitely learn better ways to update your table than reloadData, but this will get you a good, strong foundation to improve on.
One of the better pieces of example code, IMO, that demonstrates all of this is The Elements. I highly recommend studying it. It's in ObjC, but it's very clearly written, and learning to convert ObjC to Swift is a core competency of Cocoa developers. (The Elements doesn't talk to a server, but it demonstrates the Model View Controller pattern that you need.)

What is the preferred way to architect functions with coredata?

There is no shortage of tutorials on coredata, or questions here on SO about how to get started with coredata, or how to use specific parts.
My question is higher level - how should a larger project be architected with coredata?
Should the project keep most of the functions that deal with managed
objects in a single class?
Should the functions that deal with the
methods be static (I suppose they are called 'class methods') or
instance methods?
Is it ok to pass managed objects into class
methods from different threads? what about if I also supply a
context to the method?
Should I only be doing a single fetch for each entity when the app starts, then doing all of my searches and inserts against the context, or grabbing smaller sets of data from a fetch request as I need it?
As far as the blogosphere goes, it seems like the coredata architectures are the wild west - every man for themselves. Any good design patterns here to follow?
True, although some of you questions are really based on personal preference. I for one will never use a sigleton.
NO and YES. Yes on class to keep the connection to the context and no every controller will request its own data.
Using class methods requires you to either pass the context around or store it in a static. Using a static can cause problems if you need to change the context.
No, each thread should have it's now context. Core Data is not thread save.
To save memory only fetch what is needed, no sense in fetching everything at once.
I would suggest using NSFecthResultsController for filling things like table views.
If you are fetching data and storing it in core data I can really suggest using a separate context for inserting. Cocoanetics has a great article about multiple context setup.

iOS: Dealing with data and a large amount of views

I have a general design question for dealing with data. I currently am working on an app that stores about 100+ different unique properties (mostly integers, some strings) and am currently using a single object of a custom class to manage all of them.
I need the data to be "persistent" throughout the app so I currently pass the object via segues. I have managed to build 20+ views, most with their own view controller. I am very new to Objective-C and iOS development and have a feeling this is a bad practice.
I do not understand that much about core data and am not sure if it would be a better solution for me. I have also read about singletons and have heard mixed things about using them for this sort of solution.
In the future, I will need to permanently store the data that is held temporarily in the custom class I have written.
What is the best way to deal with this situation? Is it standard practice to pass the object around over many different views?
If the data needs to permeate through the entire app then a singleton might be a good way to go.
In game dev there is a pattern called the chalkboard pattern that allows any part of the game to read and write to the chalkboard. This can be used for health points, scores, etc...
This would suit you well too. Rather than pushing your data model around all the time just use the singleton to access each bit/ If the data needs to be updated then store the updates to the singleton.
The thing to avoid is using the singleton just because its there. If a bit of data needs to get from one place to another then don't just use the singleton if it isn't necessary.

Implement model portion of the MVC

I have a simple game made, still working on some of the additional portions of the game. I am not sure how/where to store my game data (scores, settings, etc)
I've been using a singleton with all of the data that I'll use in the program synthesized for ease of access, but I don't know if this is a good method? It seems to me it would make settings and such quite easy, because I can just share the singleton among the menu view and the game view, without having to copy the data.. Is there another way? Every book I've read so far seems to skip over the model and just combine it with the controller portion of the MVC.
Singletons while appealing for their simplicity generally make the code base less flexible to changes. They also do not encourage a clear separation of functionality in the model.
An alternative is to use core data for the model. You would have a managed object for game,scores, settings etc and pass around references to the objects. With Core Data you get persistence for free along with fast/efficient mechanisms for sorting and presenting data.

Resources