Safe and easy wrappers for RealmSwift

Last update: Jun 15, 2022

RealmWrapper

Cocoapods Carthage compatible Swift GitHub license Build Status

RealmWrapper is wrapper library for RealmSwift in realm-cocoa

If you use RealmWrapper, you can easily use UI update through Notification and Transaction processing. Also, you do not have to worry about the retain cycle when using self in the Notification block.

At a Glance

If you use RealmSwift, you have to be careful about try statement and thread processing every transaction. However, In RealmManageable which manages one realm file, transaction processing is performed using Realm-only DispatchQueue. RealmProxiable, which owns RealmManageable, can easily add, modify or delete models without having to worry about try statement and thread processing.

User Model

@objcMembers
class User: Object {
    dynamic var id: String?
    dynamic var name: String?

    override static func primaryKey() -> String? {
        return "id"
    }
}

var user = User()
user.id = UUID().uuidString
user.name = "Kevin"

Using RealmSwift

let realm = try! Realm(configuration: Realm.Configuration(fileURL: URL(fileURLWithPath: RLMRealmPathForFile("user.realm")), schemaVersion: 1, objectTypes: [User.self]))
try! realm.write {
    realm.add(user)
}

Using RealmWrapper

UserRealmManager().transaction(writeHandler: { (realm) in
    realm.add(user)
})
UserRealmProxy().append(user)

Threading

  • By default, you can use the transaction function to process a Realm Transaction in MainThread
UserRealmManager().transaction(writeHandler: { (realm) in
    realm.add(user)
})
  • It can be implemented by a background thread using DispatchQueue and isSync parameters.
UserRealmManager().transaction(isSync: false, writeHandler: { (realm) in
    realm.add(user)
})
UserRealmManager().transaction(writeQueue: DispatchQueue(label: "background"), isSync: false, writeHandler: { (realm) in
    realm.add(user)
})
  • You can add completion closure.
UserRealmManager().transaction(isSync: false, writeHandler: { (realm) in
    realm.add(user)
}) { (realm, error) in
    self.tableView.reloadData()
}

Getting Started

  1. Create a RealmManager that manages one realm file.
final class UserRealmManager: RealmManageable {

    var isUseInMemory: Bool {
        return false
    }
    var schemaVersion: UInt64 {
        return 1
    }
    var fileName: String {
        return "user"
    }
    var objectTypes: [Object.Type]? {
        return [User.self]
    }

}
  1. Create a RealmProxy that is responsible for the CRUD function to be accessed by the Controller.
struct UserRealmProxy<RealmManager: UserRealmManager>: RealmProxiable {

    var users: RealmQuery<User> {
        return query(sortProperty: "date", ordering: .ascending)
    }

    func append(_ user: User) {
        rm.transaction(writeHandler: { (realm) in
            realm.add(user, update: .all)
        })
    }

    func delete(_ user: User) {
        rm.transaction(writeHandler: { (realm) in
            realm.delete(user)
        })
    }

    func updateName(id: String, name: String, age: Int) {
        guard let user = userFromId(id) else {return}

        rm.transaction(writeHandler: { (realm) in
            user.name = name
            user.age = age
            realm.add(user, update: .all)
        })
    }

    func userFromId(_ id: String) -> User? {
        return query(filter: "id == '\(id)'").results.first
    }

}

var user = User()
user.id = UUID().uuidString
user.name = "Kevin"

UserRealmProxy().append(user)
UserRealmProxy().delete(user)
UserRealmProxy().updateName(id: user.id, name: "Kris")
  1. If you want to register the notification of the status of the Realm object in the controller, you can register the notification in RealmQuery.
let users: RealmQuery<User> = UserRealmProxy().users

users.setSection(0)
    .addInsertNotificationBlock(self) { (self, insertions) in
        self.tableView.reloadData()
    }
    .addModificateNotificationBlock(self) { (self, modifications) in
        self.tableView.reloadRows(at: modifications, with: .fade)
    }
    .addDeleteNotificationBlock(self) { (self, deletions) in
        self.tableView.deleteRows(at: deletions, with: .fade)
    }
    .registerNotification()

Also, since RealmQuery is doing weak handling to prevent the retain cycle, you can use closures without worrying about the retain cycle if you pass only self.

