Realm Blog

Realm Java 0.85 — with new encryption implementation!

by /

We just released a new version of Realm Java to this website and to Maven. This release replaced the signal handler–based encryption implementation with a more generic solution which works on all devices. Also a new API, Realm.isEmpty(), was added.

New Encryption Implementation

As we mentioned in our previous post, “A Look Into Realm’s Core DB Engine”, we used to rely on the POSIX signal handler to implement Realm’s encryption. It’s a really simple and elegant solution, from a software point of view. But when it comes into the real Android world, the signal handler becomes the root cause of a few weird crashes.

  • Starting with 5.0 Lollipop, Android began shipping a Chromium WebView that can be installed and updated through the Play Store. Unfortunately there was a bug in the WebView v40 that could cause encrypted Realms to crash if used together. More information can be found here.
  • A few older devices (HTC One X for example) do not work correctly with the signal handler. The same problem on the HTC One X happened to Firefox for Android as well. See this Bugzilla page for more details.

Although we tried to use workarounds to enable the encryption on as many devices as we could, using the signal handler on a device like the HTC One X is an impossible mission, because the relevant API on the device is broken. That’s why we decided to rewrite our whole encryption implementation. From this version (v0.85.0) on, Realm’s encryption will work on all Android devices!

So now you can remove the catch block of RealmEncryptionNotSupportedException and let Realm encrypt the data on any Android devices.

New API - Realm.isEmpty()

Now you can check if a Realm contains any data by calling Realm.isEmpty().

Breaking Changes

RealmEncryptionNotSupportedException is removed since it is not needed anymore. 🎉

Realm.executeTransaction() now directly throws any RuntimeException instead of wrapping it in a RealmException. If there is something wrong in the transaction block while calling Realm.executeTransaction(), the original exception will be thrown to make it easier to debug. When exceptions occur, the transaction will be rolled back, just like before.

RealmQuery.isNull() and RealmQuery.isNotNull() now throw IllegalArgumentException instead of RealmError if the field name is a linked field and the last element is a link.

Read more

Realm Java 0.84 — with Async Queries & Transactions!

by /

We just released a new version of Realm Java to this website and to Maven. This release includes support for asynchronous queries and asynchronous write transactions!

Android applications are inherently asynchronous, and thus one of the most requested features was the ability to execute Realm read queries or write operations asynchronously on a worker thread.

Asynchronous Queries

You can now execute queries asynchronously on a worker thread.

Async queries are very similar to our existing, synchronous queries. You can keep using the same fluent API to build the query, but the last method in the call will decide the behavior if the RealmQuery is synchronized (findAll()) or asynchronous (findAllAsync()).

Example: finding users with name “John” or “Peter”

First create the query:

RealmResults<User> result = realm.where(User.class)
                              .equalTo("name", "John")
                              .or()
                              .equalTo("name", "Peter")
                              .findAllAsync();

Note that the query is not blocking and immediately returns a RealmResults<User>. This is a promise (similar to the concept of Future in standard Java). The query will continue to run in a background thread, and once it completes it will update the returned instance of RealmResults with the appropriate results.

If you want to be notified of the query completion, you can register a callback. This callback will also be called every time the query is refreshed to reflect the latest changes in Realm (usually after a commit).

private RealmChangeListener callback = new RealmChangeListener() {
    @Override
    public void onChange() { // called once the query complete and on every update
    // use the result
    }
};

public void onStart() {
    RealmResults<User> result = realm.where(User.class).findAllAsync();
    result.addChangeListener(callback);
}

Since we hold a strong reference to the listener, don’t forget to remove any registered listener to avoid leaking the enclosing class.

public void onStop () {
    result.removeChangeListener(callback); // remove a particular listener
    // or 
    result.removeChangeListeners(); // remove all registered listeners
}

At any time you can check if the returned RealmResults has completed or not

result.isLoaded()

Calling isLoaded on a RealmResults obtained synchronously will always return true.

Non-Looper threads caveat: The Async query needs to use the Realm’s Handler in order to deliver results consistently. Trying to call an asynchronous query using a Realm opened inside a thread without a Looper will throw an IllegalStateException

Asynchronous Transactions

You can now also execute write transactions asynchronously on a worker thread.

It works the same way as the current executeTransaction, but instead of opening a Realm on the same thread, it will give you a background Realm opened on a different thread to work with.

You can register a callback if you wish to be notified when the transaction completes or fails (this also requires the Realm’s Handler to deliver the callback. If you start an async write from a Realm opened from a non-Looper thread, you won’t get the notification):

realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm bgRealm) {
                User user = bgRealm.createObject(User.class);
                user.setName("John");
                user.setEmail("[email protected]");
            }
        }, new Realm.Transaction.Callback() {
            @Override
            public void onSuccess() {
            }

            @Override
            public void onError(Exception e) { 
                // transaction is automatically rolled-back, do any cleanup here 
            }
        });

The callback is optional and can be null if you want to fire and forget:

realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm bgRealm) {
                User user = bgRealm.createObject(User.class);
                user.setName("John");
                user.setEmail("[email protected]");
            }
        }, null);

We hold a strong reference to the callback until the write transaction completes. In case you want to cancel a pending transaction (e.g. you’re quitting your Activity/Fragment) don’t forget to call cancel — it will attempt to cancel the scheduled transaction and remove the reference to your callback in order to avoid leaking the instance/enclosing class:

RealmAsyncTask transaction = realm.executeTransaction(new Realm.Transaction() {
            @Override
            public void execute(Realm bgRealm) {
            }
        }, null);

// configuration change ... 

public void onStop () {
    if (transaction != null && !transaction.isCancelled()) {
        transaction.cancel();
    }
}

New query options

We’ve added two new ways of doing queries: isEmpty() and distinct().

RealmQuery.isEmpty() can be used to test if a value is not null but considered empty, i.e. a RealmList or byte array with 0 elements is empty and the String "" is empty. isEmpty() does not work on number values.

// Find all users with no dogs
RealmResults<User> users = realm.where(User.class).isEmpty("dogs").findAll(); 

// Find all users with at least 1 dog
RealmResults<User> users = realm.where(User.class).not().isEmpty("dogs").findAll(); 

Realm.distinct() can be used to return a distinct set of elements as defined by a given field. distinct will only work on fields that are indexed (@Index or @PrimaryKey).

// Returns the set of users that all have a different name
RealmResults<User> users = realm.distinct(User.class, "name");

More utility methods

