Realm Blog

Realm Java 1.1.0 — New and faster Insert API!

by /

We just released a new version of Realm Java to this website and to Bintray. It contains a new insert API as well as a number of bug fixes.

Insert API

Realm’s storage engine has always been faster than SQLite when it comes to inserting data, but due to a number of design decisions in the Realm Java API, that advantage was mostly lost. This meant that Realm was generally as fast as SQLite for a small number of items (<1000), but started getting slower the more items you added in a batch.

In v1.1.0 we came up with some optimizations and now offer 4 new methods:

  • void Realm.insert(RealmModel obj)
  • void Realm.insert(Collection collection)
  • void Realm.insertOrUpdate(RealmModel obj)
  • void Realm.insertOrUpdate(Collection collection)
Realm realm = Realm.getDefaultInstance();
realm.beginTransaction();
realm.insertOrUpdate(restApi.getPersons());
realm.commitTransaction();

These methods differ mostly from the standard Realm.copyToRealm() in the sense that they do not return any objects. This has allowed us to reduce memory allocations to almost zero as well as remove many checks that were pure overhead.

Doing this, we went from being ~40% slower than an optimized SQLite implementation to being ~70% faster for 100K objects.

Realm Batch Insert Benchmark

We have released our benchmarks repo so you can verify these numbers yourself. Find it here. The numbers above were produced on a Nexus 6P using stock Android 6.0.1.

Note that due to Realm’s auto-update features it is possible to query for data before they are even saved, and you will get notified when the data is available. This can be a huge benefit for those of you that want to separate displaying data from saving it:

final PersonApi api = new PersonApi();
Realm realm = Realm.getDefaultInstance();
RealmResults<Person> persons = realm.where(Person.class).findAllAsync();
person.addChangeListner(new RealmChangeListener() {
    @Override
    public void onChange(RealmResults<Person> persons) {
      if (!persons.isEmpty()) {
	    // Callback when data is available
      }
  }
});

realm.executeTransactionAsync(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
      realm.insertOrUpdate(api.getPersons());
    }
});

Bug fixes

  • Combining async transactions and async queries on the UI thread could result in the transaction onSuccess callback being invoked before the data is available on the UI thread.

  • The RealmOptionalAPITransformer introduced in 1.0.1 does not work with DexGuard and has been disabled for now.

See the full changelog for all the details.


Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, and Twitter.

Read more

Realm Xamarin 0.76.0 released

by /

We’ve released version 0.76.0 of Realm Xamarin. This includes the first external contribution, by Joe Brock: support for INotifyPropertyChanged. This adds change notifications to your Realm objects when using data binding with Xamarin Forms. For more information, see From Data Bindings to MVVM in the Xamarin Docs. NuGet should already be telling you that the update is available in existing projects and new projects that you add it to will use the new version out of the box.

Major Changes

  • RealmObject classes will now implicitly implement INotifyPropertyChanged if you specify the interface on your class. Thanks to Joe Brock for this contribution!

Minor Changes

  • long is supported in queries
  • Linker error looking for System.String System.String::Format(System.IFormatProvider,System.String,System.Object) fixed
  • Second-level descendants of RealmObject and static properties in RealmObject classes now cause the weaver to properly report errors as we don’t (yet) support those.
  • Calling .Equals() on standalone objects no longer throws.

Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, or Twitter.

Read more

Realm Xamarin 0.75.0 released

by /

We’ve released version 0.75.0 of Realm Xamarin. This is the first release after the launch, introducing some essential features and fixes. NuGet should already be telling you that the update is available in existing projects and new projects that you add it to will use the new version out of the box.

Breaking Changes

  • File format of Realm files is changed. Files will be automatically upgraded but opening a Realm file with older versions of Realm is not possible. NOTE: If you were using the Realm Browser specified for the old format you need to upgrade. Pick up the newest version here.
  • RealmResults<T> no longer implicitly implements INotifyCollectionChanged. Use the new ToNotifyCollectionChanged method instead.

Major Changes

  • RealmResults<T> can be observed for granular changes via the new SubscribeForNotifications method.
  • Realm gained the WriteAsync method which allows a write transaction to be executed on a background thread.
  • Realm models can now use byte[] properties to store binary data.
  • RealmResults<T> received a new ToNotifyCollectionChanged extension method which produces an ObservableCollection<T>-like wrapper suitable for MVVM data binding.

Minor Fixes

  • Nullable DateTimeOffset properties are supported now.
  • Setting null to a string property will now correctly return null
  • Failure to install Fody will now cause an exception like “Realms.RealmException: Fody not properly installed. RDB2_with_full_Realm.Dog is a RealmObject but has not been woven.” instead of a NullReferenceException
  • The PCL RealmConfiguration was missing some members.
  • The Fody weaver is now discoverable at non-default NuGet repository paths.

Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, or Twitter.

Read more

13,949 Commits and 6,148 Closed Issues Later: Thank You for Helping Realm Reach 1.0

by /

It was July of 2014 when we announced Realm as “the first mobile-first database.” Today — 13,949 commits and 6,148 closed issues later — we’re proud to release Realm 1.0, a major milestone not only for Realm as a company and a product, but also for the iOS and Android developer communities that have embraced Realm.

When we launched, we only offered an Objective-C version of Realm for iOS and Mac developers. First-class support for Swift and an Android version were added later, and just recently we launched initial support for React Native and Xamarin. As a result, Realm is now available to every major mobile platform and programming language. This release is the culmination of more than two years of hard work building and shipping products, and we could not have gotten here without the tremendous support of the community. Thank you! 👏

Even before reaching 1.0, Realm has been broadly adopted by the mobile dev community. You’ve given us over 12,000 stars on GitHub (and counting). Realm is currently used by more than 100,000 active developers and in tens of thousands of apps, including apps with massive usage from companies like Starbucks, Twitter, Anheuser-Busch, NBCUniversal, Alibaba, eBay, and thousands more. They are using Realm because Realm makes their apps better — the developers behind those apps can build better user experiences, more easily and more quickly. With today’s 1.0 release, they can be further assured that Realm products for iOS and Android have reached a key stage of maturity and stability.

To see what has changed, you can look at our changelogs for Java, Objective-C, and Swift.

What is Realm?

Realm is not an ORM, and is not built on top of SQLite. Instead we’ve built a full database for mobile app developers, one that uses native objects that are dynamically mapped to a full, custom database engine (not just a key-value store). This allows us to provide a simple API while even enhancing performance. With Realm, you can model complex data, link objects in a graph, and compose advanced queries.

// Define you model class by extending RealmObject
public class Dog extends RealmObject {
    private String name;
    private int age;

    // ... Generated getters and setters ...
}

public class Person extends RealmObject {
    @PrimaryKey
    private long id;
    private String name;
    private RealmList<Dog> dogs; // Declare one-to-many relationships

    public Person(long id, String name) {
        this.id = id;
        this.name = name;
    }

    // ... Generated getters and setters ...
}

// Use them like regular java objects
Dog dog = new Dog();
dog.setName("Rex");
dog.setAge(1);

// Create a RealmConfiguration that saves the Realm file in the app's "files" directory.
RealmConfiguration realmConfig = new RealmConfiguration.Builder(context).build();
Realm.setDefaultConfiguration(realmConfig);

// Get a Realm instance for this thread
Realm realm = Realm.getDefaultInstance();

// Query Realm for all dogs younger than 2 years old
final RealmResults<Dog> puppies = realm.where(Dog.class).lessThan("age", 2).findAll();
puppies.size(); // => 0 because no dogs have been added to the Realm yet

// Persist your data in a transaction
realm.beginTransaction();
final Dog managedDog = realm.copyToRealm(dog); // Persist unmanaged objects
Person person = realm.createObject(Person.class); // Create managed objects directly
person.getDogs().add(managedDog);
realm.commitTransaction();

// Listeners will be notified when data changes
puppies.addChangeListener(new RealmChangeListener<RealmResults<Dog>>() {
    @Override
    public void onChange(RealmResults<Dog> results) {
        // Query results are updated in real time
        puppies.size(); // => 1
    }
});

// Asynchronously update objects on a background thread
realm.executeTransactionAsync(new Realm.Transaction() {
    @Override
    public void execute(Realm bgRealm) {
        Dog dog = bgRealm.where(Dog.class).equals("age", 1).findFirst();
        dog.setAge(3);
    }
}, new Realm.Transaction.OnSuccess() {
    @Override
    public void onSuccess() {
      // Original queries and Realm objects are automatically updated.
      puppies.size(); // => 0 because there are no more puppies younger than 2 years old
      managedDog.getAge();   // => 3 the dogs age is updated
    }
});
// Define your models like regular Objective‑C classes
@interface Dog : RLMObject
@property NSString *name;
@property NSData   *picture;
@property NSInteger age;
@end
@implementation Dog
@end
RLM_ARRAY_TYPE(Dog)
@interface Person : RLMObject
@property NSString             *name;
@property RLMArray<Dog *><Dog> *dogs;
@end
@implementation Person
@end

// Use them like regular Objective‑C objects
Dog *mydog = [[Dog alloc] init];
mydog.name = @"Rex";
mydog.age = 1;
mydog.picture = nil; // properties are nullable
NSLog(@"Name of dog: %@", mydog.name);