public func addDeleteNotificationBlock<Object: AnyObject>(_ object: Object, block: @escaping (Object, [IndexPath]) -> Void) -> Self {
    deleteNotificationBlock = { [weak object] (deletions) in
        guard let weakObject = object else {return}

        block(weakObject, deletions)
    }
    
    return self
}

Usage

RealmManageable Property

Property Type Default Description
isUseInMemory Bool required Use InMemory Realm
fileName Bool required Realm File Name
appGroupIdentifier String? nil Value for Realm file directory for App Extension

Example

  1. run carthage update
$ carthage update --platform iOS
  1. open RealmWrapper.xcodeproj
$ open RealmWrapper.xcodeproj
  1. run RealmWrapperExample

Installation

CocoaPods (iOS 9+)

platform :ios, '9.0'
use_frameworks!

target '<Your Target Name>' do
    pod 'RealmWrapper'
end

Carthage (iOS 9+)

github "k-lpmg/RealmWrapper"

LICENSE

These works are available under the MIT license. See the LICENSE file for more info.

GitHub

https://github.com/k-lpmg/RealmWrapper
Comments
  • 1. Occurring UI lag while insertion process

    Hi @k-lpmg!

    I'm trying to insert a batch of data (~10k, 15k). UI gets laggy while insertion process, and i'm using the different thread instead of main thread.

    Some details about getting lag of UI:

    Bad scroll experience of sliding table / collection view. UI is not freezing entirely. It's happening for a second, really short time but affects UI experience.

    You can see in below;

    ekran resmi 2019-02-20 02 42 12 ekran resmi 2019-02-20 02 39 25

    and last one;

    i'm calling that method like that;

    ekran resmi 2019-02-20 02 43 23
    Reviewed by batuhansk at 2019-02-19 23:44
  • 2. Completion block is firing in proper way.

    This commit allows the completion block to run after the transaction is finished. The current version of the lines are firing the completion block immediately.

    Reviewed by batuhansk at 2019-02-23 22:31
  • 3. Object property is unreachable in the realm result

    Hi. I have some question about the realm result property, this is my first time to use realm

    struct UserRealmProxy<RealmManager: UserRealmManager>: RealmProxiable {
       func getUser(_ userId: Int) -> User? {
            let result: RealmQuery<User> = query(filter: "id == \(userId)", sortProperty: "id", ordering: .ascending)
            return result.results.first
        }
    }
        
    

    When my service code want to fetch user from realm, the result is not nil, but the property from this realm object is still unreachable(empty) in the view render process. it's so weird.

    Reviewed by waltcow at 2019-01-21 11:36
  • 4. There are three compiler warnings.

    Every waring happens in RealmManageable.swift and same warning.

    It says

    'public' modifier is redundant for instance method declared in a public extension

    It's not a big issue, but if fixed, appreciated.

    Reviewed by MasaruKitajima at 2019-07-27 11:13
  • 5. RealmSwift 3.17.1 has changed UpdatePolicy

    In the previous versions, realm.add(users, update: true) was right, but for the 3.17.1, we must choose options update from

    • error
    • modified
    • all

    So, it's like realm.add(users, update: .all) for an instance.

    Please refer further details at RealmSwift Doc

    Reviewed by MasaruKitajima at 2019-07-18 06:54
  • 6. Support for Realm 10

    firstly thanks for your great framework! Since Realm is now on version up to 10, I wanted to ask if you think about supporting the new 10 version?

    Thank you in advance

    Reviewed by Yetispapa at 2020-11-29 13:40
A concise Mantle-like way of working with Realm and JSON.

Realm+JSON A concise Mantle-like way of working with Realm and JSON. Breaking Change Method - deepCopy replaces the previous functionality of - shallo

May 14, 2022
Sample app to demonstrate data sharing between a WatchKit app and its main app using Realm
Sample app to demonstrate data sharing between a WatchKit app and its main app using Realm

#Done! A sample app demonstrating how to share data between an app an its Watch extension using Realm. You can read more about it here. ##Screenshot #

Apr 2, 2022
Face detection and recognition iOS app with OpenCV
Face detection and recognition iOS app with OpenCV

Facemotion Facemotion it's an iOS app, allowing you to find easily a contact by face recognition. Scan the face of a person, whether the contact is in