We’ve added some extra utility methods that make it possible to ask about the state of the Realm before interacting with it:

  • Realm.isClosed(): Checks if the underlying Realm file is still open.
  • Realm.isInTransaction(): Checks if the Realm is currently in a write transaction.
  • RealmQuery.isValid(), RealmList.isValid(), RealmResults.isValid(): Checks if the underlying Realm hasn’t been closed or the data deleted.

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.96

by /

Realm files read or written by this version cannot be opened with previous versions of Realm. Please be careful about shipping updates to your existing apps!

We just released version 0.96 of Realm Objective-C and Realm Swift.

This release contains official support for null properties, keypath collection queries (count/min/max/sum/avg), a new RealmCollectionType protocol in Swift, error handling in writes, and a fistful of bug fixes!

Last week, we published a beta version of this release but now we feel this is ready for prime time.

Null Support

This version adds support for null values for all property types.

Objective-C

NSString *, NSDate *, NSData * now allow nil by default. You can disallow setting a property to nil by overriding the +requiredProperties class method and including the names of the properties which you want to disallow nil for. Accessing a Realm file created with a previous version will automatically convert these properties to nullable in the file itself, unless explicitly marked not to do so in +requiredProperties.

Optional numbers can be stored using an NSNumber * property which is tagged with the type of the number. You can use NSNumber<RLMInt> *, NSNumber<RLMBool> *, NSNumber<RLMFloat> *, and NSNumber<RLMDouble> *.

@interface OptionalTypes : RLMObject
@property NSString *optionalString;
@property NSString *requiredString;
@property NSData *optionalData;
@property NSDate *optionalDate;
@property NSNumber<RLMInt> *optionalInt;
@property NSNumber<RLMBool> *optionalBool;
@property NSNumber<RLMFloat> *optionalFloat;
@property NSNumber<RLMDouble> *optionalDouble;
@end
@implementation OptionalTypes
+ (NSArray *)requiredProperties {
    return @[@"requiredString"];
}
@end

Swift

String, NSDate and NSData properties work as you’d expect them to and can either be optional or non-optional. Unfortunately, we’re unable to directly support optional numeric types (see #2147), so you have to wrap the types in RealmOptional. For example:

class OptionalTypes: Object {
    dynamic var string: String? = "B"
    dynamic var data: NSData? = "C".dataUsingEncoding(NSUTF8StringEncoding)
    dynamic var date: NSDate? = NSDate(timeIntervalSince1970: 10)
    let int = RealmOptional<Int>(1)
    let float = RealmOptional<Float>(2.2)
    let double = RealmOptional<Double>(3.3)
    let bool = RealmOptional<Bool>(true)
    let boolWithNilDefault = RealmOptional<Bool>(nil)
}

As with List properties, RealmOptional properties should always be declared with let and not be declared dynamic. The actual value of the RealmOptional is read from and written to the value property.

Automatic Conversion

Realm files opened with this version will be automatically converted to the new file format on first access, even when only accessed in a read transaction. This automatic conversion will perform the following operations:

  1. All indexes will be recreated (only applies to ints and strings).
  2. All NSString, NSDate, and NSData properties are converted to nullable, unless marked as required in +requiredProperties.
  3. The new format version number will be written to the file.

Since this writes to the file, Realm files created with a previous version of Realm won’t be able to be read with this new version. If you’re bundling a Realm file in your app, it will have to be updated to use this new file format.

Note that this format conversion is irreversible.

Manual Migration

Please note that even though the file format upgrade happens seamlessly in the background, a schema migration in order to adopt nullable properties still needs to be performed. Even if you haven’t made any changes to your object schema in the interim, certain properties are now made nullable by default, and so you may be required to make changes to your code if you want to keep the schema the same as before. That’s especially the case when you have NSString, NSDate and NSData properties used from Objective-C, which are - as explained as above - optional by default. So assuming you had a model like shown below originally:

@interface Dog : RLMObject
@property NSString *name;
@property NSDate *birthdate;
@property Person *owner;
@end

@implementation Dog
@end

As a dog owner, you usually know your dog’s name - clearly a required property - but if you may have adopted it, you might not know the exact birthdate - something that can be considered optional. In this case, you would need to define the name as a required property in an overridden implementation of +requiredProperties on the class Dog as shown here.

@implementation Dog
+ (NSArray *)requiredProperties {
    return @[@"name"];
}
@end

Since at this point birthdate is now implicitly optional, you will still need to define a basic migration in order to properly update the schema to accomodate this. In the past, you may have provided arbitrary data to serve as default values, such as [NSDate dateWithTimeIntervalSince1970:0], which is admittedly very ambiguous in relation to birthdates, but as this is no longer necessary, you may want to go back any of your existing objects to make sure you remove any arbitrary values and properly replace them with null ones.

// Inside your [AppDelegate didFinishLaunchingWithOptions:]
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];

// Set the new schema version. This must be greater than the previously used
// version. If you've never set a schema version before, the version is 0,
// so assuming that'd be your first migration, we set it to 1.
config.schemaVersion = 1;

// Set the block which will be called automatically when opening a Realm with a
// schema version lower than the one set above
config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
    // We haven’t migrated anything yet, so oldSchemaVersion == 0
    if (oldSchemaVersion < 1) {
        [migration enumerateObjects:Person.className
                          block:^(RLMObject *oldObject, RLMObject *newObject) {
            // convert null-placeholders to actual nils
            newObject[@"birthdate"] = [oldObject[@"birthdate"] timeIntervalSince1970] > 0 ? oldObject[@"birthdate"] : nil;
        }];
        
        // Note: Even if you don't have to convert placeholder values,
        // you still have to provide at least an empty migration block
        // when your schema has changes to nullability of properties.
    }
};

The first access of [RLMRealm defaultRealm] will cause the file format to be upgraded automatically, and will execute the migration.

Keypath Collection Queries

Keypath collection queries using @count, @min, @max, @sum and @avg are now supported on RLMArray/List properties. See our handy NSPredicate Cheatsheet for more details on how to use these.

RealmCollectionType

RealmCollectionType is deprecated and has been replaced by RealmCollection. The section below is retained in its original state for posterity, but you should see here for the latest on `RealmCollection`.

Users of Realm Objective-C have had the ability to represent both RLMArray and RLMResults using their shared protocol (RLMCollection) for a long time. We’re now reflecting that protocol in Swift, while expanding what it can do.

Functionality common to both List and Results is now declared in a RealmCollectionType protocol that both types conform to. A type-erased wrapper is also provided, so Swift can store a reference to the underlying collection despite its layout being different:

class ViewController: UIViewController {
    var collection: AnyRealmCollection

    init(collection: RealmCollectionType) {
        super.init()
        self.collection = AnyRealmCollection(collection)
    }
}

