Hello everyone! In today’s article, we will develop the application to a new level. It is possible to use the application offline. Without the internet, we can still access previously loaded data. As you can see, some of the typical applications for this are facebook. When you shut down the network, it can still post, download posts on previously saved feeds. It looks pretty good, it increases the user experience, more professional, right? 😚
So, today we do it, using a framework for databases, quite professionally that is Realm. So what is realm? Maybe in a few sentences, you can’t say all the utilities that this framework brings. However, you can understand that realm helps you store data, pulling out when needed. You can add deletion edits, which can do everything with the data you’ve saved. Very convenient. To better understand, carefully read realm’s documentation for ios here:
https://docs.mongodb.com/realm/sdk/ios/install/
In the previous post, we added loading for the search to make it more professional. There are still a few little bugs, but you can fix it yourself. In this article, I will add realm to store all the results that you searched for memory. Then each search, if it finds the result already in memory, it will proceed to take that result and display it to the table, instead of requesting to the network.
First as in previous articles, you must download the code here:
https://github.com/codetoanbug/MVVMSample.git
And move on to branch bai4. How to transfer, review the first post.
Now let’s start getting acquainted and using realm in a professional way.
- Build realm manager
Consider the RealmManager class I created. The source code is a bit long, but don’t worry, I will analyze it slowly from line to line 1.
The ideas of this class are as follows:
- I want to create a database management layer with full features (save), edit(update), delete(delete).
- I want to store inherited models from Codable. By doing this, I can save the return result of the API directly from the server to the realm.
- Each model must have 1 primary key to update. Saving means updating a model into the realm. If it doesn’t exist yet, add new. If it already has one, update to the existing model.
OK, when you have this realm manager, you will easily do the things that the goal of the article has asked for.
Let’s take a look at the code line by line:
First to play with realm, you need to install realm into Podfile:
The installation is very simple, by opening the Podfile at the project and then adding line 8. Then go to the command line and cd to the source code folder, type: pod install is done!
When you’re done installing, you create a file called RealmManager.swift, then add this line to the top:
realm import
import RealmSwift
The above 2 lines so you can use realm.
Version realm database
Enum RealmVersion: UInt64 {
case version1 = 0
}
The upper line I used to update the database for realm. Every time I revise the model, it needs migration, which involves updating the data with the new model. This one you’ll be interested in later, this one I’m not saying.
I want to update the database according to the primary key so you need a RealmRepresentable that requires a primary key, I named the uid that every Codable object that wants to use realm must have, I use the protocol to do it. RealmRepresentable helps you always have to have a primary key for the model, ensuring the model is always up to date. This RealmRepresentable inherits from Object – a realm class used to handle databases like models. If you’ve done it with sqlite, then you’ll see the advantage of realm here, which is that you can manipulate realms like manipulating models. Not select, delete… sql’s tough statements.
RealmServiceProtocol is a protocol that contains possible functions of a manager. Look at the name of the function you can also guess what it means right:
- associatedtype Entity: Defines an abstract type, protocol generic placeholder. In other words it applies a specific type at the time of compile. It makes the code clearer. Entity is the model we need to save, namely the class of the codable model inherited from the Object of the realm.
- queryAll: This function returns the entire array [Entity]
- func query(with predicate: NSPredicate, sortDescriptors: ) -> : T[NSSortDescriptor]his f[Entity]unction is used to query with certain conditions and sort according to certain requirements.
- func save(entity: Entity) -> Bool: save 1 entity to database.
- func save(entities: [Entity]) -> Bool: Save 1 entity array to database.
- func delete(entity: Entity) -> Bool: Delete 1 entity from the database.
- func delete(entities: )[Entity] -> Bool: Delete 1 arra[Entity]y from the database.
- func deleteAll() -> Bool: Delete all Entities from the database.
Oh, so you understand what we’re going to do, right? Of course, it’s define thui, and now it’s time for real coding. Let’s go to RealmManager class to see 😘
Class RealmManager defines slightly differently from what you do. Here we have the function , which means that every class that inherits this class must <T: realmrepresentable=””>have the nature of RealmRepresentable, or in other words it must have a primary key:</T:>
var uid: String { get }
RealmManager inherits RealmServiceProtocol, which means that every function we just said above must define it.
- typealias Entity = T: Here we define the entity’s style as T, realmRepresentable, i.e. classes with realmRepresentable properties
- Realm.Configuration: Configure parameters for Realm.
- var realm: Realm?: the realm object that we are going to use to handle tasks with the database.
- The init function initials the configuration, which contains the processing of changing the model of the realm. You can see more here to understand more.
- print(“File 📁 url: (RLMRealmPathForFile(“default.realm”)”): This command will display your database path. Download this to see:https
://docs.mongodb.com/realm-legacy/products/realm-studio/index.htmlThe da
tabase image is as follows:
It looks like mysql, don’t you 🥺🥰
- 68->71, if realm cannot be initially initialed, returns empty
- Otherwise, take the Entity array and return it
- If realm cannot be initially initiald, false is returned
- If you do not save the entity to the database in the form of an update, that is, if it is not available, add it, and if it already exists, update it. Then refresh the realm database.
- Assuming the save process fails, proceed to print the error. Here you can leave the print command in the debug #if folder
Similar to save 1 string “func save(: )[Entity] -> Bool” as well as above, only save 1 array.
- Proceed to search the entity with the main key uid, if found, proceed to delete and return true. If false is not returned.
- The error removal case also displays the error and returns false.
Similar to “func delete(entities: ) -> Bool[Entity]” function used to delete an array of entities.
- Proceed to delete all entities in the database and return true. If the error is not deleted, false is returned.
Here you notice that I write a function with a comment on the jaw. If you want it to spawn automatically, you can place the mouse pointer on the function name and click the combination “Option + Command + /”, when you click the mark ? to the right of Xcode, it gives instructions of the jaw, which is very convenient for the birth of documents later.
So we’ve basically completed the RealmManager class, the basic base for processing databases in the realm.
The cards are a little long, so we’re going to stop here temporarily. In the next tutorial, I will guide to write the RealmGithubService class inherited from RealmManager to process the data returned from the API.
Thank you for watching.