// Query Realm for all dogs less than 2 years old
RLMResults<Dog *> *puppies = [Dog objectsWhere:@"age < 2"];
puppies.count; // => 0 because no dogs have been added to the Realm yet

// Persist your data easily
RLMRealm *realm = [RLMRealm defaultRealm];
[realm transactionWithBlock:^{
  [realm addObject:mydog];
}];

// Queries are updated in real-time
puppies.count; // => 1

// Query and update the result in another thread
dispatch_async(dispatch_queue_create("background", 0), ^{
  Dog *theDog = [[Dog objectsWhere:@"age == 1"] firstObject];
  RLMRealm *realm = [RLMRealm defaultRealm];
  [realm beginWriteTransaction];
  theDog.age = 3;
  [realm commitWriteTransaction];
});
// Define your models like regular Swift classes
class Dog: Object {
  dynamic var name = ""
  dynamic var age = 0
}
class Person: Object {
  dynamic var name = ""
  dynamic var picture: NSData? = nil // optionals supported
  let dogs = List<Dog>()
}

// Use them like regular Swift objects
let myDog = Dog()
myDog.name = "Rex"
myDog.age = 1
print("name of dog: \(myDog.name)")

// Get the default Realm
let realm = try! Realm()

// Query Realm for all dogs less than 2 years old
let puppies = realm.objects(Dog).filter("age < 2")
puppies.count // => 0 because no dogs have been added to the Realm yet

// Persist your data easily
try! realm.write {
  realm.add(myDog)
}

// Queries are updated in real-time
puppies.count // => 1

// Query and update from any thread
dispatch_async(dispatch_queue_create("background", nil)) {
  let realm = try! Realm()
  let theDog = realm.objects(Dog).filter("age == 1").first
  try! realm.write {
    theDog!.age = 3
  }
}
// Define your models and their properties
class Car {}
Car.schema = {
  name: 'Car',
  properties: {
    make:  'string',
    model: 'string',
    miles: 'int',
  }
};
class Person {}
Person.schema = {
  name: 'Person',
  properties: {
    name:    {type: 'string'},
    cars:    {type: 'list', objectType: 'Car'},
    picture: {type: 'data', optional: true}, // optional property
  }
};

// Get the default Realm with support for our objects
let realm = new Realm({schema: [Car, Person]});

// Create Realm objects and write to local storage
realm.write(() => {
  let myCar = realm.create('Car', {
    make: 'Honda',
    model: 'Civic',
    miles: 1000,
  });
  myCar.miles += 20; // Update a property value
});

// Query Realm for all cars with a high mileage
let cars = realm.objects('Car').filtered('miles > 1000');

// Will return a Results object with our 1 car
cars.length // => 1

// Add another car
realm.write(() => {
  let myCar = realm.create('Car', {
    make: 'Ford',
    model: 'Focus',
    miles: 2000,
  });

// Query results are updated in real-time
cars.length // => 2
// Define your models like regular C# classes
public class Dog : RealmObject 
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Person Owner { get; set; }
}

public class Person : RealmObject 
{
    public string Name { get; set; }
    public RealmList<Dog> Dogs { get; } 
}

var realm = Realm.GetInstance();

// Use LINQ to query
var puppies = realm.All<Dog>().Where(d => d.Age < 2);

puppies.Count(); // => 0 because no dogs have been added yet

// Update and persist objects with a thread-safe transaction
realm.Write(() => 
{
    var mydog = realm.CreateObject<Dog>();
    mydog.Name = "Rex";
    mydog.Age = 1;
});

// Queries are updated in real-time
puppies.Count(); // => 1

// LINQ query syntax works as well
var oldDogs = from d in realm.All<Dog>() where d.Age > 8 select d;

// Query and update from any thread
new Thread(() =>
{
    var realm2 = Realm.GetInstance();

    var theDog = realm2.All<Dog>().Where(d => d.Age == 1).First();
    realm2.Write(() => theDog.Age = 3);
}).Start();

Why use Realm?

Easy

Realm’s primary focus has always been ease of use. Developers tell us they switch even large apps to Realm in hours, and save weeks of implementation, optimization & debugging time on an average project.

Fast

Realm’s ease of use doesn’t come at a performance cost. Because of its memory mapping, lazy loading, and custom storage engine, Realm is usually faster than raw SQLite, despite offering a rich object-based API. Although we always recommend that everyone test their own use-cases, developers usually see huge speedups when porting apps to Realm.

Cross-platform

Realm supports Java, Objective-C, React Native, Swift and Xamarin. You can share Realm files across platforms, use the same data models, and write similar business logic on all platforms. For debugging, .realm files can be opened with the Realm Browser.

Advanced

Realm objects are always up-to-date with the underlying data, making it trivial to follow reactive patterns or a unidirectional data flow. You can link Realm objects in graphs, use an advanced query language, rely on built-in AES256 encryption, and even easily integrate Realm data into your UI through optional add-ons.

Trusted

Have a large app or a large userbase? Realm’s the database for you. We’re already trusted in production by banks and healthcare providers, and proven across complex enterprise apps and #1 hits on both the Apple App Store and Google Play Store.

Community-driven

Realm is built in the open on GitHub. Features are prioritized based on user requests and we welcome contributions. We have over 12,000 stars on GitHub, and beyond the core projects, our community has already been building hundreds of apps, plugins & components.

Supported

Realm prioritizes support and bug fixes above all else. You can get answers about your database directly from the people that build & maintain it, via Stack Overflow, GitHub, or Twitter.

Who is using Realm?

Realm is built into apps used by over a billion people.

Twitter

Even #1 app store successes trust Realm. Twitter’s innovative video app Vine and its 200M monthly active users started using Realm in 2016.

Starbucks

The Fortune 500 retailer relies on Realm in their flagship app, allowing you to order ahead from your phone and reap rewards at the counter.

Alibaba

The NYSE-listed Chinese juggernaut uses Realm in its flagship marketplace business, allowing both suppliers & buyers to sell & buy goods on a platform that generated almost $3 billion USD in revenues last year.

Budweiser

The Global 500 giant built their innovative TapWiser app on Realm. It allows bars & stores to quickly order new kegs & bottles directly from a mobile app, since most outlets don’t have a computer on site.

SAP

If you’re a Concur user, chances are you’ve used Realm already: expense reports & travel plans are managed in this app that serves over 20,000 clients and 30 million end-users.

Rite Aid

The Fortune 500 retail giant trusts Realm to securely store data for customers, via the EnvisionRx program.

Other notable users include: Amazon, eBay, Google, GoPro, Walmart, Adidas, Cisco, NBCUniversal, Nike, the NFL and many, many more.

What’s Next

We’d love your feedback on what we can improve, and are here to help you along the way on Stack Overflow and Twitter!

Get Started with Realm Java - or check out the source on GitHub
Get Started with Realm Objective-C - or check out the source on GitHub
Get Started with Realm Swift - or check out the source on GitHub
Get Started with Realm React Native - or check out the source on GitHub
Get Started with Realm Xamarin - or check out the source on GitHub

We can’t wait to see what you’ll build with Realm!

Read more

Realm Objective‑C & Swift 0.103 – Dropping Support For Older Versions, Plus Improvements

by /

We’re releasing version 0.103 of Realm Objective‑C and Realm Swift today, with a few minor breaking changes and improvements. Read on for more information.

Breaking Changes

  • All functionality deprecated in previous releases has been removed entirely.
  • Support for Xcode prior to 7.3 & Swift prior to 2.2 has been completely removed.
  • RLMResults/Results now become empty when a RLMArray/List or object they depend on is deleted, rather than throwing an exception when accessed.
  • Migrations are no longer run when deleteRealmIfMigrationNeeded is set, recreating the file instead.

Enhancements

  • Added invalidated properties to RLMResults/Results, RLMLinkingObjects/LinkingObjects, RealmCollectionType and AnyRealmCollection. These properties report whether the Realm the object is associated with has been invalidated.
  • Some NSErrors created by Realm now have more descriptive user info payloads.

Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, or Twitter.

Read more

Introducing Realm Xamarin

by /

Today we’re launching a new Realm mobile database, this time built specifically for Xamarin. It offers easy object persistence and full query capabilities, with a performance profile that’s faster than existing options.

Like the other editions of Realm, it is designed from the ground up to enable reactive app development, with live objects, change events, and support for unidirectional data flows.

public class Dog : RealmObject
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Person Owner { get; set; }
}

var realm = Realm.GetInstance();

// Query with LINQ
var puppies = realm.All<Dog>().Where(d => d.Age < 2);
puppies.Count(); // => 0 because no dogs have been added yet

// Writes in a transaction
realm.Write(() =>
{
    var mydog = realm.CreateObject<Dog>();
    mydog.Name = "Rex";
    mydog.Age = 1;
});

// Queries are updated in real-time
puppies.Count(); // => 1

Realm is a database built from the ground up for the unique challenges of mobile app development, that runs directly inside phones, tablets or wearables. We launched for Java, Objective‑C, & Swift in 2014, and for React Native earlier in 2016. We are already used on hundreds of millions of devices today by appmakers including Twitter, Starbucks, Cisco, Walmart, Google, Amazon, & eBay, plus many many others.

