This is the third post in a multi-part series on the Realm Mobile Database; it highlights some of the multi-platform aspects of the the database and the high reusability of the code across devices. If you missed the first post on our custom engine or the second post on the benefits of some of the Realm API types, we recommend taking few minutes to read through. Also, make sure to check out the fourth post highlighting how a flexible, solid SDK like Realm’s empowers good development practices., the fifth post on Realm SDK features that allow developers to provide partial UI updates based on fine-grained notifications, and the final and sixth post, which shows how the features in the previous parts come together to make a database for modern mobile apps.
The Realm Mobile Database was designed from the ground up to run on mobile devices. At the time both iOS and Android used to lack a present day, modern database designed for the specific needs of mobile developers: working easily with objects instead of writing SQL queries, a very high-performant engine that allows for quick chunks of work even on the main thread, an expressive native language API, and more.
As mentioned in the previous post in this series, the Realm Mobile Database is written in super fast C++ (the database core is open source, and you’re welcome to peek in).
Since C++ code runs almost anywhere, running on both Apple devices and Android is a piece of cake for the Realm Mobile Database. In fact, both platforms offers almost the same features and differ only in the syntax of the high-level API:
- Swift developers use a more swifty API,
- Objective-C programmers enjoy a native Cocoa style API,
- and Android developers use an API, which is more Java like.
In fact, to make sure as many as possible mobile developers can use its database, Realm offers high-level APIs for some multi-platform solutions as well:
- C# developers can create both iOS and Android apps using Xamarin Studio,
- and JavaScript developers can use it with ReactNative.
Sharing Your Data Layer Across the Apple Platforms
Sometimes it’s easy to forget that each Apple device runs a different operating system. Kudos to Apple for making it so easy to write cross-platform code!
You are, however, using a different SDK when creating a full-blown Mac, or an Apple Watch application. You use the same programming language - Swift (or Objective-C), but it is a different SDK and a different OS.
Thanks to the fact that Apple has made it so easy to create multi-platform projects and to reuse code you have laying around, you can share a lot between projects no matter which platform you’re using. With Realm, you can share your database layer as well!
In this post, we are going to have a look at a project that shares its data layer between iOS, macOS, tvOS, and watchOS.
You can clone the project from GitHub and run it locally if you want to play around with it.
We’re going to be looking into a “Top GitHub Repos” app - it loads the Top 100 popular Swift repos from GitHub and allows the user to search and favorite them. Not a very complex example, yet it clearly demonstrates the benefits of re-using the whole data layer between platforms.
The Xcode project has specific code for each supported platform. The code that only depends on Apple’s Foundation
, like the networking layer, is shared between all platforms.
Oh yes - also Realm objects and the whole data layer is shared between all platforms because these depend only on Foundation
and RealmSwift
:
When you run the Mac version of the project you will see a typical Mac app pop up on screen:
When you run the Watch target you will see the Watch Simulator display an app with the typical UI for that OS:
Note: It might take quite a while until the watch simulator fetches the repos from GitHub though. In a production app you’d like to fetch them from the companion iOS app instead (we wanted to focus on code sharing in this example).
Let’s have a look at some of the code (it’s pretty easy to read through even if your favorite language is different).
One of the Realm objects all those apps share is Favorite
- it allows for a Repository to be marked as a favorite and assign it a favorite symbol:
import Foundation
import RealmSwift
class Favorite: Object {
//persisted property
dynamic var symbol = "💖"
//dynamic property
var symbolIndex: Int? {
return Favorite.symbols.index(of: symbol)
}
//static properties
static let symbols = ["💖", "🚀", "🤕"]
static let noSymbolIndex = -1
}
The class features both persisted and dynamic properties but all said and done the only two frameworks it depends on are Foundation
and RealmSwift
. This makes the class shareable across all platforms that those two support. If you check the file membership in Xcode you’ll see the file is re-used as-is in all four targets:
The benefit of being able to share and re-use code is that you get to write it only once, test it once, and your data entities can never get out of sync between the different versions of the app.
If you read further in that same file, you will see that Favorite
features even some simple helper methods:
// MARK: - Favorite model methods
extension Favorite {
func set(symbol newSymbol: String?) throws {
guard let realm = realm,
let symbol = newSymbol else { return }
try realm.write {
self.symbol = symbol
}
}
}
For a more complete business logic implementation, you’d probably like to create a separate structure of classes. But some basic methods like the one above could also go directly in the Favorite
class and be re-used along with the entity definition itself.
I hope this overview really puts the phrase “write once, use anywhere” in perspective! In the next post, we’ll discuss in a bit more detail how the re-usability of Realm objects and the excellent level of isolation allows for a better app architecture.
Sharing Data Entities Even Further
So far you’ve seen how to re-use code across four different operating systems, but they were all within the Apple eco-system.
You can share code in both Swift and Objective-C across those four Apple platforms, but you would most certainly want to expand to Android in order to reach another multitude of mobile users.
Let’s translate the Favorite
class in Java for the Android version of the same app:
public class Favorite extends RealmObject {
@Required
private String symbol = "💖";
private static String[] symbols = {"💖", "🚀", "🤕"};
public static final int NO_SYMBOL_INDEX = -1;
public String getSymbol() {
return symbol;
}
public void setSymbol(String symbol) {
if (symbol == null) return;
this.symbol = symbol;
}
public int getSymbolIndex() {
for (int i = 0; i< symbols.length; i++) {
if (symbols[i].equals(symbol)) {
return i;
}
}
return NO_SYMBOL_INDEX;
}
}
It’s visible even to the naked eye how similar those classes are, yet not completely identical. They do however bind to the same underlying C++ structure and ultimately to the same data stored on disc.
There are few interesting aspects to that fact.
You, obviously, cannot re-use the code as-is between iOS and Android, since one is written in Swift or Objective-C and the other is in Java.
You can, however, easily keep them in line - you see that the basic data types are the same, and Realm’s API to create object relationships is identical.
Even further - you can choose to re-create the same simple helper methods you have included in your class across platforms. Then the two entities are identical across iOS and Android, and you can also synchronize the test suits covering Favorites
and its behavior!
Keeping your entities identical across platforms does have a greater benefit than just coherence, re-usability, better testability, and the simple joy of using a fantastic API across platforms.
And now for the real kicker - once you install the free Realm Mobile Platform on your own server, you will provide out-of-the-box data synchronization between your tvOS, macOS, iOS and Android apps!
The data syncing will come at no cost since your entities already have the same structure and the Realm Object Server will know exactly how to keep them in sync.
We Hope You Like What You’re Seeing!
We’ve looked a bit into multi-platform solutions with Realm Mobile Database. But a solid, reusable data layer is just the foundation of a robust mobile app, and we’re going to explore this in more detail in the next posts in this series.
As always, if you have few extra minutes, you are welcome to check out the Realm Mobile Database:
- Download the database (it’s free!)
- or (speaking of multi-platform APIs) read through how to use Realm with RxSwift.
In the next installment in this series, we’re going to look in more detail into this series’ companion project. We’re going to see how the Realm API empowers a clean and flexible app architecture.
See you next time! 👋
Receive news and updates from Realm straight to your inbox