Improved Error Handling

In current versions of Realm committing a write transaction on a severely space-constrained device would cause Realm to crash. Thankfully, Realm’s crash safety would prevent existing data from being corrupted, but this wasn’t exactly a solid user experience.

Now committing write transactions via commitWrite / commitWriteTransaction and write / transactionWithBlock optionally allow for handling errors when the disk is out of space.

Minor Enhancements

  • Added isEmpty property on RLMRealm/Realm to indicate if it contains any objects.

Bug Fixes

  • Fix assertion failure when inserting NSData between 8MB and 16MB in size.
  • Fix assertion failure when rolling back a migration which removed an object link or RLMArray/List property.
  • Add the path of the file being opened to file open errors.
  • Fix crashes when the first Realm opened uses a class subset and later Realms opened do not.
  • Fix inconsistent errors when Object(value: ...) is used to initialize the default value of a property of an Object subclass.
  • Throw an exception when a class subset has objects with array or object properties of a type that are not part of the class subset.
  • Fix a crash that could be triggered by rapidly opening and closing a Realm many times on multiple threads at once.
  • Fix several places where exception messages included the name of the wrong function which failed.

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

Read more

Realm Java 0.83 — with Null Support!

by /

Realm files read or written by this version cannot be opened with previous versions of Realm. Please be careful about shipping updates to your existing apps!

We just released a Realm Java update to this website, and to Maven. This release includes support for null values, one of the most-frequently requested Realm features!

Breaking Changes

With this release, fields of the types String, Date, and byte[] are now nullable by default. (In previous versions of Realm Java, no fields could have the value null.) Existing apps will have to either modify model classes or provide a migration step to explicitly support this new feature. Read on for details.

In order to be able to support null values, Realm’s underlying storage engine has changed its file format. Your Realm files will automatically be converted to new file format when you open the Realm file for the first time. The file format conversion is irreversible! It is not possible to open the new Realm file using a previous version of Realm. Furthermore, it is not possible to downgrade a Realm file to the old file format.

If you are going to upgrade existing apps, we recommend that you test carefully before shipping.

Boxed types

Realm Java supports the most common types in Java, including boolean, integer types (byte, short, int, and long), and floating-point numbers (float and double). These primitive (or unboxed) types cannot be assigned to null in Java, and thereby they have served us well. You can still use the primitive types in your model classes. As before, the primitive types indicate that the field cannot be assigned to null.

On the other hand, boxed types are common in Java, and variables and fields of boxed types can be assigned to null. We are introducing boxed types for booleans (Boolean), integers (Byte, Short, Integer, and Long), and floating-point numbers (Float and Double) to Realm Java. When you use these boxed types in your model classes, the field can be assigned to null.

Fields of the types String, Date, and byte[] can be null. Setting a RealmList field to null means that the list is cleared. No objects are removed, only the references to the objects are removed. Moreover, a RealmList field cannot be null. The getter will always return a RealmList object but the length of the list might be zero.

Let us show you a little example. The model class below has two integer fields and one string field.

class Person extends RealmObject {
    String name;
    int age;
    Integer weight; // weight is not required!
}

You can create objects, and assign values to the fields.

Person john = realm.createObject(Person.class);
john.setName("John");
john.setAge(25);
john.setWeight(73);

Person bill = realm.createObject(Person.class);
bill.setName("Bill");
bill.setAge(41);
bill.setWeight(null);

As you can see, we set all three fields for John, while we don’t know the weight of Bill and set it to null (actually, the default value for Person.weight is null so we can skip the line).

The new @Required annotation

Strings, Dates, byte[], and box typed fields can all be assigned to null. As the example above showed, sometimes a proper value (not null) is required. You can specify that a field cannot be null by using the new @Required annotation. Using this annotation, Realm will not allow you to set it to null. If you will always know the name of a person, a better model class is:

class Person extends RealmObject {
    @Required
    String name;
    int age;
    Integer weight;
}

It is possible to add the @Required annotation to boxed typed fields, and Realm will enforce that no null values are saved. The annotation is not used for the primitive types, as a field of a primitive type cannot be null. Moreover, relationships (RealmList and single Realm objects) cannot be required.

Querying

For any field which is not required, you can query with null as a value. Moreover, aggregate functions (sum, min, etc.) will not take null values into account. The Realm interpretation of null implies that every string begins with, ends with, and contains null. This means that the following query will return all objects:

RealmResults<Person> persons = realm.where(Person.class).where().beginsWith("name", null).findAll();

If you query with null as a value for required fields, an exception is thrown.

Migration

With the release supporting null, Realm’s underlying storage engine will automatically convert your Realm files. The conversion is required as the file format used by the storage engine has been changed. The conversion is done even though you don’t intend to use null values in your model classes. The automatic conversion will take time, so the very first access to a Realm file will take a bit longer. After the conversion, files will be opened just as fast as before.

You are likely to do some manual migration as well. If you have string, date or binary (byte[]) fields in your model classes, you will have to migrate them. In previous versions of Realm Java, Strings could not be null. In version 0.83.0 of Realm Java, the semantics of String has been changed. Take the following model class as an example:

class Dog {
    String name;
    int age;
}

If you have created a Realm file which includes Dog, the field name could not be assigned to null. With Realm Java 0.83.0 and later, if you which to disallow null as a value, you must change the model class to:

class Dog {
    @Required
    String name;
    int age;
}

If you don’t wish to change the model class (or wish to use null), you will have to migrate the Realm file. For that purpose, you can use the method Table.convertColumnToNullable() as part of your migration.

RealmMigration migration = new RealmMigration() {
    @Override
    public long execute(Realm realm, long version) {
        Table table = realm.getTable(Dog.class);
        table.convertColumnToNullable(table.getColumnIndex("name"));
        return 1;
    }
};

RealmConfiguration realmConfig = new RealmConfiguration.Builder(getContext())
    .schemaVersion(1)
    .schema(Dog.class)
    .migration(migration)
    .build();
Read more

Leonardo Kim joins Realm

by /

We’re happy to announce that Leonardo has joined Realm and will be helping us from Seoul, Korea.

김용욱 님이 대한민국 서울에서 렘과 함께 일하게 되었다는 사실을 알릴 수 있어 기쁩니다.

Leonardo Kim 김용욱

Leonardo YongUk Kim is a software developer with extensive experience in mobile and embedded projects, including: several WIPI modules (Korean mobile platform based on Nucleus RTOS), iOS projects, a scene graph engine for Android, an Android tablet, a client utility for black boxes, and some mini games using Cocos2d-x. He has also developed many open source projects.