Today, we’re launching for Xamarin, Microsoft’s mobile framework that lets developers write C# code that becomes native iOS & Android apps.

Realm Xamarin brings the modern design & simplicity you expect from Realm, and will allow you to target both iOS and Android with the same codebase. We currently support Xamarin.iOS and Xamarin.Android, and look forward to supporting Xamarin.Mac in the future, as well as UWP and Unity.

What is Realm?

Realm is not an ORM, and is not built on top of SQLite. Instead we’ve built a full database for mobile app developers, one that uses native C# objects that are dynamically mapped to a full, custom database engine (not just a key-value store). This allows us to provide a simple API while even enhancing performance. With Realm, you can model complex data, link objects in a graph, and compose advanced queries.

public class Dog : RealmObject
{
    public string Name { get; set; }
    public int Age { get; set; }
    public Person Owner { get; set; }
}

var realm = Realm.GetInstance();

realm.Write(() =>
{
    var mydog = realm.CreateObject<Dog>();
    mydog.Name = "Rex";
    mydog.Age = 9;
});
// Basic query with LINQ fluent or extension syntax
var oldDogs = realm.All<Dog>().Where(d => d.Age > 8);
// or
var oldDogs = from d in realm.All<Dog>() where d.Age > 8 select d;

// Queries can be chained
var dogsNamedRex = oldDogs.Where(p => p.Name == "Rex");
dogsNamedRex.Count(); // => 1

// Writes happens in a thread-safe transaction
realm.Write(() =>
{
    var mydog = realm.CreateObject<Dog>();
    mydog.Name = "Rex Maximus";
    mydog.Age = 10;
});

// Query results are updated in real-time
dogsNamedRex.Count(); // => 2
public class Person : RealmObject
{
    public string Name { get; set; }
    public RealmList<Dog> Dogs { get; }
}

var realm = Realm.GetInstance();

realm.Write(() =>
{
    var jim = realm.CreateObject<Person>();
    var mydog = realm.CreateObject<Dog>();
    mydog.Name = "Fido";
    mydog.Owner = jim;
});

You can see more examples of how to use these APIs in our sample apps.

Why use Realm?

Easy

Realm’s primary focus has always been ease of use, and as you can see from the samples above, Realm Xamarin has the same overall goal. After that, we’ve been working on some of the same advantages our other products are known for…

Fast

Realm’s ease of use doesn’t come at a performance cost. Because of its memory mapping, lazy loading, and custom storage engine, Realm is usually faster than SQLite despite offering a rich object-based API. Although we always recommend everyone test their own use-cases, we usually see huge speedups when porting code to Realm. See benchmark results below.

Cross-platform

This should go without saying, but Realm Xamarin obviously allows you to write your app once in C# and target both iOS & Android. Please note the Realm file format is also completely cross-platform, allowing data to be shared across iOS & Android easily. For debugging, .realm files can be opened via the Realm Browser.

Advanced

Realm objects are always up-to-date with the underlying data, making it trivial to follow reactive patterns or a unidirectional data flow. You can link Realm objects in graphs, query any property combination via LINQ, and even easily integrate Realm data in Xamarin.Forms.

Trusted

Realm Xamarin is built on top of the same core as Realm Java, Objective‑C, React Native, and Swift, which is trusted by hundreds of millions of people around the world, and used by e‑commerce applications, banks, healthcare providers, and even governments.

Community-driven

Realm Xamarin is built in the open on GitHub. Features are prioritized based on user requests and we welcome contributions.

Supported

Realm prioritizes support & bugfixes above all else. You can get answers about your database directly from the people that build & maintain it, via Stack Overflow, GitHub or Twitter.

Tests conducted on May 9, 2016, using the latest versions available of Realm, sqlite-net and Couchbase Lite. Measurements taken on an iPhone 6S Plus with 128GB memory running iOS 9.3.1. Source. We recommend you perform your own benchmarks that represents your use cases as any synthetic benchmarks can only provide rough indicators.

What’s Next

We’d love your feedback on what we can improve, and we’re particularly interested in bug reports or feature requests on our GitHub repository. Expect the API to improve significantly over the next few weeks, especially as we polish advanced features like migrations and queries.

If you are a fan of .NET and want UWP support or Unity support, please speak up — we’d love to add that in the future.

We can’t wait to see what you will build with Realm!

Read more

Realm Objective‑C & Swift 0.102 – Rename Properties in Migrations or Skip Them Altogether!

by /

Support for Xcode 6.x and Swift older than 2.2 is deprecated and will be removed entirely in our next release.

We’re releasing version 0.102 of Realm Objective‑C and Realm Swift today, adding two small migration-related features: the ability to rename properties in migrations, or to configure your Realm file to be deleted whenever a migration would have previously been required. Read on for more information.

Renaming Properties in Migrations

It’s now possible to rename properties as part of migrations. Renaming a property is more efficient than copying values and preserves relationships rather than duplicating them.

To rename a property during a migration, make sure that your new models have a property by the new name and don’t have a property by the old name.

If the new property has different nullability or indexing settings, those will be applied during the rename operation.

Here’s how you could rename Person’s yearsSinceBirth property to age:

// Inside your application(application:didFinishLaunchingWithOptions:)

Realm.Configuration.defaultConfiguration = Realm.Configuration(
  schemaVersion: 1,
  migrationBlock: { migration, oldSchemaVersion in
    // We haven’t migrated anything yet, so oldSchemaVersion == 0
    if (oldSchemaVersion < 1) {
      // The renaming operation should be done outside of calls to `enumerate(_:)`.
      migration.renamePropertyForClass(Person.className(), oldName: "yearsSinceBirth", newName: "age")
    }
  })
// Inside your [AppDelegate didFinishLaunchingWithOptions:]

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.schemaVersion = 1;
config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
  // We haven’t migrated anything yet, so oldSchemaVersion == 0
  if (oldSchemaVersion < 1) {
    // The renaming operation should be done outside of calls to `enumerateObjects:`.
    [migration renamePropertyForClass:Person.className oldName:@"yearsSinceBirth" newName:@"age"];
  }
};
[RLMRealmConfiguration setDefaultConfiguration:config];

Deleting Realms When a Migration is Required

It’s quite common to modify a Realm schema numerous times during development, but writing fully-fledged migrations at that stage is time consuming and distracting when you’re just trying to “get the job done”…

So in this version, we’re adding a deleteRealmIfMigrationNeeded boolean property to RLMRealmConfiguration/Realm.Configuration. This flag defaults to false so you won’t start suddenly losing data if you upgrade to this version of Realm, unless you explicitly opt in to this feature.

Bug Fixes

  • Fix crash when migrating to the new date format introduced in 0.101.0.
  • When using BETWEEN on an RLMArray/List property, only match when a single related object is within the request range, rather than allowing different objects in the list to satisfy the upper and lower bounds.
  • Fix crash when querying inverse relationships when objects are deleted.
  • Fix a race condition when a Realm is opened on one thread while it is in the middle of being closed on another thread.

Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, or Twitter.

Read more

Realm Objective‑C & Swift 0.101 – Better Dates, Memory Overhead & Crash Handling!

by /

Realm files read or written by this version cannot be opened with previous versions of Realm. Existing files will automatically be upgraded when they are opened. Please be careful about shipping updates to your existing apps!

We’re releasing version 0.101 of Realm Objective‑C and Realm Swift today, addressing some long-standing limitations regarding date precision, memory mapping overhead, multi-process crash handling, and more.

Nanosecond Precision Dates & New File Format

Until now, NSDate properties have discarded their sub-second values, leading to some surprising behavior in apps requiring sub-second precision in dates. This release includes a new date format that’s even more precise than NSDate, so date properties maintain their full precision.

This new property type format required an update to the overall Realm file format, meaning that Realm files read or written by this version cannot be opened with previous versions of Realm. Existing files will automatically be upgraded when they are opened, except for read-only files bundled with your app, which you can upgrade by opening them in the Realm Browser. Please be careful about shipping updates to your existing apps! 🚨

Reduced Multi-Threaded Memory Mapping Overhead

Previous versions of Realm needed to mmap the entire file for each thread in order to preserve transaction isolation. This isolation is why Realm doesn’t have a concept of “faults” like some other persistent data frameworks.

In this version, opening a single Realm file on multiple threads now shares a single memory mapping of the file for all threads, significantly reducing the virtual memory required to work with large files.

Improved Multi-Process Crash Handling

Crashing while in the middle of a write transaction no longer blocks other processes from performing write transactions on the same file.

You’ll recall from our previous posts on Fast Inter-Process Communication and 0.91 release announcement that Darwin doesn’t support robust inter-process mutexes 😰. So we reimplemented some of Realm’s most fundamental locking mechanisms to use fcntl(3) to emulate robust inter-process mutexes on platforms that do not support the full POSIX API for them.

This change prevents a situation where a crash in one process holding the lock, while leaving the database locked in all other processes.

Enhancements

We greatly improved the performance of the background worker for fine-grained notifications for complex object graphs, and the performance of refreshing a Realm (including via autorefresh) when there are live Results/RLMResults objects for that Realm.

Bugfixes

We fixed a crash when an RLMArray or List object is destroyed from the wrong thread.


Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, or Twitter.

