I am starting a new project (learning purposes) and I am trying to figure out what is the best software design pattern to use in the following scenario.
I have several data that need to be downloaded from multiple webservices and store somewhere in my app, to display it later. However each piece of data (e.g. list of teachers, students) will only be used in one or more specific view controllers (e.g. teachersViewController and studentsViewController).
I read that the Singleton pattern or use the AppDelegate to store a variable (an object like ApplicationData) is a bad practise, even more in this example which I want to restrict the data access.
So, which design pattern should I choose? I have read something about dependency injection, but I don't have any clue about it or if it even helps me in this question. If it helps, some examples with explanation would be nice.
You need some sort of database to store downloaded data. Good choices are Realm and Core Data. The right way to process data is:
Check if data is already in DB and show it if available.
Download or update data from server and parse it to objects.
Save objects to DB.
Show data taken from DB to user.
Download data as needed. When you open VC with students then download only students data and so on.
EDITED: If you need all the data on app open then load it and put in a DB before first screen opens. Then just use DB to show data to user.
Related
I create a SQLite connection with SQLite.swift but I'm not sure where to store the DB connection so I can use it during the duration that a user has the app open across various views.
Is using UserDefaults here an appropriate case? Or EnvironmentObject?
What is the recommendation with iOS apps in terms of keeping a DB connection open for reuse?
Is using UserDefaults here an appropriate case?
Definitely not. Like you said yourself: you want it to exist while the app is open. While UserDefaults is for things you want to store when app is not running.
Or EnvironmentObject?
You could, but semantically it's still wrong: Apple defines it as "A property wrapper type for an observable object supplied by a parent or ancestor view.", which doesn't really fit the DB connection. It's not an observable object with states.
Ideally you step back and look at a more generic architecture of your app.
Views want data in a specific format. They don't care where the data is coming from.
The fact that data is coming from DB is an implementation detail - tomorrow you may decide to retrieve it from remote server, and you don't want to change every single view because of that.
So what you really want is
View talks to some sort of "data provider" interface that defines an interface by which views can get their data regardless of where it's stored.
Your implementation of "data provider" is to talk to the local database (currently, but it can changed base don your needs).
In this structure the DB connection(s) are managed by data provider, and do not need to be shared with anyone. And your views will actually use Observable objects, except those observable objects are data itself, not the connection to database (and in fact views will not "know" where the data is coming from).
I will not go into details on how to make that model happen - there are many other details here (like what's overall architecture of your app), but this is the gist of the idea.
I am very new to iOS. I am developing an app with data persistence. I have decided to use Realm for that purpose.
I must to create the database and load data the first time that app runs. I get data from a Web Service in JSON format. I will implement some strategy to update this database later, maybe with iOS Silent Push notifications.
I have read and I have worked about Realm, loading data from JSON... to learn about that.
Now, I need to apply this in my project but I don't know how to start. I need some clues about general idea for the app:
How can I organize my app to load data when it is installed? At what point should I create the database and load data?
I have thought to create a global Realm object y AppDelegate and use it as a global variable. Is it a good idea?
Do I need to set a path for my database? Can I user default path?
If you are looking for a place to start, you can check out the example apps of this UI component add-on for Realm: ABFRealmGridController.
The controller is a subclass of UICollectionView and the example app should demonstrate most of the functionality you are curious about. The example uses the controller to display the top news stories from the New York Times. This involves making a request to their API and loading the JSON response data into Realm.
When to load the data is dependent on how you want the app to function. If the data will be the same for each user, you could bundle the Realm file with the app pre-populated with data.
The ABFRealmGridController example loads data when the user clicks the refresh button and performs the JSON handling on a background thread; a general best-practice.
Finally, unless you have multiple Realms or need to store the file in a specific path, it is probably simplest to use the default path.
New to iOS development..
Basically what i'm trying to do is hard code data into my app using core data. Two different types will be stored, both strings: quotes and authors (There will be around 20 of each in the app). I have a button on my Storyboard as an IBaction that when clicked will populate a label with a new quote and author. My struggle right now is 1) finding out how to create this data and 2) how to fetch this data.
Every resource i'm finding online goes through tutorials on how to store data that a user typed in and then fetch it from a button. I'm trying to figure out how to store data without user input and then fetch it. Any help is appreciated. Sorry for asking what I am sure is a pretty simple question.
Unfortunately, though this would seem like a simple task, to my knowledge there is know "built-in" way to prepopulate CoreData. You can build up a core database and then copy it into an app, or possibly use a third party solution, though. Searching for "prepopulate coredata" here and on google should give you a start.
Here's a couple threads that might help:
Any way to pre populate core data?
iOS CoreData - prepopulate db with existing indexes
I've checked a lot of sites and answers and I can't find any solutions specific to my problem.
I don't need to change the schema for my Core data model, all I need is to modify (add some) content to the current backing SQL Database.
Any direction on this will be welcome. Thanks.
PS: I tried Apple docs and they were about as useful to me as sunshine on Mecury.
Also go easy please, I'm a beginner.
Thanks.
UPDATE;
To shed more light on my issue, my app works as thus. I have preloaded static information on the app that can't be changed by the user, each day has new content. Every month, I push an update with entirely new content specific to that month. However, when my app entered production, upon the update I pushed for this month, my users were complaining that they couldn't access the month's data. This led to me spamming them with Push notifications to have them delete the app and do a fresh install to access the new data.
How can I fix this issue? my schema stays the same, only the data changes.
If I understand correctly you want to pre-fill a Core Data database ?
If you don't care about pre-existing data on existing app, you can make an iPhone or Mac app with the same model, and let it generate the database, like explain here (Any way to pre populate core data?) it's also the way recommended in a really great book if you want to learn more about Core Data (http://pragprog.com/book/mzcd2/core-data).
Do not ever make SQL request directly, Core Data work in his own magic way.
Don't work on the SQLite-Database directly. Change all your Data through NSManagedObjectContext! To find a good strategy look up examples from Batch-Importing.
Update: You could actually have two PersistentStores (one with just static data (readonly) and the other one with user-generated data). You could interchange the readonly which you prefilled with a commandline util and downloaded from a server. You cannot have direct relationships between those two store though.
I would say that it depends on the amount of data in this prefilled store wether you should go this way or just use a plist and reference some string constants in your user data store. Try to do it with a plist as this is the simpler approach.
app scenario: on the UI, a button is tapped to get contact list from the server. the request goes to subproject which does the download and parsing and returns the result thru its delegate to the UI. so far everything works properly. lets say there is no internet connection and we cant have the contact list. to solve the problem, I want to cache the data in core data. if there is no internet, the cached data will be returned. now the question that bugs me, is it possible to create one data model and use it in subproject to save the data and in UI where data get pulled and edit from the same data model?
so basically i want to access core data from different subprojects and UI.
i couldnt find hints or tutorials regarding this issue. any ideas?
thanks in advance!
edit:
a project "b" that is added to the parent project "a". the project "b" is actually a static library.
if i let the library to do the saving and returning data to UI, wont it be inefficient to get all data from core data then send it to the UI?
i actually hope that there is a way to use same data model in both UI and the library.
i want prevent the UI to have huge load of data. its better to hace core data to handle that incl. memory mangement. i'm still reading some sources and trying to implement it on a test project.
I would argue that only the main project should deal with persistency, as than you can always decide to handle it differently — save it permanently or not, use core data or a home grown sql wrapper…. So it would be up the the delegate to decide what to do with more data.
But along with the delegate protocol you could decide to maintain different model protocols that define, what your models can hold. this would be independent to the implementation. The delegate now could return objects — no matter if core data models or not — to the delegator if this objects conforms to the protocols. The delegator in the sub module now could check for values on the server and/or in the cache.