Additionally, Leonardo has been an organizer of GDG Korea Android for the last several years. To date, he has organized conferences, codelabs, hackathons, and meetups.

Get in touch with Leonardo on Facebook, GitHub or email. Welcome to Realm, Leonardo!

김용욱님이 대한민국 서울에서 Realm에 합류 하였습니다.

김용욱님은 많은 모바일 프로젝트와 임베디드 프로젝트를 개발한 소프트웨어 프로그래머로 WIPI, iOS, 씬 그래프 엔진, 안드로이드 타블렛, 블랙박스, Cocos2d-x로 작성된 미니게임 등의 다양한 프로젝트에 참여했습니다.

그는 또한 GDG 코리아 안드로이드의 오거나이저로 몇년간 활동해왔습니다. 그는 몇몇 오픈소스 프로젝트를 개발하고 컨퍼런스, 코드랩, 해커톤, 밋업을 개최하였습니다.

김용욱님을 페이스북, 깃헙, 이메일를 통해 만나보세요. 용욱님 환영합니다!

Realm Community in Korea

Realm is a mobile database: a replacement for SQLite & Core Data. It’s easy to use, fast, and cross platform.

The Realm community in Korea has expanded rapidly since our public launch in July 2014. From the start, we’ve prioritized the Korean developer community; Tim Anglade, our VP of Product unveiled Realm for Android publicly while on stage at Seoul’s DEVIEW conference in September, 2014. This year, we expanded and presented at both GDG Android and DEVIEW 2015.

In Korea, we organize regular meetups in Seoul to share knowledge, host technical presentations, and help Realm users meet one another. In the future, we plan to organize a coding club, hackathons, and more. Many Korean apps are already using Realm, including: Retrica, Cymera, RidiBooks, CJmall, and Interpark. We hope your app will join this list!

Please join us on the Realm Korea Page where we share the latest news about Realm & mobile development. We also have a Realm Korea User Group on Facebook to help you solve technical problems, share case studies, presentations, tips, and more. Feel free to ask your questions in Korean there or email [email protected]. Happy hacking!

Realm 은 Android와 iOS 에서 SQLite와 Core Data를 대체해 사용하실 수 있는 모바일 데이터베이스입니다. 오픈소스로 무료로 사용하실 수 있고, 간결하고 짧은 코드로 편하게 개발할 수 있으며 속도가 빨라 더 나은 사용성의 앱을 만들 수 있습니다. 현재 Starbucks, Amazon, Ebay 등에서 모바일 앱 개발에 사용되고 있습니다.

Realm 사용자 커뮤니티는 2014년 7월에 Realm SDK 가 공개된 이후 빠르게 발전해 왔습니다. Realm은 2014 DEVIEW 컨퍼런스에서 Realm: Android와 iOS를 위한 데이터베이스 세션을 진행 하였고, Realm Android SDK는 그 세션에서 공개 되었습니다. 이는 Realm 이 한국 Android 사용자를 얼마나 중요하게 생각하고 있는지를 보여줍니다. 현재 카카오헬로, 네이버 폴라, 싸이메라, 리디북스, CJmall 를 포함한 다양한 한국 앱들이 이미 Realm을 사용하고 있습니다.

2014년에 제품을 발표한 이래 한국에서 꾸준히 Realm 개발자 모임을 진행하고 있습니다. 최근에는 8월에 네이버 D2에서 Realm 개발자 모임을 가졌습니다.

앞으로도 한국에서 정기적인 개발자모임을 가지고 기술정보를 교환하는 등 모바일 개발자들들 위한 자리를 만들 계획입니다. 또한 코딩 클럽, 해커톤, 코드랩 등의 행사도 기획하고 있습니다. 페북에서 운영중인 Realm 한국 사용자 그룹 에 기술이슈나 사용 경험, 프리젠테이션 자료, 사용 팁 등을 공유해 주시고 Realm 한국 사용자 페이지와도 방문해 주십시오. 한국어 연락처는 [email protected] 입니다. 감사합니다.

Read more

Makoto Yamazaki joins Realm

by /

We’re happy to announce that Realm’s recent agreement with uPhyca Inc. has resulted in Makoto Yamazaki, a.k.a. @zaki50, joining our team! Makoto will support Realm’s development in Japan, focusing mainly on the Android platform.


株式会社ウフィカとRealmが契約を結び、山﨑 誠(@zaki50)がRealmの活動に加わることになりました! 主にAndroidを中心に、Realm自体の開発と日本における利用を支援してまいります。

Makoto Yamazaki

As a seasoned Java and Android expert, Makoto has already developed many apps. He has also given technical presentations at several Android conferences, including Android Bazaar and Conference (ABC) and DroidKaigi.

In addition to helping us develop Realm software, Makoto will also support Japanese developers by sharing information and maintaining a helpful presence in the community.

Japanese developers have already been talking about Realm on channels such as Twitter, Facebook, Stack Overflow, and Slack, thanks to Katsumi Kishikawa, another Realm team member based in Japan. With Makoto’s help, we are confident that we will provide even better support to Japanese developers.

You can follow Makoto on Twitter and GitHub, or you can even drop him an old fashioned email.

山﨑はJavaおよびAndroidのエキスパートとして様々なアプリケーションの開発に携わってきただけでなく、Android Bazaar and Conference(ABC)DroidKaigi など各種Android関連イベントでの豊富なプレゼンテーション経験をもっています。

これらの経験をもとに、これからはRealmの開発だけでなく、日本の開発者のみなさんとRealmをつなぐ存在として積極的に情報発信と支援活動をおこなってまいります。

現在Realmでは、TwitterFacebook GroupStack Overflow日本語版Slackを日本の開発者のみなさんとのコミュニケーションのチャンネルとして活用しています。 これまでは岸川がひとりで日本の開発者のみなさんを支援してまいりましたが、山﨑が加わることでより一層充実した支援体制となることを確信しております。

TwitterGitHubで山﨑をフォローしてください。また、困ったことや要望があれば、どんなことでもお気軽にメールしてください。

Realm Community in Japan

Realm is a mobile database: a replacement for SQLite & Core Data. It’s easy to use, fast, and cross platform.

The Realm community in Japan is very active. We regularly organize meetups to share knowledge, host technical presentations, and help Realm users meet one other. Many Japanese apps are already using Realm, including AWA, Nikkei, Eight, Sync by Wantedly, and ChatWork.

Please join our Realm Japan User Group on Facebook to find help solving technical problems, as well as case studies, presentations, and tips for using Realm. We also run Realm Slack. Feel free to join us there and ask any questions you have, in Japanese or English. Happy Hacking!