Read more

Realm Java 0.90 — Better Date and API Cleanup!

by /

We just released a new version of Realm Java to this website and to Bintray. This release adds full support for the Date datatype as well as an API cleanup.

Better Date support

Realm Java has from the beginning supported the standard java.util.Date, with one limitation. We truncated all timestamps to the nearest second.

The reason was that we wanted all of our products to be compatible, even though their date formats differ widely. Starting with Realm Java 0.90 and Realm Objective-C & Swift 0.101, we have fixed these issues and Realm Java now supports the full millisecond precision that is normally offered by the Date class.

This change will require an upgrade of the format of the Realm file, but it will happen automatically when opening a Realm file using 0.90+. Enjoy all those milliseconds :D

Android Adapters

We have decided to split off all Android-specific components into their own repository. This will make it easier to release enhancements and hotfixes for those as well as keeping the general size of the main library down.

This means that from 0.90, the class RealmBaseAdapter is no longer part of the main Realm library, and you will have to add the following dependency to get it:

dependencies {
	compile 'io.realm:android-adapters:1.0.1'
}

Going forward we are planning to add more Android framework support like RecyclerView and Cursors, but if you have any other ideas or feedback, please create an issue in the new Realm Android Adapters repository.

API Cleanup

Realm Java has been in beta for roughly 1.5 years, and during that time we have gotten a lot of feedback and input on how the API should look. For that reason we are now taking the opportunity to do a general cleanup. We are removing things that are not really used and improving others.

The most important items are below:

  • All Realm classes are now final.

  • RealmChangeListeners now send the changed object as a parameter to onChange().

realm.addChangeListener(new RealmChangeListener<Realm>() {
	@Override
	public void onChange(Realm realm) {
		// A reference to Realm. Note that all Realm instances and objects
		// are live objects, so this is just convenience and it cannot
		// be compared to previous references as they will all be the same.
    }
});

Person p = realm.where(Person.class).findFirst();
p.addChangeListener(new RealmChangeListener<Person>() {
	@Override
	public void onChange(Person person) {
		person.getName(); // The updated person.
	}
});
  • All query methods on Realm and DynamicRealm have been deprecated. All query methods should be done through Realm.where(), DynamicRealm.where() or RealmCollection.where().

  • RealmConfiguration.Builder.setModules() has been renamed to RealmConfiguration.Builder.modules().

  • Realm.refresh() has been deprecated in favor of Realm.waitForChange(). See this gist for an example of how to use it. This change was motivated by the fact that one-time tasks should either use the asynchronous API’s or open a Realm instance and close it again when done with it. waitForChange() is more suited for use-cases where you can’t use the async API (because it requires a Looper thread).

calling waitForChange() will block the current Thread until a commit happens in the background or you call stopWaitForChange(), which will stop the wait of the Thread that called waitForChange().

See the full changelog for all the details.


Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, and Twitter.

Read more

Realm Objective‑C & Swift 0.99 – Fine-Grained Notifications!

by /

We’ve released version 0.99 of Realm Objective‑C and Realm Swift!

This release adds the number one requested feature since our launch nearly two years ago: fine-grained change notifications.

We’ve also walked through the entire Objective-C and Swift APIs to clean up some unnecessary duplication and omissions. These make up several small breaking changes, but we hope you’ll find it makes the API more cohesive.

Fine-Grained Notifications

This release extends the collection notifications functionality we introduced in Realm 0.98 by adding a new changes parameter to the notification block.

This RLMCollectionChange/RealmCollectionChange parameter describes what changes have occurred at a fine-grained level, including the indices of objects that have been inserted, deleted, or modified since the last notification. This makes it possible to discretely control the animations and visual updates made to the content inside your UI, instead of arbitrarily reloading everything each time a notification occurs.

The arrays of indices follow UITableView’s batching conventions, and can be passed as-is to a table view’s batch update methods after converting to index paths in the appropriate section. Here it is in action:

Fine-Grained Notifications

For example, for a simple one-section table view, you can do the following:

notificationToken = results.addNotificationBlock { (changes: RealmCollectionChange) in
  switch changes {
  case .Initial:
    // Results are now populated and can be accessed without blocking the UI
    self.tableView.reloadData()
    break
  case .Update(_, let deletions, let insertions, let modifications):
    // Query results have changed, so apply them to the UITableView
    self.tableView.beginUpdates()
    self.tableView.insertRowsAtIndexPaths(insertions.map { NSIndexPath(forRow: $0, inSection: 0) },
        withRowAnimation: .Automatic)
    self.tableView.deleteRowsAtIndexPaths(deletions.map { NSIndexPath(forRow: $0, inSection: 0) },
        withRowAnimation: .Automatic)
    self.tableView.reloadRowsAtIndexPaths(modifications.map { NSIndexPath(forRow: $0, inSection: 0) },
        withRowAnimation: .Automatic)
    self.tableView.endUpdates()
    break
  case .Error(let error):
    // An error occurred while opening the Realm file on the background worker thread
    fatalError("\(error)")
    break
  }
}
__weak typeof(self) weakSelf = self;
self.notificationToken = [[Person objectsWhere:@"age > 5"] addNotificationBlock:^(RLMResults<Person *> *results, RLMCollectionChange *change, NSError *error) {
  if (error) {
    NSLog(@"Failed to open Realm on background worker: %@", error);
    return;
  }

  UITableView *tableView = weakSelf.tableView;
  // Initial run of the query will pass nil for the change information
  if (!changes) {
    [tableView reloadData];
    return;
  }

  // Query results have changed, so apply them to the UITableView
  [tableView beginUpdates];
  [tableView deleteRowsAtIndexPaths:[changes deletionsInSection:0]
                   withRowAnimation:UITableViewRowAnimationAutomatic];
  [tableView insertRowsAtIndexPaths:[changes insertionsInSection:0]
                   withRowAnimation:UITableViewRowAnimationAutomatic];
  [tableView reloadRowsAtIndexPaths:[changes modificationsInSection:0]
                   withRowAnimation:UITableViewRowAnimationAutomatic];
  [tableView endUpdates];
}];

See our docs on Collection Notifications for more information.

API Revisions

Over time, as we add new features to Realm, we need to take a step back, reviewing the entire API structure to adjust interfaces in a holistic way.

The changes can be summarized in these categories:

  1. RLMNotificationToken/NotificationTokens now only have one method to unsubscribe from notifications (-stop).
  2. Methods that had variants with and without an encryptionKey parameter have been combined.
  3. Properties that were present on both RLMRealm/Realm and RLMRealmConfiguration/Realm.Configuration have been deprecated in favor of the ones on the configuration.
  4. Methods and properties dealing with string-based Realm file paths now use NSURLs to better align with recent changes in Apple’s Foundation APIs.
  5. One Swift API we had missed in our Swift 2 transition has now shed its NSErrorPointer parameter and uses Swift’s native error handling mechanism (throws).

Here’s the complete list of Objective-C APIs that have been deprecated in favor of newer or preferred versions:

Deprecated API New API
-[RLMRealm removeNotification:] -[RLMNotificationToken stop]
RLMRealmConfiguration.path RLMRealmConfiguration.fileURL
RLMRealm.path RLMRealmConfiguration.fileURL
RLMRealm.readOnly RLMRealmConfiguration.readOnly
+[RLMRealm realmWithPath:] +[RLMRealm realmWithURL:]
+[RLMRealm writeCopyToPath:error:] +[RLMRealm writeCopyToURL:encryptionKey:error:]
+[RLMRealm writeCopyToPath:encryptionKey:error:] +[RLMRealm writeCopyToURL:encryptionKey:error:]
+[RLMRealm schemaVersionAtPath:error:] +[RLMRealm schemaVersionAtURL:encryptionKey:error:]
+[RLMRealm schemaVersionAtPath:encryptionKey:error:] +[RLMRealm schemaVersionAtURL:encryptionKey:error:]

Here’s the complete list of Swift APIs that have been deprecated in favor of newer or preferred versions:

Deprecated API New API
Realm.removeNotification(_:) NotificationToken.stop()
Realm.Configuration.path Realm.Configuration.fileURL
Realm.path Realm.Configuration.fileURL
Realm.readOnly Realm.Configuration.readOnly
Realm.writeCopyToPath(_:encryptionKey:) Realm.writeCopyToURL(_:encryptionKey:)
schemaVersionAtPath(_:encryptionKey:error:) schemaVersionAtURL(_:encryptionKey:)

Other Breaking Changes

  • Deprecate properties of type id/AnyObject. This type was rarely used, rarely useful, and unsupported in every other Realm product.
  • The block for -[RLMArray addNotificationBlock:] and -[RLMResults addNotificationBlock:] now takes another parameter, as explained above in the Fine-Grained Notifications section.

Bug Fixes

  • Fix a use-after-free when an associated object’s dealloc method is used to remove observers from an RLMObject.
  • Fix a small memory leak each time a Realm file is opened.
  • Return a recoverable RLMErrorAddressSpaceExhausted error rather than crash when there is insufficient available address space on Realm initialization or write commit.

Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, or Twitter.

Read more

Realm Objective‑C & Swift 0.100 – Queryable, Live Inverse Relationships!

by /

