# New Realm Cocoa Data Types

In this blog post we will discover the new data types that Realm has to offer.

Over the past year we have worked hard to bring three new datatypes to the Realm SDK: `MutableSet`, `Map`, and `AnyRealmValue`.

> **Build better mobile apps with Atlas Device Sync**: Atlas Device Sync is a fully-managed mobile backend-as-a-service. Leverage out-of-the-box infrastructure, data synchronization capabilities, built-in network handling, and much more to quickly launch enterprise-grade mobile apps. Get started now by build: Deploy Sample for Free!

## MutableSet

`MutableSet` allows you to store a collection of unique values in an unordered fashion. This is different to `List` which allows you to store duplicates and persist the order of items.

`MutableSet` has some methods that many will find useful for data manipulation and storage:

- `Intersect`
    - Gets the common items between two `MutableSet`s.
- `Union`
    - Combines elements from two `MutableSet`s, removing any duplicates.
- `Subtract`
    - Removes elements from one `MutableSet` that are present in another given `MutableSet`.
- `isSubset`
    - Checks to see if the elements in a `MutableSet` are children of a given super `MutableSet`.

So why would you use a `MutableSet` over a `List`?
- You require a distinct collection of elements.
- You do not rely on the order of items.
- You need to perform mathematical operations such as `Intersect`, `Union`, and `Subtract`.
- You need to test for membership in other Set collections using `isSubset` or `intersects`.

### Practical example

Using our Movie object, we want to store and sync certain properties that will never contain duplicates and we don't care about ordering. Let's take a look below:

```swift
class Movie: Object, ObjectKeyIdentifiable {
   @Persisted(primaryKey: true) var _id: ObjectId
   @Persisted var _partitionKey: String
   // we will want to keep the order of the cast, so we will use a `List`
   @Persisted var cast: List
   @Persisted var countries: MutableSet
   @Persisted var genres: MutableSet
   @Persisted var languages: MutableSet
   @Persisted var writers: MutableSet
}
```

Straight away you can see the use case, we never want to have duplicate elements in the `countries`, `genres`, `languages`, and `writers` collections, nor do we care about their stored order. `MutableSet` does support sorting so you do have the ability to rearrange the order at runtime, but you can't persist the order.

You query a `MutableSet` the same way you would with List:
```swift
let danishMovies = realm.objects(Movie.self).filter("'Danish' IN languages")
```
### Under the hood

`MutableSet` is based on the `NSSet` type found in Foundation. From the highest level we mirror the `NSMutableSet / Set API` on `RLMSet / MutableSet`. 

When a property is unmanaged the underlying storage type is deferred to `NSMutableSet`.

## Map

Our new `Map` data type is a Key-Value store collection type. It is similar to Foundation's `Dictionary` and shares the same call semantics. You use a `Map` when you are unsure of a schema and need to store data in a structureless fashion. NOTE: You should not use `Map` over an `Object` where a schema is known.

### Practical example

```swift
@Persisted phoneNumbers: Map

phoneNumbers"Charlie"] = "+353 86 123456789"
let charliesNumber = phoneNumbers["Charlie"] // "+353 86 123456789"
```

`Map` also supports aggregate functions so you can easily calculate data:

```swift
@Persisted testScores: Map

testScores["Julio"] = 95
testScores["Maria"] = 95
testScores["John"] = 70

let averageScore = testScores.avg()
```

As well as filtering with NSPredicate:

```swift
@Persisted dogMap: Map

let spaniels = dogMap.filter(NSPredicate("breed = 'Spaniel'")) // Returns `Results`

```

You can observe a `Map` just like the other collection types:

```swift
let token = map.observe(on: queue) { change in
    switch change {
    case .initial(let map):
        ...
    case let .update(map, deletions: deletions, insertions: insertions, modifications: modifications):
        // `deletions`, `insertions` and `modifications` contain the modified keys in the Map
        ...
    case .error(let error):
...
    }
}
```

Combine is also supported for observation:

```swift
cancellable = map.changesetPublisher
    .sink { change in
        ...
    }
```

### Under the hood

`Map` is based on the `NSDictionary` type found in Foundation. From the highest level, we mirror the `NSMutableDictionary / Dictionary API` on `RLMDictionary / Map`. 

When a property is unmanaged the underlying storage type is deferred to `NSMutableDictionary`.

## AnyRealmValue

Last but not least, a datatype we are very excited about, `AnyRealmValue`. No this is not another collection type but one that allows you to store various different types of data under one property. Think of it like `Any` or `AnyObject` in Swift or a union in C.

To better understand how to use `AnyRealmValue`, let's see some practical examples.

Let's say we have a Settings class which uses a `Map` for storing the user preferences, because the types of references we want to store are changing all the time, we are certain that this is schemaless for now:

```swift
class Settings: Object {
   @Persisted(primaryKey: true) var _id: ObjectId
   @Persisted var _partitionKey: String?
   @Persisted var misc: Map
}
```

Usage:

```swift
misc["lastScreen"] = .string("home")
misc["lastOpened"] = .date(.now)

// To unwrap the values

if case let .string(lastScreen) = misc["lastScreen"] {
    print(lastScreen) // "home"
}
```

Here we can store different variants of the value, so depending on the need of your application, you may find it useful to be able to switch between different types.

### Under the hood

We don't use any Foundation types for storing `AnyRealmValue`. Instead the `AnyRealmValue` enum is converted to the ObjectiveC representation of the stored type. This is any type that conforms to `RLMValue`. You can see how that works [here.

## Conclusion

I hope you found this insightful and have some great ideas with what to do with these data types! All of these new data types are fully compatible with MongoDB Realm Sync too, and are available in Objective-C as well as Swift. We will follow up with another post and presentation on data modelling with Realm soon.

Links to documentation:

- MutableSet
- Map
- AnyRealmValue