RealmはSQLiteやCoreDataの代替となるべくオープンソースソフトウェアとして開発されているモバイルデータベースです。クロスプラットフォーム(現在はiOSとAndroid)で利用でき、シンプルなAPIで簡単に利用することができ、動作速度が非常に高速であることが特長です。この利点を活かして、より短期間で使い勝手の良いアプリケーションを開発することが可能になります。

すでに日本では音楽ストリーミングサービスのAWA日本経済新聞 電子版、名刺管理のEightSync by WantedlyChatWorkなど数多くのアプリケーションでRealmが使用されています。

デベロッパーコミュニティに対する活動として、毎月のRealmミートアップの開催や、各種の勉強会、ミートアップをサポートしています。

また、私たちはFacebookにユーザーグループRealm Japan User Groupを開設して、技術情報の共有、新機能のお知らせ、アプリケーションの紹介など、日本のデベロッパーの皆さんの情報交換をサポートしています。

より複雑な質問にはSlackチャットによるサポートを活用しており、迅速な問題解決に役立っています。もちろん、質問は日本語でしていただいて構いません。

We’re Hiring!

Welcome to Realm, Makoto!

If you’d like to work with Makoto and the rest of us at Realm, take a look at our jobs page, or drop Tim a line.

Read more

Realm Objective-C & Swift 0.96 Beta

by /

Realm files read or written by this version cannot be opened with previous versions of Realm. Please be careful about shipping updates to your existing apps!

We just made a special release of Realm Objective-C & Swift numbered “0.96.0-beta”. This release can be installed manually using our zip release for Objective-C or Swift, or by specifying this exact version in your Podfile or Cartfile. For the RealmSwift pod, you’ll need to use 0.96.0-beta2.

This release contains early support for null properties, keypath collection queries (count/min/max/sum/avg), a new RealmCollectionType protocol in Swift, error handling in writes, and a fistful of bug fixes!

We encourage you to try out this version in your local development environments. Although we’ve taken every precaution to test this new file format and the migration process, we’re relying on your feedback to catch any possible issues before we cut an official release.

After a period of beta-testing, these features will be made available as part of an official 0.96.0 release.

Null Support

This version adds support for null values for all property types.

Objective-C

NSString *, NSDate *, NSData * now allow nil by default. You can disallow setting a property to nil by overriding the +requiredProperties class method and including the names of the properties which you want to disallow nil for. Accessing a Realm file created with a previous version will automatically convert these properties to nullable in the file itself, unless explicitly marked not to do so in +requiredProperties.

Optional numbers can be stored using an NSNumber * property which is tagged with the type of the number. You can use NSNumber<RLMInt> *, NSNumber<RLMBool> *, NSNumber<RLMFloat> *, and NSNumber<RLMDouble> *.

@interface OptionalTypes : RLMObject
@property NSString *optionalString;
@property NSString *requiredString;
@property NSData *optionalData;
@property NSDate *optionalDate;
@property NSNumber<RLMInt> *optionalInt;
@property NSNumber<RLMBool> *optionalBool;
@property NSNumber<RLMFloat> *optionalFloat;
@property NSNumber<RLMDouble> *optionalDouble;
@end
@implementation OptionalTypes
+ (NSArray *)requiredProperties {
    return @[@"requiredString"];
}
@end

Swift