We’re releasing version 0.100 of Realm Objective‑C and Realm Swift today, adding another highly requested feature: making inverse relationships queryable and as live as their forward counterparts.

Queryable, Live Inverse Relationships

Let’s recap how relationships work in Realm. Relationships are unidirectional, and are declared using RLMArray/List or object properties. These properties can be used in queries, and are updated automatically to reflect changes to the property value made elsewhere in your app. Realm has historically provided a method to retrieve a snapshot of all objects that link to a specific object instance at the current point in time. Realm 0.100 improves on this by allowing you to declare linking objects properties that represent the inverse side of a relationship. These properties are live, auto-updating, queryable collections that provide the full capabilities of Realm’s other collection types. Unlike other Realm properties, linking objects properties cannot be modified directly. They’re modified automatically as a result of adding or removing the object from the RLMArray/List or object property that makes up the forward side of the relationship.

One-to-Many Relationships

@interface Dog : RLMObject
@property NSString *name;
@property NSInteger age;
@property Person *owner;
@end

@implementation Dog
@end

@interface Person : RLMObject
@property NSString *name;
@property NSInteger age;
@property (readonly) RLMLinkingObjects<Dog *> *dogs;
@end

@implementation Person
+ (NSDictionary *)linkingObjectsProperties {
    return @{
        @"dogs": [RLMPropertyDescriptor descriptorWithClass:Dog.class propertyName:@"owner"],
    };
}
@end
class Dog: Object {
    dynamic var name = ""
    dynamic var age = 0
    dynamic var owner: Person?
}

class Person: Object {
    dynamic var name = ""
    dynamic var age = 0
    let dogs = LinkingObjects(fromType: Dog.self, property: "owner")
}

Many-to-Many Relationships

@interface Person : RLMObject
@property NSString *name;
@property NSInteger age;
@property RLMArray<Person *><Person> *children;
@property (readonly) RLMLinkingObjects<Person *> *parents;
@end

@implementation Person
+ (NSDictionary *)linkingObjectsProperties {
    return @{
        @"parents": [RLMPropertyDescriptor descriptorWithClass:Person.class propertyName:@"children"],
    };
}
@end
class Person: Object {
    dynamic var name = ""
    dynamic var age = 0
    let children = List<Person>()
    let parents = LinkingObjects(fromType: Person.self, property: "children")
}

Note that due to their computed nature, RLMLinkingObjects/LinkingObjects properties must be declared as readonly/let.

The new linking objects properties offer several significant advantages over the previous approach:

1) Linking Objects Are Live, Auto-updating Collections

Just like the other collection types in Realm, RLMLinkingObjects/LinkingObjects are live and auto-updating. When new relationships are formed with or removed from the object, the linking objects will update to reflect the currently linking objects. This means you are no longer working with a static point-in-time snapshot of the relationship that you need to keep updated yourself.

2) Linking Objects Can Be Used In Queries

To perform queries on linking objects with the old API you had to manually filter the objects in your own code, missing out on the performance & liveness provided by Realm’s native query system.

Linking objects properties are completely integrated with Realm’s query system, making it efficient and easy to filter over inverse relationships.

// People that have a child that have a parent named Diane.
[PersonObject objectsWhere:@"ANY children.parents.name == 'Diane'"];

// People whose parents have an average age of > 65.
[PersonObject objectsWhere:@"[email protected] > 65"];
// People that have a child that have a parent named Diane.
realm.objects(Person).filter("ANY children.parents.name == 'Diane'")

// People whose parents have an average age of > 65.
realm.objects(Person).filter("[email protected] > 65")

3) Linking Objects Are Realm Collections

While the previous linking objects API returned a standard library array type, the new RLMLinkingObjects/LinkingObjects types conform to Realm’s collection type protocol. This makes them familiar to work with and provides all the functionality you’re used to from Realm’s RLMResults/Results types.

// Which of my parents are over the age of 56?
[self.parents objectsWhere:@"age > 56"];

// Calculate the age of my parents.
[self.parents averageOfProperty:"age"];
// Which of my parents are over the age of 56?
self.parents.filter("age > 56")

// Calculate the age of my parents.
self.parents.average("age")

Deprecations

The -[RLMObject linkingObjectsOfClass:forProperty:] and Object.linkingObjects(_:forProperty:) methods are deprecated and will be removed in a future release.

Other Changes

  • Queries that compare objects for equality now support multi-level key paths.
  • Queries that compare RLMArray / List properties using != now give the correct results.
  • Fix an assertion failure when a second write transaction is committed after a write transaction deleted the object containing an RLMArray/List which had an active notification block.

Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, or Twitter.

Read more

Realm Java 0.89 — Model and Collection interfaces!

by /

We just released a new version of Realm Java to this website and to Bintray. This release is packed with fixes and new features.

RealmModel interface

A longstanding requirement for Realm has been that all Realm model classes must extend the base class RealmObject.

Starting with 0.89, this is no longer a strict requirement and you can now choose to implement the new RealmModel interface instead.

@RealmClass
public class implements RealmModel {
	
}

You will need to manually add the @RealmClass annotation since inheriting annotations from interfaces is not yet supported by Android.

The helper methods on RealmObject are available as static methods, so if you use RealmModel you can use these methods.

Person person = getPerson();

// Extending RealmObject
person.isValid();
person.addChangeListener(listener);

// Implementing RealmModel
RealmObject.isValid(person);
RealmObject.addChangeListener(person, listener);

Extending RealmObject is still the recommended approach, but you now have the option of using the method which suits your architecture and codebase guidelines better.

Note that Realm Java still does not support extending anything other than RealmObject. That feature is still being tracked here.

RealmCollection API

The Realm Java API currently consists of two collections: RealmResults and RealmList, which both implement the standard List interface.

Both of these classes have been extended with additional Realm capabilities, but unfortunately their behavior had diverged slightly, which caused problems with RealmBaseAdapter.

In order to provide a more consistent experience, we are now introducing two new interfaces: RealmCollection and OrderedRealmCollection.

This provides a solid foundation for adding future collections as well as unifying the behavior and naming of methods across the API.

It has a few implications:

The behavior of methods like remove and clear now only operate on the collection and not the underlying Realm data. This especially impacts RealmResults where these methods will now throw UnsupportedOperationException.

  • RealmBaseAdapter now works out of the box with both RealmList and RealmResults.

  • Methods for deleting objects from both the collection and Realm are now called deleteFromRealm() or deleteAllFromRealm().

  • Realm.clear(Class) and Realm.clear() have been renamed to Realm.delete(Class) and Realm.deleteAll().

  • RealmObject.removeFromRealm() has been renamed to RealmObject.deleteFromRealm().

Stable iterators

One of the design paradigms of Realm is the concept of auto-updating results. Normally that is a great feature to have, except in one case: Changing objects in a way that would remove them from the RealmResult.

Take the following example:

RealmResults<Person> results = realm.where(Person.class).equalTo("inviteToGoogleIO", false).findAll();

// Try to invite all the people
realm.beginTransaction();
for (Person p : results) {
	p.inviteToGoogleIO(true);
}
realm.commitTransaction();

With a normal collection, you would expect to have all persons invited to Google I/O, but due to RealmResults being live-updated, it would actually only send invites to every other person. The reason is that due to the RealmResults live-updating, it would adjust the size of the collection the moment you set the first boolean field to true. This would in turn cause the iterator’s internal index to point to the next item (which hasn’t been updated), so when you call Iterator.next() or similar, it would skip over an item.

The solution so far has been to iterate backwards as that takes into account the changing size():

for (int i = results.size() - 1; i >=0; i--) {
	results.get(i).inviteToGoogleIO(true);
}

This is however very counter-intuitive. With 0.89, the auto-updating feature of RealmResults have changed slightly so instead of RealmResults being live all the time, they are now only updated on Looper events.

This means that iterators will now work as expected but also introduces a slight chance that you might accidentally access a deleted item.

RealmResults<Person> results = realm.where(Person.class).findAll();
for (Person p : results) {
	p.deleteFromRealm(); // Indirectly delete all items one-by-one.
}

// RealmResults are not updated until next Looper event
// So the RealmResult might now contain deleted objects
Person p = results.get(0); 
p.isValid() == false;

// Deleting the item directly on the RealmResults will remove them
// from the RealmResults as well
results.deleteFromRealm(0);

// and new Queries will also exclude deleted objects
results = realm.where(Person.class).findAll(); // Deleted users are removed

Read more here.

This change also impacts all RealmChangeListeners that were previously triggered after each call to Realm.commmitTransaction() on the same thread. They are now deferred to the next Looper event just like changes from other threads. This should have no effect on normal app behavior, but could potentially cause issues in unit tests that assumed that callbacks where immediately notified.

Breaking changes 🚨

PrimaryKey fields are no longer automatically marked as @Required. They can now be null if the type of the field can usually be null.

This change will throw a RealmMigrationNeededException. Either manually add @Required to the primary field to maintain the same behavior as 0.88.3 and below, or change the nullability in a migration step.

RealmObjectSchema personSchema = schema.get("Person");
personSchema.setNullable("myPrimaryKey", true);

Other improvements

See the full changelog for all the details.


Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, and Twitter.

Read more

React Native Radio Ep. 24: Realm React Native

