How to Load Thousands Records to Realm Correctly

How to load thousands records to Realm correctly?

Try the way in official demo to save large amounts of data:

DispatchQueue(label: "background").async {
autoreleasepool {
// Get realm and table instances for this thread
let realm = try! Realm()

// Break up the writing blocks into smaller portions
// by starting a new transaction
for idx1 in 0..<1000 {
realm.beginWrite()

// Add row via dictionary. Property order is ignored.
for idx2 in 0..<1000 {
realm.create(Person.self, value: [
"name": "\(idx1)",
"birthdate": Date(timeIntervalSince1970: TimeInterval(idx2))
])
}

// Commit the write transaction
// to make this data available to other threads
try! realm.commitWrite()
}
}
}

How to add 1 milion items in Realm correctly?

You have to be aware that SQLite and Realm are two very different things. Realm is an object store and you are creating a lot of objects in the code shown above. Depending on your model class and the number of rows/objects, you will often see that Realm is a bit slower on inserts. To do a fair comparison, you could compare Realm with one of the many excellent ORMs out there.

Said that, Realm offers a low-level interface (io.realm.internal). I wouldn't recommend you to use it as it is currently undocumented. Your example would look like this:

long numberOfObjects = 1000000;
SharedGroup sharedGroup = new SharedGroup("default.realm");
WriteTransaction writeTransaction = sharedGroup.beginWrite();
Table table = writeTransaction.getTable("class_Product");
table.addEmptyRows(numberOfObjects);
for (int i = 0; i < numberOfObjects; i++) {
table.setLong(0, i, i); // id
table.setString(1, i, "Product_"+i); // name
table.setString(2, i, "SKU__"+i); // sku
table.SetDate(3, i, new Date()); // date
}
writeTransaction.commit();
sharedGroup.close();

You can now compare two table/row oriented data stores, and you will probably find that Realm is a bit faster than SQLite.

At Realm, we have a few ideas on how to get our object interface to run faster, and we hope to be able to implement them in the near future.

How to properly use Realm objects in a UITableViewController?

No cast needed

It seems that casting to Site is not needed. This works fine:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let allSites = Site.allObjects()
let site: AnyObject! = allSites[UInt(indexPath.row)]

cell.textLabel!.text = site.name

println("Site is: \(site.id)")

return cell
}

Seems to be a bug with either Swift or Realm. I'm guessing one of them gets confused when downcasting AnyObject! to something.

Initializing a new instance with correct type

However, if you really need to use the Site model class you can initialize a new RLMObject from the result:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let allSites = Site.allObjects()
let site = Site(object: allSites[UInt(indexPath.row)])

cell.textLabel!.text = site.name

println("Site is: \(site.id)")

return cell
}

First try

It is unfortunate to hear that you are having issues with Realm and Swift. I am by no means a Swift pro, but it looks like you are casting site to an optional, and the result of using the optional cast operator site?.name is also an optional. Hence getting Optional("").

Can you try to see if you have any better luck with the following?

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = self.tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as UITableViewCell
let allSites = Site.allObjects()

if var site = allSites[UInt(indexPath.row)] as? Site {
println("Site is: \(site.name)")
} else {
println("it not castable to Site. It is: \(toString(allSites[UInt(indexPath.row)].dynamicType))")
}

return cell
}

Also, you can use yourObject.dynamicType to get a reference to the objects real class type.

Best of luck

Realm query sometimes return no data

Realm writes are transactional - the transaction is a list of read and write operations that Realm treats as a single indivisible operation.

The reads and writes within the closure {} following the write are part of the transaction; the data is not committed until all of those complete. Transactions are also all or nothing - either all operations complete or none.

Most importantly for this case, transactions are synchronous so adding a callback within the transaction is going to present intermittent results.

Move the callback outside the write transaction

try realm.write {
realm.add(list)
}
completion(.success(()))

It can be illustrated by how we used to write realm transactions:

realm.beginWrite()
write some data

// Commit the write transaction to make this data available to other threads
try! realm.commitWrite() <- data is not valid until after it's been committed

//data has been committed

Swift - How to update objects in bulk with out iterating over a collection of realm objects

Short answer:

It is not possible without iterating over a collection of realm
objects.

Long answer:

The realm is a model class based database. It does not support any
query (Predicates or Filter mostly used to retrieve data with a specific condition) like SQLite means We can't update all record in a single query by using the realm. So answer of your question is pretty
straightforward, Without iterating we can not update the value.

You can improve performance if you want to change the value of some object.

Code:

let persons = realm.objects(Person.self).filter("id IN %@", ids)
try! realm.write {
persons.first?.setValue(true, forKeyPath: "isFirst")
// set each person's planet property to "Earth"
persons.setValue("Earth", forKeyPath: "planet")
}

How to store groups of booleans in Realm for Android?

Option 1: One field per boolean

public class Restaurant extends RealmObject {

private boolean wifi;
private boolean listedOnYelp;

/* getter, setter, etc.*/
}
  • Easy to implement
  • Easy to understand
  • RealmQueries based on the booleans are possible

Option 2: Flag field

64 booleans per long, the masks go from 21, 22, 23 to 264

public class Restaurant extends RealmObject {

private long booleanFlags;

private boolean getFlag(long mask) {
return (booleanFlags & mask) == mask;
}

private void setFlag(long mask, boolean value) {
if (value) {
booleanFlags |= mask;
} else {
booleanFlags &= ~mask;
}
}

public boolean hasWifi() {
return getFlag(1);
}

public void setWifi(boolean hasWifi) {
setFlag(1, hasWifi);
}

public boolean isListedOnYelp() {
return getFlag(2);
}

public boolean isTippingEncouraged() {
return getFlag(4);
}
}
  • Super memory efficient (unless Realm does not do the same in its core)
  • Not so easy to read or understand
  • No RealmQueries based on the booleans

Option 3: Extra class

public class Restaurant extends RealmObject {
/*...*/
}

public class RestaurantPropertyStore extends RealmObject {
private RealmList<Restaurant> restaurantsWithWifi;
private RealmList<Restaurant> restaurantsListedOnYelp;
}
  • Not object-oriented
  • Queries on one boolean at a time are possible

Option 1 is the object-oriented, Java-like and Realm-like way

Option 2 is the C, C++ way

Option 3 is the SQL, RDBMS way



Related Topics



Leave a reply



Submit