String, NSDate and NSData properties work as you’d expect them to and can either be optional or non-optional. Unfortunately, we’re unable to directly support optional numeric types (see #2147), so you have to wrap the types in RealmOptional. For example:

class OptionalTypes: Object {
    dynamic var string: String? = "B"
    dynamic var data: NSData? = "C".dataUsingEncoding(NSUTF8StringEncoding)
    dynamic var date: NSDate? = NSDate(timeIntervalSince1970: 10)
    let int = RealmOptional<Int>(1)
    let float = RealmOptional<Float>(2.2)
    let double = RealmOptional<Double>(3.3)
    let bool = RealmOptional<Bool>(true)
    let boolWithNilDefault = RealmOptional<Bool>(nil)
}

As with List properties, RealmOptional properties should always be declared with let and not be declared dynamic. The actual value of the RealmOptional is read from and written to the value property.

Automatic Conversion

Realm files opened with this version will be automatically converted to the new file format on first access, even when only accessed in a read transaction. This automatic conversion will perform the following operations:

  1. All indexes will be recreated (only applies to ints and strings).
  2. All NSString, NSDate, and NSData properties are converted to nullable, unless marked as required in +requiredProperties.
  3. The new format version number will be written to the file.

Since this writes to the file, Realm files created with a previous version of Realm won’t be able to be read with this new version. If you’re bundling a Realm file in your app, it will have to be updated to use this new file format.

Note that this format conversion is irreversible.

Keypath Collection Queries

Keypath collection queries using @count, @min, @max, @sum and @avg are now supported on RLMArray/List properties. See our handy NSPredicate Cheatsheet for more details on how to use these.

RealmCollectionType

Editor’s Note: RealmCollectionType is deprecated and has been replaced by RealmCollection. The section below is retained in its original state for posterity, but you should see here for the latest on `RealmCollection`.

Users of Realm Objective-C have had the ability to represent both RLMArray and RLMResults using their shared protocol (RLMCollection) for a long time. We’re now reflecting that protocol in Swift, while expanding what it can do.

Functionality common to both List and Results is now declared in a RealmCollectionType protocol that both types conform to. A type-erased wrapper is also provided, so Swift can store a reference to the underlying collection despite its layout being different:

class ViewController: UIViewController {
    var collection: AnyRealmCollection

    init(collection: RealmCollectionType) {
        super.init()
        self.collection = AnyRealmCollection(collection)
    }
}

Improved Error Handling

In current versions of Realm committing a write transaction on a severely space-constrained device would cause Realm to crash. Thankfully, Realm’s crash safety would prevent existing data from being corrupted, but this wasn’t exactly a solid user experience.

Now committing write transactions via commitWrite / commitWriteTransaction and write / transactionWithBlock optionally allow for handling errors when the disk is out of space.

Minor Enhancements

  • Added isEmpty property on RLMRealm/Realm to indicate if it contains any objects.

Bug Fixes

  • Fix assertion failure when inserting NSData between 8MB and 16MB in size.
  • Fix assertion failure when rolling back a migration which removed an object link or RLMArray/List property.
  • Add the path of the file being opened to file open errors.
  • Fix crashes when the first Realm opened uses a class subset and later Realms opened do not.
  • Fix inconsistent errors when Object(value: ...) is used to initialize the default value of a property of an Object subclass.
  • Throw an exception when a class subset has objects with array or object properties of a type that are not part of the class subset.

Again, we encourage you to try out this version in your local development environments. Although we’ve taken every precaution to test this new file format and the migration process, we’re relying on your feedback to catch any possible issues before we cut an official release.

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.95.1

by /

We just released version 0.95.1 of Realm Objective-C and Realm Swift.

New Technologies

Now that Xcode 7 is officially out, all the new technologies that it brings are now officially supported: Swift 2.0, iOS 9, watchOS 2 & OS X 10.11.

We’ve been testing and building for these new technologies for months now, so you should feel confident that Realm will run smoother than ever with this release.

We’ll still be supporting Swift 1.2 via the swift-1.2 branch for some time to come, but we encourage you to move to Swift 2 as soon as possible.

Bug Fixes

Along with support for new Apple technologies, we’ve included a number of bug fixes in this release:

  • We added missing KVO handling for moving and exchanging objects in RLMArray and List.
  • We fixed a crash due to race condition in RLMRealmConfiguration where the default configuration was in the process of being copied in one thread, while released in another.
  • We fixed a crash when a migration which removed an object or array property is rolled back due to an error.
  • Setting the primary key property on persisted RLMObjects / Objects via subscripting or key-value coding will cause an exception to be thrown.

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

Groupon

by /

Groupon App Screenshots

At the time of this writing, many apps on the iOS App Store are powered by Realm. A lot of them are brand new and still relatively small, while some have already reached critical success, and others even exceeded that, earning Apple’s coveted ‘Essentials’ badge.

This week, we’re proud to recognize a very prominent app, straight from Apple’s “Essentials” collection: Groupon!

If you haven’t heard of it before, Groupon is a global service aimed at connecting users and merchants in the same area, letting users take advantage of special discounts and deals of merchants around them. Merchants can advertise their products or services as separate discounted ‘coupons’ via the Groupon app that users can simply buy directly in the app. These coupons are then saved in the user’s account, and may be redeemed for their full value from the merchant at a later date.

The model is both amazingly simple and effective. The discounted prices aren’t trivial, with certain products and services being advertised for 50% off or more. Even without buying anything from the app, it’s a great advertising channel for merchants to let users find out about them!

Of course, if you hadn’t already guessed, we’re absolutely thrilled that the Groupon apps are powered by Realm. Groupon has been an early adopter of Realm, and we couldn’t be happier that it fit their scale requirements well.

Also, while we have the chance, special recognition should also be given to Groupon for letting the Swift Language Users Group meetup periodically host events at their incredibly beautiful office in Palo Alto.

From everyone at Realm, we thank Groupon for leveraging our tech in their fantastic, worldwide service (as well as allowing the use of their offices)! We wish them the very best in their endeavors, and will continue to support them in the future!

Read more

Realm Objective-C & Swift 0.95

by /

We just released version 0.95 of Realm Objective-C and Realm Swift.

Key-Value Observing

Realm objects are now Key-Value Observing compliant for most properties. Using KVO on standalone Realm objects has always worked as normal, but on persisted objects you would only get notifications for changes made directly to the observed object, and not changes made on other threads or via other accessors for the same object. This has now been fixed, and observing properties of persisted objects will now work correctly regardless of how they’re changed. In addition, you can now observe the invalidated property of persisted objects to be notified of when the object is deleted from the Realm.

See the docs for Objective-C or Swift for more information on KVO with Realm, or check out our ReactKit or ReactiveCocoa examples showing them used with Realm.

Realm Configuration

We’ve reworked how you open and configure Realm instances. Rather than a mixture of class methods that register options for a path and overloaded initializers, all options are stored in a Realm configuration object (RLMRealmConfiguration in Objective-C and Realm.Configuration in Swift). This configuration object can be safely passed around between threads to easily create Realm instances for each thread, or can be set as the default configuration to use.

RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];

// Set either the path for the file or the identifer for an in-memory Realm
// By default config.path will be the Default realm path
config.path = "";
// config.inMemoryIdentifier = @"MyInMemoryRealm";

// Encryption keys, schema versions and migration blocks are now all set on the
// config object rather than registered for a path:
config.encryptionKey = GetKeyFromKeychain();
config.schemaVersion = 10;
config.migrationBlock = ^(RLMMigration *migration, uint64_t oldSchemaVersion) {
    // do stuff
};

// New feature: a Realm configuration can explicitly list which object classes
// should be stored in the Realm, rather than always including every `RLMObject`
// and `Object` subclass.
config.objectClasses = @[Dog.class, Person.class];

// Either use the configuration to open a Realm:
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];

// Or set the configuration used for the default Realm:
[RLMRealmConfiguration setDefaultConfiguration:config];

The following APIs have been deprecated in favor of the new RLMRealmConfiguration class in Realm Objective-C:

Deprecated API New API
+[RLMRealm realmWithPath:readOnly:error:] +[RLMRealm realmWithConfiguration:error:]
+[RLMRealm realmWithPath:encryptionKey:readOnly:error:] +[RLMRealm realmWithConfiguration:error:]
+[RLMRealm setEncryptionKey:forRealmsAtPath:] -[RLMRealmConfiguration setEncryptionKey:]
+[RLMRealm inMemoryRealmWithIdentifier:] +[RLMRealm realmWithConfiguration:error:]
+[RLMRealm defaultRealmPath] +[RLMRealmConfiguration defaultConfiguration]
+[RLMRealm setDefaultRealmPath:] +[RLMRealmConfiguration setDefaultConfiguration:]
+[RLMRealm setDefaultRealmSchemaVersion:withMigrationBlock] RLMRealmConfiguration.schemaVersion and RLMRealmConfiguration.migrationBlock
+[RLMRealm setSchemaVersion:forRealmAtPath:withMigrationBlock:] RLMRealmConfiguration.schemaVersion and RLMRealmConfiguration.migrationBlock
+[RLMRealm migrateRealmAtPath:] +[RLMRealm migrateRealm:]
+[RLMRealm migrateRealmAtPath:encryptionKey:] +[RLMRealm migrateRealm:]

The following APIs have been deprecated in favor of the new Realm.Configuration struct in Realm Swift for Swift 1.2:

Deprecated API New API
Realm.defaultPath Realm.Configuration.defaultConfiguration
Realm(path:readOnly:encryptionKey:error:) Realm(configuration:error:)
Realm(inMemoryIdentifier:) Realm(configuration:error:)
Realm.setEncryptionKey(:forPath:) Realm(configuration:error:)
setDefaultRealmSchemaVersion(schemaVersion:migrationBlock:) Realm.Configuration.schemaVersion and Realm.Configuration.migrationBlock
setSchemaVersion(schemaVersion:realmPath:migrationBlock:) Realm.Configuration.schemaVersion and Realm.Configuration.migrationBlock
migrateRealm(path:encryptionKey:) migrateRealm(configuration:)