by Tim Anglade /

On the latest episode of Devchat.tv’s React Native Radio, hosts Peter Piekarczyk and Lee Johnson sat down with Scott Kyle and Tim Anglade to talk about the recently released Realm React Native. They discuss everything from the design paradigms behind the database to the company’s business model, and get in-depth about encryption, object types, async, and more. Have you been wondering why Realm decided to directly support React Native rather than asking devs to bridge to iOS or Android? Tim and Scott reveal the thinking and product design going on behind the scenes, as well as what goes on in our underlying storage engine to make Realm so fast and easy to use. Be sure to check out the episode on Devchat.tv and subscribe on iTunes.


Play the episode below


Play on Devchat.tv

Introduction

Peter Piekarczyk: Hello and welcome to episode 24 of React Native Radio. I’m your host, Peter Piekarczyk, and we also have Lee Johnson, Scott Kyle, and Tim Anglade.

So, Scott and Tim, would you guys like to start by introducing yourselves and letting us know what you do?

Scott Kyle: I’m Scott, and I have been working on the Realm React Native binding for maybe the past 6 months or so. Before that, I co-founded a startup and we did software for WiFi routers, so a whole different thing. I was with Apple prior to that, so I’ve been bouncing around, doing lots of different stuff and enjoying every minute of it.

Tim Anglade: I’m Tim, I’m overseeing product at Realm and I’ve been with them for about 2 1/2 years, through some dark ages when we were called something else, doing something else as a startup prior to being called Realm, launching for Objective-C, Swift, Java, Android, and most recently React Native. Before that, I did a bunch of different things around NoSQL distributive systems. I came from that background and started on web originally. I’m coming back to JavaScript after a long hiatus. So that’s my back story.

Lee Johnson: All right so you piqued my interest. I didn’t realize you guys were around that long, with the dark ages comment. I’d love to hear the story of how that all transpired.

Tim Anglade: We used to be called TightDB, which was a bad name on a number of levels. We were doing something very similar. The technology hasn’t changed all too much but we were doing more of an embedded database, like a pound for pound type of replacement for SQLite. As I said, the technology hasn’t changed all that much but we’re much more focused on disk space and raw speed and a bunch of advanced features, something you couldn’t quite do with SQLite if you were into embedded systems and their devices or low level programming.

The company was really founded by a bunch of C++ dudes and was like a developers’ database type of ideal to it. We decided around early 2014 to focus more specifically on mobile, which was the founders’ first dream anyway. They both came out of Nokia and they both had worked for a long time on old mobile and new mobile. They started building a database for mobile way back when they founded the company in the late 2000s, early 2010s. A lot of the investors told them that nobody needed a mobile database so they had gone into different direction.

We took it back to the start, really focus it on what mobile was today, in the iPhone and Android world, and really focused on the Realm you see today, which is this really easy to use mobile database that has a first party integration into your language of choice, so Objective-C, Swift, Java, and specifically now JavaScript and React Native. That is the detour that we took towards building what it is today and how you always end up doing what you thought of in the first place anyway.

Realm’s Features & Use Cases

Lee Johnson: So it’d be nice if you could give us an overview of Realm’s features and use cases.

What’s cool about it is React Native is new and Objective-C and Xcode projects obviously have Core Data and Android has their database. So a database for React Native is a unique thing. It’s specific to that environment and we don’t have a lot of options for that now. You guys are pretty new to the scene for an actual database in React Native, and that makes it easier to use than writing bridges to Core Data or something crazy like that.

Tim Anglade: Realm is the umbrella term – it’s the name of the company, it’s also the name of the product that we have for each platform. In its raw form Realm is this easy to use, really fast replacement for your data model layer, including persistence, relationships, querying, and everywhere you would use a model in your app, you use a Realm object.

The basic principle of it is to build a modern data model if we were trying to rebuild SQLite today. It’s easy to use, which is what we think most developers need at this point – they really need something that doesn’t take a lot of time. When you’re developing your application and trying to maintain it and find a bug, we’re trying to do something really, really fast because you don’t want to be slowed down by an ORM or database queries and having to optimize that.

We try to maintain a really advanced feature set, like encryptions built in, graph queries built in, easy migrations, and a nice reactive notification system, and we try to do so in the open so we develop everything we can on GitHub. We support developers directly on GitHub, Stack Overflow, Twitter, or by email. We’ve tried to build a large, trusted community around it, and we are now running on half a billion devices around the world, which is pretty nice. We’re used in some really large apps on the Objective-C, Swift, Java side. We just launched JavaScript but we’ve seen some good adoption. On the older products, we’re already used by Google, Amazon, Starbucks, eBay, Budweiser, BBC, McDonald’s, Wal Mart, a bunch of global companies, which you can find on our website. That’s Realm in general.

Realm for React Native is our reinvention of the product specifically for the platform. We don’t really do bindings in the strict sense of “Let’s just take this thing we built and expose the API directly into whatever language we have to deal with.” We really try to start every new product thinking “What is that product trying to do? What is the platform trying to do? What is the framework behind it trying to do? What are its design principles and how can we fit in there in the best possible way?” We spent an enormous amount of time launching every product specifically for that community. You should look at our Swift product, it’s drastically different from our Android product in terms of the API it exposes, the query language it adds, a lot of things like that. If you look at our Swift products versus our Objective-C products, they’re also very different even though they both target the iOS platform.

Our React Native and JavaScript product is no different. We’re trying to build something that is very first party, that feels native to JavaScript, that feels like you’re interacting with a standard component of the React Native ecosystem. The jury’s still out as to whether or not we succeeded in that, so we’re always looking for feedback on everything we’re doing wrong and making improvements. It’s the application of our basic design principles around data models, around concurrency, around consistency and having different types of data you’re offloading on your app, but also applying all these things to what’s idiomatic to JavaScript and React Native. We came out with Realm for React Native very recently, and actually launched at React Conf this year. We’re lucky to have some users like TaskRabbit already using us in production for two months actually, since before we even launched publicly, and adoption’s been pretty good so far. We’re still in the early days, but we’re in the hundreds of users already after a few weeks, and we’re growing about fifteen to twenty percent every week, so we’re seeing nice exponential growth and nice pick-up in the React Native community. I’m pretty excited about that.

Peter Piekarczyk: Do you have a particular client or customer or app type that you think would most benefit from Realm? Or is it anything?

Tim Anglade: We really tried to design this for any app and for if you need a data model that would basically feel like you should be able to use Realm. Specifically on a relatively new ecosystem like the React Native ecosystem that doesn’t have a very strong integration with SQLite, like Android does, or doesn’t have a very strong framework like Core Data on iOS, we feel like there are very few reasons why you shouldn’t consider Realm for React Native. I say this because there’s a lot of trust and safety built into using the first party option in every ecosystem, so definitely there are a lot of reasons why if you’re on iOS you might still want to stick with Core Data or if you’re doing Android that you may want to use the built in SQLite functions. For React Native, there’s not the same nice, clean, first party persistence solution that has the semantics that we do and has the performance that we do. Unless you’re really happy with key-value storage, we think that you should probably give Realm a look. And again, if you don’t think we stay true to that promise, then we really would like your feedback to see how we can do that.

One of the specific use cases that tend to trigger people using us are if you need to use data offline. If you need to do complex querying, complex relationship between your objects, that’s another reason to think about it. If you need a lot of first party support from a company and not just community answers or open source projects, that’s another. There’s a bunch of different reasons to consider Realm but in terms of what apps, we really tried to invent something that should be usable by any app, whether you need offline or not, whether you need complex queries or not, no matter what business or application you’re building.

The Business Model

Peter Piekarczyk: If you don’t mind me asking, how are you guys going to make money? Because Realm is free, which is amazing, but what are your plans for the future? Offering an enterprise package?

Tim Anglade: Yeah. We’ve already generated revenue selling both services and also products around licenses to large company that need it. Our basic business model isn’t dissimilar to say, GitHub, where 90% plus of the product ends up being given away for free but it helps us build a community, build a standard on which we can up-sell a small portion of the population, to specifically ensure a sort of product that a large corporation would need. We’re looking to be a bit more public about what those offerings are in the next few months. We’re actually still learning a lot as to what people want to do on top of Realm and what specifically big corporations want out of Realm. It’s taking us a long time to refine that understanding into a nice packaged product with nice names and nice messages around them. Doing that while also taking care of launching all these new platforms and doing all support around that has been a bit of a slow ordeal but we’re going to have more announcement on that front in the next few months.

I always assume people have read the website, but in case they haven’t, the basic thing is we are free to use. All of our high level code, all of our JavaScript code in the case of React Native, is free and open sourced, Apache 2.0 on GitHub. We’ve committed to keeping that open source and to maintaining it, so it’s not going to be the case that what you’re using today is going to become paid all of a sudden. Everything that is open on GitHub will stay open on GitHub and we’ll also be actively contributing to expand it. That’s the basic promise of the business model.

Under the Hood

Lee Johnson: There are definitely a couple key features that I really love that I want to dig into shortly. But first, I just have a question about the code base for the JavaScript versus the OS side for React Native or Android side. Is it a SQLite under the covers with a bridge, or did you guys rewrite something completely different? How is that orchestrated, and could this ever develop into a node package?