Apr 25, 2022
iOS and watchOS app for try! NYC
iOS and watchOS app for try! NYC

trySwiftApp try! Swift Conference App 2016 presentations You can find an overview of speakers and their presentations, including slides and video here

Feb 8, 2022
Safe and easy wrappers for RealmSwift

RealmWrapper RealmWrapper is wrapper library for RealmSwift in realm-cocoa If you use RealmWrapper, you can easily use UI update through Notification

Jun 15, 2022
Safe and easy wrappers for common Firebase Realtime Database functions.

FirebaseHelper FirebaseHelper is a small wrapper over Firebase's realtime database, providing streamlined methods for get, set, delete, and increment

Apr 9, 2022
RxSwift extension for RealmSwift's types
RxSwift extension for RealmSwift's types

RxRealm This library is a thin wrapper around RealmSwift ( Realm Docs ). Table of contents: Observing object collections Observing a single object Wri

Jun 24, 2022
RealmSwift, MVVM with Repository, DI, Coordinators,

Todo_App_With_RealmDB Lol, just playing around because I'm bored ?? Refreshing usage of Realm, been a while. New updates look cool though (first time

Feb 23, 2022
Modern thread-safe and type-safe key-value observing for Swift and Objective-C

Now Archived and Forked PMKVObserver will not be maintained in this repository going forward. Please use, create issues on, and make PRs to the fork o

Mar 13, 2022
A Protocol-Oriented NotificationCenter which is type safe, thread safe and with memory safety
A Protocol-Oriented NotificationCenter which is type safe, thread safe and with memory safety

A Protocol-Oriented NotificationCenter which is type safe, thread safe and with memory safety. Type Safe No more userInfo dictionary and Downcasting,

Jun 24, 2022
MemoryCache - type-safe, thread-safe memory cache class in Swift

MemoryCache is a memory cache class in swift. The MemoryCache class incorporates LRU policies, which ensure that a cache doesn’t

Jan 29, 2022
CCCryptor (AES encryption) wrappers for iOS and Mac in Swift. -- For ObjC, see RNCryptor/RNCryptor-objc

RNCryptor Cross-language AES Encryptor/Decryptor data format. The primary targets are Swift and Objective-C, but implementations are available in C, C

Jun 25, 2022
Swift Property Wrappers, but in Objective-C. And done horribly.

TOPropertyAccessor is an open source, Objective-C abstract class. Similar to Realm's Cocoa API, it uses the dynamic nature of the Objective-C runtime to access the properties of any of its subclasses, and routes calling them through overridable access points.

May 23, 2021
Short examples and references to work with property wrappers in SwiftUI.

A Colection of useful playgrounds This repo contains a collection of useful swift playgrounds. PropertyWrappers Playground Contains small example of u

Nov 24, 2021
CCCryptor (AES encryption) wrappers for iOS and Mac in Swift. -- For ObjC, see RNCryptor/RNCryptor-objc

RNCryptor Cross-language AES Encryptor/Decryptor data format. The primary targets are Swift and Objective-C, but implementations are available in C, C

Jun 20, 2022
A micro-framework that leverages Swift Property Wrappers to implement the Service Locator pattern

Locatable Context Locatable is a Swift micro framework that leverages Property Wrappers to implement the Service Locator pattern, through a custom att

Jan 9, 2022
Helps you define secure storages for your properties using Swift property wrappers.

?? Secure Property Storage Helps you define secure storages for your properties using Swift property wrappers. ?? Features All keys are hashed using S

Jun 23, 2022
A library to inject your dependencies via property wrappers

?? DependencyInjection A library to inject your dependencies via property wrappers ?? Features DependencyInjection allows you to define the dependenci

Dec 18, 2021
Swift wrappers for the tree-sitter incremental parsing system

SwiftTreeSitter Swift wrappers for the tree-sitter incremental parsing system. Remember that tree-sitter has both runtime and per-language dependencie

Jun 17, 2022
A set of SwiftUI dynamic property wrappers that provide a more familiar API for accessing the Contacts framework. (iOS, watchOS, macOS)

Connections Also available as a part of my SwiftUI+ Collection – just add it to Xcode 13+ A set of SwiftUI dynamic property wrappers that provide a mo

Apr 18, 2022