The following APIs have been deprecated in favor of the new Realm.Configuration struct in Realm Swift for Swift 2.0:

Deprecated API New API
Realm.defaultPath Realm.Configuration.defaultConfiguration
Realm(path:readOnly:encryptionKey:) throws Realm(configuration:) throws
Realm(inMemoryIdentifier:) Realm(configuration:) throws
Realm.setEncryptionKey(:forPath:) Realm(configuration:) throws
setDefaultRealmSchemaVersion(schemaVersion:migrationBlock:) Realm.Configuration.schemaVersion and Realm.Configuration.migrationBlock
setSchemaVersion(schemaVersion:realmPath:migrationBlock:) Realm.Configuration.schemaVersion and Realm.Configuration.migrationBlock
migrateRealm(path:encryptionKey:) migrateRealm(configuration:)

The old methods will be removed entirely in a future version.

Class Subsets

The new Realm configuration API also adds the ability to specify what object classes you want to be stored in a given Realm file, rather than having it be all RLMObject and RealmSwift.Object subclasses. This is done by setting the objectClasses property to an array of the class objects you want to be persisted in the Realm.

RLMRealmConfiguration *config = [[RLMRealmConfiguration alloc] init];
config.objectClasses = @[MyClass.class, MyOtherClass.class];
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:nil];
var config = Realm.Configuration()
config.objectTypes = [MyClass.self, MyOtherClass.self]
let realm = Realm(configuration: config)

The main benefit of this is that it makes it much easier to have independent components in your application which use Realm. In previous versions, making a change to an object class would require bumping the schema version for all Realms you open, even ones which would never actually be used to store objects of that type.

Explicitly listing the classes to include also lets Realm skip scanning for RLMObject and RealmSwift.Object subclasses. This can be important for App Extensions. Iterating over all of the registered classes in a process eagerly loads all linked bundles, which in applications linking a large number of frameworks can cause problems with the App Extension memory limit.

Modifying objects while enumerating query results

Previously, Realm’s collection types matched the behavior of the Foundation collections and forbade modifying the collection while enumerating it with for..in. Unfortunately, this combined confusingly with Realm’s live-updating query results. A simple loop like for employee in realm.objects(Employee).filter("hired = false") { employee.hired = true } didn’t actually work because as soon as you set hired = true that object is removed from the Results that you’re enumerating.

To fix this, we’ve made it so that enumerating a Realm collection always enumerates the objects which are in the collection at the beginning of the enumeration. This means that you can freely add or remove items from an RLMArray/List while enumerating it, or modify the values of objects in the Realm while enumerating an RLMResults/Results. For example, you can now safely do the following and have it work as desired:

let realm = Realm()
let dogs = realm.objects(Dog)
realm.write {
  for dog in dogs {
    if dog.age > 10 {
      realm.delete(dog)
    }
    else {
      dog.age += 1
    }
  }
}

Performance Improvements

Adding objects to a Realm via the Swift API has been greatly optimized to bring it in line with the Objective-C API.


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

Dubsmash

by /

Dubsmash App Screenshots

Wow. Just wow. This app. The power level of this app. This is amazing.

This week, we’re extremely thrilled to bring you a feature on Dubsmash, the social selfie app that lets you dub yourself to famous sound clips by Mobile Motion!

In case you somehow missed it on the front page of your iPhone’s App Store page, Dubsmash is an app that lets you record a video of yourself dubbing, or acting in sync to a wide range of available sound clips; mostly famous movie quotes. Once you’ve created one of these dubbed video masterpieces, Dubsmash makes it seamless to publish it anywhere on the web; on web sites, on your social feed, or even directly to friends. The app also lets you manage your previous videos, as well as submit your own dubbed sound clips for other users to use. All of this is in a very simple, clean user interface that takes mere seconds to learn.

The uptake of Dubsmash has been absolutely staggering. Within a week of its launch, it had hit the coveted #1 position of free apps on the App Store in its home region of Germany, and later went on to achieve the #1 position in over 40 other App Store regions after that! And no, that isn’t simply #1 in one of the App Store’s category filters, that’s #1 overall, beating out apps such as Facebook and YouTube!

Finally, if you hadn’t already guessed it from this post, both the iOS and Android apps for Dubsmash are taking full advantage of Realm! We’re absolutely over the moon that our technology was able to contribute to Dubsmash’s efforts, and congratulate them on the ridiculous achievements they’ve reached with both of these apps. We thank everyone at Mobile Motion for choosing to go with Realm, and wish them all the very best in their future of Dubsmash!

Read more

Chris Kurose joins Realm

by /

We’re delighted to announce that Chris Kurose has joined Realm and will be helping us in San Francisco, California!

Chris Kurose

Chris comes from a filmmaking background, and after shooting most of the past year’s SLUG meetups, is joining the marketing team to expand Realm’s video production and manage content publishing. Besides his love of all things camera-related and an eye for composition, he brings a storytelling perspective that he hopes to use to help create better and better content!

Get in touch with Chris.

Welcome to Realm, Chris!

We’re hiring!

If you’d like to work with Chris & the rest of us, take a look at our jobs page.

Read more

Cymera - Collage & Filters

by /

Cymera App Screenshots

Following on with the photography trend we started last week, our quest for this week’s App of the Week took us farther than we’ve been before; all the way to Korea! This week, the crew at Realm is very happy to put our official support behind the iOS and Android app of Cymera, the selfie social networking service by SK Communications Co., Ltd in Korea.

When Apple first announced the iPhone 4 with its front-facing camera, it’s quite possible they didn’t quite realize the magnitude of just what sort of powerful emotions they were enabling. Us humans are a passionate bunch; we love expressing ourselves and we love seeing our friends’ expressions. Because of this passion, posting pictures of yourself online (in case you’ve been living under a rock, more commonly referred to as a “selfie”) has become a very popular social networking content medium.

And it turns out that a lot of users agree. Cymera has proudly announced that they now have over one hundred and fifty million users! Holy Guacamole, Batman!

Getting started on Cymera is VERY simple. You simply download the app, make an account (Which is VERY quick thanks to Facebook and Google+ integration), and away you go! Right off the bat, you can start posting your own photos, or simply browse some the publicly joinable community galleries. There is a slide-out menu from the left that provides all of the major app navigation, and the tab buttons at the bottom make it very fast to post photos.