Tim Anglade: The basic thing about Realm is that we don’t use SQLite. We’re not an ORM and we’re not building stuff with SQLite. So that’s different from virtually every other persistence option out there. We’re not building on LevelDB or any other key value store either. We’re built on our own underlying storage engine, which is a part of Realm that’s not open source right now, in full disclaimer. It’s something that we’re looking to open source, but it just keeps getting backlogged with everything else.

So we’re built on our own underlying storage system right now, that’s gonna go Apache 2 in the next few months. That is not strictly speaking a relational database, it’s a mix between a relational database and an object database. That powers a lot of the high-level feature that you see.

The reason why we’re able to give you a native JavaScript interface with really nice objects, and nice relationship model, and fast queries and everything else, is because we have our own storage underneath. It allows us to do a lot of really nice things, like an MVCC type storage underneath. like Git, but for your data objects. It allows us to do a lot of zero-copy things, it gives us a really nice threading model, which isn’t terribly useful of course in the case of React Native, but we hope that might change in other platforms. It’s a replacement for SQLite underneath, and at the higher-level is a replacement for an ORM, but it’s not exactly what’s happening.

There are some major differences, for example an ORM will take a copy of your data out of the database. That’s really bad for consistency, that’s really bad for resource usage, that’s really bad for speed. Whereas Realm has those two separate layers as well, like a SQLite layer, and like an ORM layer, but Realm’s layers are actually integrated to work together. We don’t copy data in and out, we give you complete consistency, everything is memory mapped all the way down. We get huge performance savings, huge ease of use improvements, and huge consistency improvements by having those two layers really tightly integrated together as opposed to the SQLite and ORM combo.

Scott Kyle: A huge portion of the Realm language bindings are shared between all the platforms within C++. Both that core storage layer that Tim was talking about and then another layer on top of that provides many of the facilities that all the language bindings need. Then we just specialize on top of that for each language. So with Swift, Objective-C, Java, they all require their own custom integration points, and we have this intermediary layer where we can make that really easy. We’re constantly improving that as well, and we do that obviously for Realm React Native as well.

Also like what Tim said, the objects that you pull out of the database, they’re not copied out. You’re just always looking at accessors to the data that’s in the database. So we can do lots of different kinds of operations very quickly that are sometimes very slow with ORMs because they have to make many queries through the database. Whereas we don’t really need to make many queries. We can do it all in one shot when the user needs it.

Tim Anglade: Yeah and there’s a specific example to give people a concrete example. If you come from a SQLite or ORM background, you have this idea of if you do a query, and that’s just a representation or projection of your data. If you want to edit the object you have to do a separate thing, and then find the object and edit it. With Realm, you don’t have to worry about that. Any time you get a query, all you get is the actual object and you can just modify them in line, for example. Again, any time you access any value in Realm, you’re not accessing some sort of derivative, or projection, or copy of it. You’re accessing the raw data itself, with a minor asterisk for consistency and refresh loops and stuff like that. This is a bit of a simplified view but you have access to everything.

Scott Kyle: We still have transactions, so when you do make modifications to your database you do that inside of a transaction. If anything does go wrong, like an exception is thrown, or even if the app itself crashed for some reason, your data should remain consistent because that transaction would not have been committed. Besides for making all your mutations inside a transaction, we try to keep the objects like their native object, like with JavaScript. Most of the Realm objects that you use, they just act like native JavaScript objects, or arrays, or whatever. So it’s really easy to use and integrate, and even pass around Realm objects into other libraries that are not even expecting a Realm object to be able to act on them.

Tim Anglade: Another quick thing to drop in there as an example of the interesting aspect of building our own core and integration thereof, is that we get to really apply a lot of reactive patterns directly into the design. Not in a very functional sense, we’re not doing streams and that stuff, but we have a really nice ability to just let you work very asynchronously, get notified of changes that are happening, and we’re doing more and more work there.

This is especially raw on the React Native side, where we still have to build in async inquiries to start with. The basic promise of the underlying engine, that you can see in the other products that we’re developing for Swift and Objective-C, and that’s on its way to React Native, is the ability to follow in a lot of really nice reactive patterns. Where you just subscribe to updates and are able to modify your UI when the underlying data changes very easily. Many people have tried and it’s very hard to build on top of SQLite or key value store, so it’s one of the nice things of being able to start fresh and build on your own foundation.

Auto-Updating Results & Listviews

Lee Johnson: That actually brings up one of the features I wanted to talk about, which is the auto-updating results which you even have for the React Native client. It’s pretty awesome especially considering the JavaScript, and iOS with its restrictions on the WebSockets and other things. For example, in iOS you’re restricted on how you can do those notifications for anything. How does that work, and could you explain the auto-updating a little bit and how it ties in? You also have a custom listview for React Native, how could those maybe be used together to show auto-updating of a listview?

Scott Kyle: Like we were talking about when you make a query into a Realm, you’re getting a view on that query that you made. So when you try to access objects inside those results, that’s when the actual query is made, and if something in the Realm changes that would affect that query. Then that query would get automatically updated so when you try to access objects out of those results again, it would give you a live representation of what the state of the Realm is at that moment.

We have change notifications but unfortunately right now they’re not super granular. So if you make a change to your Realm you’ll get a notification, but soon you’ll be able to get a change directly on a query that you made. For instance, if you have a listview – We have our own custom listview that would tie in with this very nicely. You can get a notification that something in that results changed so that you can re-render the listview. Right now we would re-render it on any change for now. It’s made to do that very efficiently because nothing has changed.

Our custom listview is not actually necessary to use to integrate Realm with a listview, it just exists to make it extra fast. For our own test purposes, we have a little app with a listview with about one million items in it, and you can scroll through it and delete them, and see them be deleted immediately. Using the stock listview, you could still use Realm with it but it would be a bit slower because of certain assumptions that it makes. So that’s why we built that, to make it extra easy and extra fast to use Realm queries, or Realm lists, inside a listview in your app.

Tim Anglade: The basic promise of what we’re building, that’s coming to React Native really quickly, is, let’s say you have a part of a UI that depends on a counter (the number of items that match a query and just one dynamic tooltip, or some sort of counter badge). You can subscribe to whether or not the results of this query have changed in any way, and then in the handler for that notification, you just recompute and redraw your UI. You don’t need to rerun the query. You don’t need to do anything because the count itself will have data automatically.

It’s super straightforward and painless to do a lot of basic UI changes. You don’t need to set up a lot of boilerplate code and you don’t need to think about the consistency of your data. It feels pretty native and fluid, with the JavaScript intact. We’re pretty excited about it – it’s pretty raw, but you can take a look at the other bindings and see what’s gonna drop in React Native very soon, as soon as we get done fixing some of these early bugs we’ve found, and support issues from the community.

Scott Kyle: This ties back in with what Tim was talking about earlier, how we have certain advantages. We’re not just building on top of SQLite, and one of the advantages of that is the deep integration from the core storage layer. When we do integrate fine-grained notifications, we won’t just get a message that something changed, we’ll be able to get a message as to exactly what changed. When updating UI components, knowing exactly what changed means you have to do a lot less recomputing diff’s and trying to figure out for yourself what changed. Again, it would just let you build an app that’s a little bit more performant.

Tim Anglade: It’s important to understand the general design patterns we have at the end of this. We fully bind to reactive patterns. I remember talking about that with Alexander, one of our two founders, and how he was pushing that when I first met him in 2013. Back then not very many people were super eager to talk about that, but it’s been driving the design of what we’ve been doing, at TightDB before even Realm, and definitely today at Realm. Whenever you’re wondering about what database we’re building, what framework we’re building, you can expect us to follow reactive patterns in everything we do.

Async

Peter Piekarczyk: How do you handle async states, loading indicators, and anything similar to that?

Scott Kyle: Right now when you query a Realm in Realm React Native, we only support synchronous queries right now, but async is coming pretty soon. Generally speaking, one of the reasons why async hasn’t been a priority for us is that we don’t generally see a performance impact unless you’re around 100,000+ items, and also asking them to be sorted in a certain way. For your regular use, standard to-do lists for normal people who don’t have 100,000 to-do’s, you don’t see much of a performance impact at all by doing live synchronous queries. That’s why we haven’t done that yet, but we are working on it, so for large databases you will be able to make asynchronous queries.

Tim Anglade: We haven’t agreed on the design specifically for that yet, but in other products that we have for Java and Swift, we let you determine what state your query is in and whether you’re still computing results, or whether you have finally computed the results, which makes it easy to update your UI accordingly.

As Scott said, in practice this is not a performance bottleneck, which I know flies in the face of a lot of “best practices” for app development, where people tell you to do all the I/O asynchronously. A lot of those best practices are designed with stuff like SQLite and ORMs in mind, and the performance improvement you get out of Realm is actually very major to the point where it’s really much closer to accessing objects in memory than it is to performing old school I/O like you’re used to with SQLite. We understand some queries still will need to be done asynchronously, but we recommend people to just enjoy the fact that they don’t have to worry about the state of their query and whether it has finished completing for most cases, and can just do a synchronous query.

Encryption

