Is running a query the only way of re-initializing a Realm Object for use in a different thread? Is there no way to somehow grab some kind of reference for use with Realm, so that the query doesn't have to be completely from scratch? It would be nice to have some kind of guarantee that the object is for the same record (if it exists and the query for that "ref" is successful), without having to add a primary key just for this one purpose.
This outlines my situation:
func construct(name: String, tokens: [String]) -> Document {
let doc = Document()
let realm = try! Realm()
try! realm.write {
realm.add(doc)
}
DispatchQueue.global(qos: .userInitiated).async {
let realm = try! Realm()
// Some long running task to convert `tokens` into `[Blurb]`
// var blurbs: [Blurb]
// What's the recommended way of re-initing that new `Document`?
// let sameDoc = .....
try! realm.write {
sameDoc.blurbs.append(blurbs)
}
}
return doc
}
Related
I'm using a function to save a realm object to my server. It's called using DataManager().updatedCategory(~InsertCategory~). The implementation goes like this;
func updatedCategory(_ c: Category) {
guard let realm = try? Realm() else { return }
guard let category = realm.object(ofType: Category.self, forPrimaryKey: c.id) else { return }
do {
try realm.write {
c.updatedAt = Date()
}
} catch {
print(error)
}
dbCategories.document(category.id).updateData(category.dictionaryValue())
}
This function is being called after using a realm.write block. It's not in another write block and even the UI is being updated before this is called. I can't figure out what's causing this error, since there's no notification being registered.
I think this
try realm.write {
c.updatedAt = Date()
}
should be
try realm.write {
category.updatedAt = Date()
}
also, this
dbCategories.document(category.id).updateData(category.dictionaryValue())
looks like you're also attempting to write data to realm (?). If so, it needs to be within a write closure. If not, clarify what that does so I can update the answer.
Lastly, this is a bit unclear
This function is being called after using a realm.write block.
You can't embed a write closure within another, and adding observers should occur outside of a write closure as well - the error indicates the observer is being attached within a closure
I want to make an offline translator (dictionary) with swift 4.
I need advice on where to store words with translation.
The words with the translation are now in the dsl format and I search for this particular file, but on average it takes 2-3 seconds to search.
Is it possible to speed up the search? If i put words with translation in core data or realm database, its help or not ?
Realm Swift enables you to efficiently write your app’s model layer in a safe, persisted and fast way. Here’s what it looks like:
// Define your models like regular Swift classes
class Dog: Object {
#objc dynamic var name = ""
#objc dynamic var age = 0
}
class Person: Object {
#objc dynamic var name = ""
#objc dynamic var picture: Data? = nil // optionals supported
let dogs = List<Dog>()
}
// Use them like regular Swift objects
let myDog = Dog()
myDog.name = "Rex"
myDog.age = 1
print("name of dog: \(myDog.name)")
// Get the default Realm
let realm = try! Realm()
// Query Realm for all dogs less than 2 years old
let puppies = realm.objects(Dog.self).filter("age < 2")
puppies.count // => 0 because no dogs have been added to the Realm yet
// Persist your data easily
try! realm.write {
realm.add(myDog)
}
// Queries are updated in realtime
puppies.count // => 1
// Query and update from any thread
DispatchQueue(label: "background").async {
autoreleasepool {
let realm = try! Realm()
let theDog = realm.objects(Dog.self).filter("age == 1").first
try! realm.write {
theDog!.age = 3
}
}
}
For a dictionary app. I'd definitely go with Realm. it uses NSFileProtection and encryption so people won't be able to steal your translation data.
Setup RealmSwift for your projects
I am new to Realm and I am wondering if it is good idea to store primary key of object in View controller and object as stored property.
class VC: ViewController{
public var id:Int!
private var customer:Customer{
get{
return DBO.loadCustomer(for: id)
}
}
}
class DBO{
public static func loadCustomer(for id: Int) -> Customer{
let realm = try! Realm()
return realm.object(ofType: Customer.self, forPrimaryKey: id)!
}
}
I am assuming that this because of this my app will be thread safe, because every time thread will try to access customer it will fetch object from db. But I wonder if this is efficient for single object and array of objects.
As of Realm 2.2 you could use thread-safe references (see here):
Now, you can create thread-safe references for all types that were
previously thread-confined within a Realm, and passing objects between
threads becomes a simple, three-step process:
Initialize a ThreadSafeReference with the thread-confined object.
Pass that ThreadSafeReference to a destination thread or queue.
Resolve this reference on the target Realm by calling
Realm.resolve(_:). Use the returned object as you normally would.
And a code sample, from the source above:
let realm = try! Realm()
let person = Person(name: "Jane") // no primary key required
try! realm.write {
realm.add(person)
}
let personRef = ThreadSafeReference(to: person)
DispatchQueue(label: "com.example.myApp.bg").async {
let realm = try! Realm()
guard let person = realm.resolve(personRef) else {
return // person was deleted
}
try! realm.write {
person.name = "Jane Doe"
}
}
But, your approach should also work fine.
I am new to iOS developing. I try to receive the data which is stored in realm Database but sometimes I get an empty set although I can see the data in RealmBrowser. Often it works, but it is not reliable.
At first I clear the stored data to get sure I am not going to display old data.
After that I insert it to the RealmDatabase and in addition to that I query all stored data to display it in the tableView.
Here is my code (Swift 3):
let realm = try! Realm()
try! realm.write {
// clear all old data stored as fahrt.self
//realm.delete(realm.objects(fahrt.self));
realm.delete(realm.objects(fahrt.self));
let nsArray = try! JSONSerialization.jsonObject(with: data as Data, options: []) as! NSArray;
for eintrag in nsArray{
realm.create(fahrt.self, value: eintrag, update: false)
}
try! realm.commitWrite();
}
DispatchQueue.main.async {
let temp = ui as! DisplayViewController;
let realm = try! Realm()
let result = realm.objects(fahrt.self)
ui.showData(res: result);
// sometimes result is empty , don't know why
}
RealmModel:
class fahrt: Object {
dynamic var id: Int = 0
dynamic var date = ""
dynamic var from_lang: Double = 0.0
dynamic var from_lon: Double = 0.0
dynamic var to_lang: Double = 0.0
dynamic var to_lon: Double = 0.0
override static func primaryKey() -> String? {
return "id"
}
}
First of all, you don't need to include realm.commitWrite() inside a realm.write { } block. realm.commitWrite() is used in conjunction with realm.beginWrite(), but both of these are automatically called inside realm.write { }. :)
Secondly, when you perform a write transaction on a background thread, the changes are automatically exposed on the main thread on the next iteration of the run loop. However, in some cases, when immediately calling code on the main thread after a background write, it's possible this hasn't happened yet. To ensure Realm has the very latest copy of its data on the main thread, you should call realm.refresh() in that dispatch block before you perform the query.
the Problem is, that I can add relationships to my object and it works temporally but realm doesn't save the changes and when I quit the app and restart ist, the relationships are gone.
In the first view I create the main object. Here is the class:
class UserListClass: Object {
dynamic var UserListName = ""
let Medis = List<MediClass>()
override static func primaryKey() -> String? {
return "UserListName"
}
}
And the code how I create the object:
let realm = try! Realm()
let newList = UserListClass ()
newList.UserListName = textField.text!
try! realm.write {
realm.add(newList)
}
This works without problems, and the object I add is also there when I restart the app.
When the user click on Edit it will open the next view:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showUserlistEdit" {
let editViewController = segue.destinationViewController as! MediUserlistEditViewController
editViewController.userlist = userlist
}
}
In the next view the code add selected entries to the list, I tried two versions, but both have the result, that it saves the relationships only for the runtime of the app. When I restart it, they are away.
First try:
let realm = try! Realm()
try! realm.write {
userlist.Medis.append(medi)
realm.add(userlist, update: true)
}
Second try:
let realm = try! Realm()
try! realm.write {
userlist.Medis.append(medi)
}
The problem is the
let realm = try! Realm()
The documentation specify
// Get the default Realm
let realm = try! Realm()
// You only need to do this once (per thread)
You did on both view controllers and there is no guarantee that the path to the default Realm will be the same. It might work on the actual device but not on simulator.
Try this and delete all other occurrences
// Put this inside your Real class Definition/Declaration file
let realm = try! Realm()
Hope this help