Speaking of which, posting photos via the Cymera app is absolutely amazing. If there’s an image manipulation feature out there, Cymera has it. Period. You can change the color grade, perform distortions via facial detection (like enhancing a smile!), add tilt shift, and if all that wasn’t enough, on top of that, you can then choose to apply stickers from an absolutely vast sticker collection; all completely free!

Cymera is an amazing service. With a simple concept, features that enable a truly ridiculous amount of personal freedom and expression, as well as an absolutely thriving userbase, it is a very impressive implementation. All of us at Realm are humbled that our technology was able to help enable and empower a service of this magnitude and we wish everyone at SK Communications the very best of luck in their endeavor!

Read more

#Photos - A simple, powerful photo manager

by /

#Photos App Screenshots

This week, we’re thrilled to feature another beautifully designed app that’s using Realm for an absolutely excellent cause.

Apple tells us time and time again that the iPhone is one of the best cameras out there. It’s a camera we constantly carry with us, and at the drop of a dime it’s very easy to quickly pull it out and snap a photo. It’s no wonder Flickr reports that more photos are uploaded to their service by iPhones than any other camera!

With all that said and done, sadly the experience of managing all these photos on an iPhone isn’t as great as it could be. Photos are simply dumped in one massive scrolling view called the “Camera Roll”. More sorting options were added in iOS 7, but it remains quite a cumbersome thing to manage, and you still have to manually navigate a large collection of photos. Sadness, and frustration.

Enter #Photos!

Elegantly designed and very thoughtfully crafted, #Photos is an app developed by beyondf that helps you manage all of the photos on your iOS device. Unlike the system Photos app, #Photos brings order to your chaotic mess by extracting the timestamp from each photo, and it breaks up the list into time blocks of your choosing (months or days), visually separating them in the list. Additionally, by simply swiping to the left, a menu appears that makes it possible to instantly jump between batches of photos taken in specific months, making it far easier to navigate your photo collection than the system Photos app. On top of that, swiping to the left reveals a menu that will let you edit your photo albums as well. Again, much faster than the standard system app.

If all that wasn’t enough, when actually viewing your images, #Photos provides an absolute plethora of features to extend what you can do with your photos. You can share them with the standard iOS share sheet, send them directly to another app, add memos or tags, or even — perhaps most importantly — directly view all of the EXIF metadata embedded in that photo, including an embedded map of where the photo was taken. The level of functionality that #Photos provides is mind-blowing.

#Photos is awesome. This is how the default Photos app should have worked from the start. Apple should be watching this and taking notes for iOS 10. All of us at Realm are incredibly happy to see our technology contribute to an app that will help people every day with one of the most common and usually frustrating tasks on the iOS platform. We wish them all the best, and we can’t wait to see the app grow from this point onwards!

Read more

Realm Objective-C & Swift 0.94

by /

We just pushed version 0.94 of Realm Objective-C and Realm Swift. Along with many bug fixes and performance enhancements, this release improves support for Xcode 7 Beta 4, watchOS, Swift 2.0, Objective-C generics, and bitcode.

We’ve also exposed the ability to swap & move objects in an RLMArray or a List.

Finally, to allow us to make more informed product decisions moving forward, this release introduces the collection of development analytics.

Read on for an overview of all the changes included in 0.94.

Performance Improvements

RLMRealm notification listener threads should now consume less memory than ever before. This is part of an ongoing effort to reduce the memory footprint of apps using Realm.

Filtering and sorting results is now done lazily, which will further reduce the overhead of chaining queries together.

Support for New Apple Features

Nullability

The Objective-C API has been fully annotated for nullability semantics to provide enhanced compiler warnings and bridging to Swift. Here’s what that looks like when using Realm Objective-C from Swift:

// Before nullability annotations
class func ignoredProperties() -> [AnyObject]!

// After nullability annotations
class func ignoredProperties() -> [AnyObject]

Generics

RLMResults and RLMArrays now support native Objective-C generics if available (Xcode 7 or later), which should help catch more type errors at compile-time.

Here’s how you can make use of these new generics:

// Define a Company model with a generic array of employees
@interface Company : RLMObject
@property RLMArray<Employee *><Employee> *employees;
@end

// Retrieve all employees and store in a generic RLMResults
RLMResults<Employee *> *allEmployees = [Employee allObjects];

Here’s what the different components of the RLMArray property definition mean and why they are useful:

  • RLMArray: The property type.
  • <Object *>: The generic specialization. This helps prevent using the array with the wrong object type at compile-time.
  • <Object>: The protocol this RLMArray conforms to. This enables Realm to know how to specialize the schema of this model at runtime.

Objective-C generics are unfortunately type-erased, which means Realm can’t determine the specialization at runtime. This is why the protocol conformance declaration is still necessary, even though it’s unsightly. We apologize for the angle-bracket blindness!

Bitcode, watchOS & Swift 2.0

iOS & watchOS builds of Realm now include bitcode. Our zip archives distributed via this website, GitHub Releases, and Carthage now include builds for all these configurations:

  • Objective-C / Swift 1.2 / Swift 2.0 Beta 4
  • Mac / iOS / watchOS

Yikes! And people say Android is fragmented!

realm-cocoa-deal-with-it

Other Enhancements

  • The exceptions thrown in getters and setters are more informative.
  • Add -[RLMArray exchangeObjectAtIndex:withObjectAtIndex:] and List.swap(_:_:) to allow exchanging the location of two objects in the given RLMArray / List.
  • Add -[RLMArray moveObjectAtIndex:toIndex:] and List.move(from:to:) to allow moving objects in the given RLMArray / List.

Bugfixes

  • Processes crashing due to an uncaught exception inside a write transaction will
  • Fix incorrect results when querying for < or <= on ints that require 64 bits to represent with a CPU that supports SSE 4.2.
  • An exception will no longer be thrown when attempting to reset the schema version or encryption key on an open Realm to the current value.
  • Date properties on 32 bit devices will retain 64 bit second precision.
  • Wrap calls to the block passed to enumerate in an autoreleasepool to reduce memory growth when migrating a large amount of objects.
  • In-memory realms no longer write to the Documents directory on iOS or Application Support on OS X.

Analytics

Realm now asynchronously submits build information to Realm if running in an iOS Simulator or on OS X if a debugger is attached. Nothing is done when running on a physical iOS / watchOS device or if a debugger is not attached.

To be clear: this does not run when your app is in production or on your end-user’s devices; it will only run in the simulator or when a debugger is attached.

For more information, see PR #2276 which introduced this change.


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