Lee Johnson: One thing I definitely want to discuss, because it’s one of the features that you guys have that really excited me, is the encryption. A lot of times, especially with SQLite for example because that’s what most people are familiar with, it’s a pain to get the SQLite cipher and get it set up. You have data on a device and devices are getting hacked all the time, and it’s in the news, now, with Apple fighting with the government over encryption.

We deal with data, but we don’t put any student data on mobile devices for that very reason. It’s just not worth the risk. But for health care applications for example or anything sensitive, can you walk through the use case and your encryption?

Tim Anglade: Encryption is one of the things that we actually had at launch for Android because we knew it was a big limiting factor on that platform. iOS already has a lot of built in encryption of files and all that stuff, so it was pretty good. For Android it was really nice to be able to just do it first party. So now we have encryption rolled out across platforms on both IOS and Android and accessible from React Native whether you’re targeting iOS or Android. To be clear though we don’t implement our own crypto, we piggy-back on either OpenSL or common crypto and we use standard AES 256 algorithm.

It’s really just like accessing any Realm you have in your application but instead of just opening it, you just have to pass the key to encrypt it or decrypt it. The only tricky part is where you store that key. You have to make sure you either get that key from somewhere secure, from a third party service, or you have to store it securely on the device. I believe there’s a library that lets you alias that across different OS’s. If you’re comfortable storing that key or getting that key from somewhere, Realm makes the encryption part very easy and uses best practice implementations from trusted 3rd party libraries. It’s definitely been mentioned as something that people like quite a bit. Getting the same level of encryption from other frameworks, especially on React Native, is really cumbersome otherwise.

Lee Johnson: Yeah, there are a lot of hoops to jump through to get any of that, but with Realm it’s literally just setting the key, right? You have a method to create the hash based on your key and then you pass it – is that how it works?

Tim Anglade: Yeah, it’s just a 64 byte key and as long as it’s correct we’ll let you open the file. I don’t have specific stats on usage but I’m always amazed because I hear about even non-health care applications or e-commerce applications using this feature, because it’s much easier than relying on platform features or other integrations. We’re really glad that we put that in. It was a bit of a complex implementation task as you can imagine to wire all that in, and we weren’t quite sure if it was worth the time we spent, but it seems to be very well-received.

Object Types

Lee Johnson: You have different object types in your models, with lists being one of those types. Can you go through the object types that you can have in your models and your schema and how they’re set up, and some of those list types, object types, and different ways you can connect data?

Scott Kyle: When you define a schema for an object, for instance, and you have a data model of a person for example, you can have your basic primitive types as properties on that person, such as string for their name and a number for their age, or a date for their birthday. We also support relationships so you can have, for instance, partner could be a pointer to another person, for instance. Or we refer to them as references to other persons. You can have lists too. You could have a list of friends and inside that list there are references to other persons, or to other objects, like pets for instance.

You define all that in your schema and then when you create those person objects or you get them out of the Realm when you query for them, you get objects that will basically behave just like native Javascript objects. You access a property like a name, and you get back a string, or you access a property called “friends” and you get back a list that basically looks and acts as much like an array as we really can make it. It has all your standard array methods, both for iterating through them and also for slicing them or pushing new objects onto them. Generally speaking it will behave as much like an array as we could make it behave. That’s list and that’s why we don’t call it array because we don’t want to mislead anyone into thinking it’s exactly an array, but generally speaking it will behave just like an array.

Tim Anglade: That name varies a little bit from platform to platform because we call it an array when we do Objective-C and we call it a list when we do it in Java. It really emulates arrays pretty closely as Scott mentioned. We think about it as “What if you just had to model your data with regular Javascript objects? How would you make that happen?” We try to give you Realm models that are as close to that as possible, that you can very intuitively understand. For example you’re going to declare your own standard properties, you’re going to link one object to another just by referencing them, and when an object references multiple other objects like a person having many cats then you’re going to use an array to do that. We wanted that syntax to be very intuitive. We don’t want you to have to worry about schemas and abstract types that are not native to your language or any other complexities, but rather you can just chain things as if they were just regular objects.

Lee Johnson: You mentioned the pointer to the actual object. There are document stores like MongoDB, where things are nested and it gets really difficult to normalize, then you have relational databases like anything Postgres, where the relationships can get really complex and can be overkill for mobile applications. Is Realm some blend between the two?

Tim Anglade: It’s more of a mix between a relational database and an object database. This is the part where it gets tricky, and I’m simplifying drastically, but the short of it is underneath, your data is in tables with rows and columns. The columns have types, and everything is neatly stored in this platform-independent format. So if you write that Realm data from React Native you can open it from Swift concurrently, for example. In both languages you’d be able to read and write the same file.

That data is always automatically mapped to an object, so when you reference another object from an object it’s just going to point you to that other table that contains the row that has the columns for the object that you want. It’s a property that lets you do a very expressive thing, like a document model, but without the overhead of every document with nested sub-documents becoming too large and complex to index or fetch in and out of memory well, because we always have independent properties accessible in memory.

It allows us to do an immense amount of lazy loading. If, for example, you’re loading an object that is graphed sequentially to every other object in your database, and it goes all the way down: object linked to an object, linked to another object, etc. Just because you load that top level object, it won’t load the rest of your graph in memory. You won’t even load any of their properties until you try to access one of those properties, because everything is just referenced. It’s a nice hybrid storage system that gives you a high level expressive object model but with the performance of a traditional table-oriented database. It’s not strictly speaking relational, because we don’t use real relational algebra and joined tables. It’s a table that consists of rows and columns, so you can isolate individual properties and values very easily and you have maximum performance there.

Read more

Realm React Native 0.11.0

by /

First off, a word of thanks for the warm reception you all gave to our newest product. Hundreds of you are already using Realm in React Native apps, and the community is growing every week. Thanks to your feedback, we were able to release version 0.11.0 of Realm React Native. We fixed a ton of bugs since our initial release, added support for indexed fields and encryption, and you can now install Realm with just one line in your terminal!

Easier setup and installation

Realm React Native is now packaged as a static library for iOS and can be setup completely from the command line using rnpm. To use the new version after updating your package.json:

  • Remove the reference to RealmJS.xcodeproj from your Xcode project (under the Libraries group)
  • Make sure rnpm is installed and up-to-date: npm install -g rnpm
  • Run rnpm link realm from your app’s root directory

Major additions

  • Support for encrypted Realms
  • List and Results are now iterable (e.g. supports for...of loops)
  • Common iteration and other methods from Array have been added to Results and List
  • Case insensitive queries are supported by adding [c] after operators
  • Support for indexed bool, string, and int properties
  • Added Realm.schemaVersion method, to check whether unopened Realms should be migrated

Major bugfixes

  • Fix for crash on Android when initializing the Realm module
  • Fix for using Chrome debug mode from a device

For the full details, check our the full release notes.


Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, or Twitter.

Read more

Introducing Realm Cocoa Converter

by /

Today, we’re launching a new open source library to complement Realm Objective-C and Realm Swift called Realm Cocoa Converter!

We’ve heard from many of our users that there are times in their development where they would like to be able to move large batches of data in and out of Realm files more easily. The goal of Realm Cocoa Converter is to provide a common library to enable importing data from other file formats into Realm, and vice-versa, exporting data from Realm.

The library is written in Swift, and is very easy to work with. For exporting a Realm file, it only takes a single class. For example, exporting to CSV:

let path = ... // Absolute path to the target Realm file
let destinationFolder = ... // Absolute path to the folder in which to save the CSV files

let exporter = CSVDataImporter(realmFilePath: path)
exporter.exportToFolderAtPath(outputFolderPath: destinationFolder)

When importing files into Realm, the process is a little more complicated. This is because Realm needs to generate a schema for each type of object in the input file before the data can be imported.

Realm Cocoa Converter handles this by having a separate class for intelligently generating the schema, which can then be either saved, or modified by the user before the import.

This schema is then supplied when the import operation takes place.

var filePaths = [String]() // An array of paths to each file representing a Realm table

// Create an instance of the schema generator and analyze the contents of those data files
let generator =  ImportSchemaGenerator(files: filePaths)
let schema = try! generator.generate()

let destinationRealmPath = ... // The destination folder for this Realm file

// Create an importer object, and import those files using the previously generated schema
let dataImporter = CSVDataImporter(files: filePaths)
try! dataImporter.importToPath(String(destinationRealmPath), schema: schema)

While Realm Cocoa Converter itself is implemented in Swift, it has also been designed to properly integrate with Objective-C and its code conventions as well.

NSString *path = ... // Absolute path to the target Realm file
NSString *destinationFolder = ... // Absolute path to the folder in which to save the CSV files

RLMCSVDataExporter *exporter = [[RLMCSVDataExporter alloc] initWithRealmFileAtPath:realmFilePath];
[exporter exportToFolderAtPath:destinationFolder withError:nil];

Currently, the library contains support for generating Realm files from groups of CSV and XLSX files, and the ability to export to CSV files. We’re planning on adding more formats in the future, including JSON and SQLite.

Realm Cocoa Converter is still very much in its infancy, and we’d love to have you help in its development! If you have any specific use-cases in your app for it, or additional formats you think it should support, please let us know!


Thanks for reading. Now go forth and build amazing apps with Realm! As always, we’re around on Stack Overflow, GitHub, or Twitter.

Read more