Realm Swift: Always Put Nil Values Last in Sort

Realm Swift: always put nil values last in sort

Realm doesn't support custom sorting of Results other than what the Results.sorted(_:ascending:) method gives you. But you can compose this yourself fairly easily by concatenating two queries, maybe even exposing that through a computed property:

var results: [MyModel] {
let sorted = realm.objects(MyModel).sorted("...", ascending: true)
return sorted.filter("optionalProperty != nil") +
sorted.filter("optionalProperty == nil")
}

How quickly can Realm return sorted data?

At this time it appears that Realm sorts data when it is accessed rather than when it is written, and there is not a way to have Realm sort data at write time. This means that accessing sorted data scales with the number of documents in the database rather than the number of documents being accessed.

The actual time taken to access the data varies by use case and platform.

Realm order ascending by date always fails

sorted(_:, ascending:) doesn't modify a Results<T>. You attempt to sort the results in tableView(tableView:, cellForRowAtIndexPath:), but there is no point doing that. Because you ignored the return value.

let eventakiaSaved = realm.objects(eventsNewSaved2)
eventakiaSaved.sorted("realmgettime", ascending: true)

Above code should be like the following:

var eventakiaSaved = realm.objects(eventsNewSaved2)
var eventakiaSaved = eventakiaSaved.sorted("realmgettime", ascending: true)

More better way is chaining method.

let eventakiaSaved = realm.objects(eventsNewSaved2)
.sorted("realmgettime", ascending: true)

Moreover, Results instances are live, auto-updating views into the underlying data, which means results never have to be re-fetched.

https://realm.io/docs/swift/latest/#auto-updating-results

So you don't need to re-fetch every time for the same query. Keep the results once, just use it everywhere as long as in the same thread.
The recommended way is like the following:

...
var eventodos: Results<eventsNewSaved2>? // Keep results as a model
...

override func viewDidLoad() {
super.viewDidLoad()

let realm = try! Realm()
eventodos = realm
.objects(eventsNewSaved2)
.sorted("realmgettime", ascending: true) // Query only once
}

...

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return eventodoscount?.count ?? 0
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("savedCell", forIndexPath: indexPath) as! locationEventsTableViewCell

let task = eventodos[indexPath.row]

cell.eventTitle?.text = "\(task.realmtitle)"
cell.eventDate.text = "\(task.realmdate)"
cell.eventAttends.text = "\(task.realmattends)"

let imageDef : UIImage = UIImage(named: "noimage")!

if task.realmeventCover == "No Image Available" {
cell.eventImage.image = imageDef
} else {
let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT
dispatch_async(dispatch_get_global_queue(priority, 0)) {
let realm = try! Realm()
// Need re-fetch because this within sub-thread
let eventakiaSaved = realm
.objects(eventsNewSaved2)
.eventakiaSaved.sorted("realmgettime", ascending: true)

let task = eventakiaSaved[indexPath.row]
let url = NSURL(string: task.realmeventCover)

if url != nil {
let data = NSData(contentsOfURL: url!)
dispatch_async(dispatch_get_main_queue()) {
cell.eventImage.image = UIImage(data: data!)
}
} else {
cell.eventImage.image = imageDef
}
}
}

return cell
}

How to handle null value in realm.io?

Null is now fully supported.

OLD answer:

Supporting nil/NULL is on the roadmap.
Until then there are two workarounds:

  1. Add a separate property to indicate if your property is nil.

    @interface IntObject : RLMObject
    @property NSInteger myProp;
    @property boolean myPropIsNil;
    @end
  2. Wrap your property in an object:

    Object properties (links), can be nil though. So if you need a nullable int property, for example, you can wrap it in a new Realm model, like this:

    @interface IntObject : RLMObject
    @property NSInteger myProp;
    @end

    Then anytime you want to have an optional "int" property in your models, you can write this:

    @interface MyModel : RLMObject
    @property IntObject *optionalMyProp;
    @end


Related Topics



Leave a reply



Submit