0

I'm trying to load simple data stored in realm into uitableview in swift. But I don't want realm to load all of it at once, instead I want it to load chunk by chunk, everytime the user reaches the bottom of the table.

I've gone through all the basic documentation and several questions and discussions on stackoverflow and github, but nothing seems to be helpful.

This is my object -

class Numbers:Object {
    @objc dynamic var numb = ""
    @objc dynamic var name = ""
    override class func primaryKey() -> String? {
        return "numb"
    }
}

And this is the very basic code -

override func viewDidLoad() {
    super.viewDidLoad()

    let realm = try! Realm()
    try! realm.write {
        let info = realm.objects(Numbers.self)
    }
}

Now the following line -

    let info = realm.objects(Numbers.self)

It will load all the data stored in the realm table at once, but I want to load only some of it at once.

Dávid Pásztor
  • 51,403
  • 9
  • 85
  • 116
robben
  • 637
  • 1
  • 7
  • 14
  • Realm loads it's object lazily so it does that by design. *All queries (including queries and property access) are lazy in Realm. Data is only read when the properties are accessed.* What kind of issue are you encountering? – Jay Jul 12 '19 at 16:38

1 Answers1

3

It's not clear why you want to do this, but it is probably because you are worried fetching all the Number objects is going to be too costly from a memory perspective. If this is your concern it needn't be. Realm loads all its objects lazily. What that means is when you 'fetch' all the Number objects from realm using let info = realm.objects(Numbers.self) none of those objects are actually accessed until they are used. As an example: if the Number objects are displayed in a tableview, the first time the object will actually be read is when it is drawn in the tableview cell, and since a tableview only draws a subset of cells (the ones that need to be immediately visible for scrolling purposes) it means only a subset of those Number objects will get read.

If you really do need to access a smaller set of your number objects you can do the following. This is taken from the Swift realm docs (section: Limiting results).

let info = try! Realm().objects(Numbers.self)
for i in 0..<5 {
    let number = info[i]
    // ...use number as you need to.
}
thecloud_of_unknowing
  • 1,103
  • 14
  • 23
  • Fantastic answer (which sounds strangely like my comment, lol) until the code. That code overwrites limitedSetOfNumbers repeatedly with each Realm object. So the end result is that limitedSetOfNumbers will only contain the last object indexed from the results, and will only be valid within that for loop. I would fix it but I don't know what the intention was. Can you update? – Jay Jul 13 '19 at 14:17
  • @Jay Thx. Have edited it to make the intension clearer. – thecloud_of_unknowing Jul 13 '19 at 14:33
  • So you're saying that when I run the ".objects(Numbers.self)" command, the data isn't actually fetched, hence no resources are taken. It's only when I write a command such as "data.append(res)" or something, the data is actually fetched and resources gets eaten up? Did I get it right? Memory use is my main concern here. Although I know, Realm is very fast and efficient, but I'm trying to make it better by fetching data in batches. – robben Jul 15 '19 at 17:44
  • @Robin Yes, that is correct. Please take a look at [Swift Properties](https://docs.swift.org/swift-book/LanguageGuide/Properties.html) in the *Lazy Stored Properties* section. Also see [this question](https://stackoverflow.com/questions/40694691/what-is-the-advantage-of-a-lazy-var-in-swift) and – Jay Jul 15 '19 at 18:53