Swift-Based Conversion Between Realm.Object and Business Models Using Protocols
This article explains how to implement a Swift‑centric conversion framework that maps Realm.Object instances to plain business models and vice versa by defining protocols, leveraging Mirror for reflection, handling basic and complex types, and providing generic solutions for collections and optionals.
Realm is a cross‑platform mobile database released in July 2014, offering advantages such as cross‑platform support, ease of use, performance over SQLite/Core Data, and visual tools. In a project that uses Realm, developers must define special data models based on Realm.Object , which cannot be used directly across threads.
To avoid repetitive conversion code between Realm objects and business models, the article proposes a Swift‑only conversion approach that relies on protocols instead of traditional Objective‑C runtime tricks.
Preparation
The goal is to convert a Realm.Object to a plain business model (which inherits from NSObject ) and back. The business model must conform to a Persistable protocol that defines methods for creating a managed object and for instantiating a model from a managed object.
protocol Persistable {
associatedtype ManagedObject: RealmSwift.Object
public func managedObject() -> ManagedObject
public static func modelInstance(managedObject: RealmSwift.Object) -> Self
}Realm.Object → Business Model
The default implementation creates an instance of the model using an extension on NSObject and then populates its properties via reflection:
extension Persistable where Self: NSObject {
public static func modelInstance(managedObject: RealmSwift.Object) -> Self {
var instance = Self._creatInstance()
AutoExchangeHelper.updateModelWithObject(model: instance, managedObject: managedObject)
return instance
}
}Two steps are performed: (1) create the model instance, (2) assign values to its properties using setValue(_:forKey:) . The creation uses an NSObject extension:
extension NSObject {
static func _creatInstance() -> Self { return self.init() }
}Property traversal uses Mirror to iterate over model properties, compare their types with Realm's schema, and assign values accordingly. Basic types (String, Int, Date, etc.) are set directly, while collections and objects are handled recursively.
Handling Collections
Realm's List<T> is converted to Swift arrays [T] by extending List with a protocol that extracts the underlying Swift array:
private protocol _BaseValueProtocol { var _snsBaseValue: Any? { get } }
extension List: _BaseValueProtocol {
var _snsBaseValue: Any? {
var values = [Element]()
forEach { values.append($0) }
return values
}
}Generic collection creation is achieved by defining an _AutoMallocObjectProtocol and providing default implementations for Array , Set , and Optional types, allowing recursive instantiation of nested elements.
extension Collection {
static func _collectionCreatInstance() -> [Iterator.Element] {
return [Iterator.Element]()
}
}
extension Array: _AutoMallocObjectProtocol, _MallcoContentInstanceProtocol {
static func _creatInstance() -> Array
{ return _collectionCreatInstance() }
static func _creatElement() -> Any? { ... }
}Optional types are also extended to support instance creation, ensuring that [T]? and similar signatures are correctly handled.
Summary
The article demonstrates a complete Swift protocol‑oriented solution for converting between Realm.Object and plain business models, covering basic types, nested objects, generic collections, and optionals. The same principles can be applied in reverse (model → Realm.Object) with minor adjustments. The approach showcases the power of Swift’s protocol extensions for clean, reusable data‑mapping logic.
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.