realm.write is not saving the new items - swift

Here is my code. I'm using RealmSwift and the following code to save the new items to Item class.
if let currentCategory = self.selectedCategory {
do {
try self.realm.write {
let newItem = Item()
newItem.title = textField.text!
newItem.dateCreated = Date()
currentCategory.items.append(newItem)
}
} catch {
print("Error saving new items, \(error)")
}
}
I created a new instance of selectedCategory called currentCategory to append new items into my todo list. The code inside the closure is not working for some reason. I tried to test by adding a print(newItem.title) in the closure, that didn't print either. How to fix this issue?

Related

Prevent delete array of object adding again in realm db

I have an api who fetch data and add it in realm, what i want is whenever i delete realm object and refresh the page and called the api. the object that already delete is not showing/adding again in realm db. How to do it? here is my code
class TickerRealmStorage: RealmStorage, TickerStorage {
private var items = RealmSwift.List<Ticker>()
private var temptTicker: Ticker?
func get() -> RealmSwift.List<Ticker> {
return items
}
func save(messages: [Message]) {
messages.forEach { message in
let ticker = Ticker()
ticker.campaignID = message.campaignID
ticker.isRead = message.isRead
ticker.messageBody = message.body
if let temptTicker = temptTicker, ticker.campaignID == temptTicker.campaignID {
try! realm.write {
realm.delete(ticker)
}
}
items.append(ticker)
}
do {
try realm.write {
realm.add(items, update: .modified)
}
} catch {
fatalError("Failed to save tickers")
}
}
func delete(ticker: Ticker) {
temptTicker = ticker
try! realm.write {
realm.delete(ticker)
}
}
}
Should i add a temptItems so i check if the data already delete not adding into list items.

Saving objects to Realm

I try to save some objects to a Realm, but even after setting the member variables and saving it - after reading the Realm, the objects have their default values.
class Person: Object {
#objc dynamic var Name: String = "test"
#objc dynamic var Age: Int = 0;
}
do {
let realm = try Realm();
var p = Person();
p.Name = "Poirot"
p.Age = 55
try realm.write {
realm.add(p)
print("Person:",p.Name); // <-- Here its correct: "Poirot"
}
} catch let error {
print(error.localizedDescription)
}
do {
let realm = try Realm()
let data = realm.objects(Person.self)
for persons in data {
print("Person:", persons.Name); // <-- Here its wrong: "test"
}
} catch let error {
print(error.localizedDescription)
}
After running this, it would print:
Person: Poirot
Person: test
Can someone explain me this behavior and tell me what I´m doing wrong?
Thank you!
If you run your code in foreground it is fine.
If you are on a background thread (a thread without a RunLoop) than you need to refresh your realm.
let realm = try Realm()
realm.refresh()
let data = realm.objects(Person.self)
for persons in data {
print("Person:", persons.Name); // <-- Here its wrong: "test"
}
Have a look at the Realm threading documentation and scroll down to Refreshing Realms

Item keeps getting added to Tableview even if I just have one in my DB

I have this code and I call it every time I click on a button and call another viewcontroller where I call fetchVinylData inside viewWillappear. The problem is everytime I click a button to go to this VC it adds one item to the tableview even if I only have one inside my database.I am guessing is because my array keeps getting fed even if there is only one record in my database.How do I delete from my array so I don't get many values inside my tableView only the ones that is saved on my firebase database?I tried to add myArray.removeAll() inside fetchrequest before I load the vinyl to the array but my app crashs eventually
func fetchVinylData() {
SVProgressHUD.show()
guard let currentUID = Auth.auth().currentUser?.uid else { return }
dbRef.child("vinylsOUT").child(currentUID).observe(.childAdded) { (snapshot) in
guard let dictionary = snapshot.value as? Dictionary<String,AnyObject> else { return }
let vinyl = Vinyl(dictionary: dictionary)
self.vinyls.append(vinyl)
self.vinyls.sort(by: { (vinyl1, vinyl2) -> Bool in
return vinyl1.artist < vinyl2.artist
})
self.tableView.reloadData()
}
SVProgressHUD.dismiss()
}
thank yo very much
You are appending to your array every time you get back data from Firebase:
- self.vinyls.append(vinyl)
You can just override your current vinyls array by doing:
self.vinyls = [Vinyl]()
before you fetch the new data from Firebase.
That would look like this:
func fetchVinylData() {
SVProgressHUD.show()
guard let currentUID = Auth.auth().currentUser?.uid else { return }
self.vinyls = [Vinyl]() // <- here you reset the array
dbRef.child("vinylsOUT").child(currentUID).observe(.childAdded) { (snapshot) in
guard let dictionary = snapshot.value as? Dictionary<String,AnyObject> else { return }
let vinyl = Vinyl(dictionary: dictionary)
self.vinyls.append(vinyl)
self.vinyls.sort(by: { (vinyl1, vinyl2) -> Bool in
return vinyl1.artist < vinyl2.artist
})
self.tableView.reloadData()
}
SVProgressHUD.dismiss()
}

RealmDB does not get populated

New to Realm... so hopefully a simple fix!
I have a data object of:
class GasFile : Object {
#objc dynamic var gasFilename : String = ""
// #objc dynamic var gasCategory : String? = ""
}
In my ViewController I have the following function:
func PopulateRealmWithFilenames() {
let fm = FileManager.default
var path = Bundle.main.resourcePath!
path += "/NBTFiles"
//let items = try! fm.contentsOfDirectory(atPath: path)
let items : [String] = try! fm.subpathsOfDirectory(atPath: path)
for item in items {
do {
print("item for realm is: \(item)")
try self.realm.write {
let newGasFile = GasFile()
newGasFile.gasFilename.append(item)
print("newGasFile written ok")
}
} catch {
print("Error writing new item to Realm \(error)")
}
}
}
This sets up the RealmDB ok, but never gets populated.
The aim of the function is to save all the filenames (not paths) of the files stored in a folder called NBTFiles.
I get the 'newGasfile written ok printed out' so it is getting into the loop.
datatype error ?
(I know I could just put it into an Array, but I want to use realm)
how do you want to add new object to realm without using adding function ?
you should use realm.add(object: newGasFile)
try this
func PopulateRealmWithFilenames() {
let fm = FileManager.default
var path = Bundle.main.resourcePath!
path += "/NBTFiles"
//let items = try! fm.contentsOfDirectory(atPath: path)
let items : [String] = try! fm.subpathsOfDirectory(atPath: path)
for item in items {
do {
print("item for realm is: \(item)")
try self.realm.write {
let newGasFile = GasFile()
newGasFile.gasFilename.append(item)
realm.add(object: newGasFile)
print("newGasFile written ok")
}
} catch {
print("Error writing new item to Realm \(error)")
}
}
}

Swift Remove Object from Realm

I have Realm Object that save list from the JSON Response. But now i need to remove the object if the object is not on the list again from JSON. How i do that?
This is my init for realm
func listItems (dic : Array<[String:AnyObject]>) -> Array<Items> {
let items : NSMutableArray = NSMutableArray()
let realm = try! Realm()
for itemDic in dic {
let item = Items.init(item: itemDic)
try! realm.write {
realm.add(item, update: true)
}
items.addObject(item)
}
return NSArray(items) as! Array<Items>
}
imagine your Items object has an id property, and you want to remove the old values not included in the new set, either you could delete everything with just
let result = realm.objects(Items.self)
realm.delete(result)
and then add all items again to the realm,
or you could also query every item not included in the new set
let items = [Items]() // fill in your items values
// then just grab the ids of the items with
let ids = items.map { $0.id }
// query all objects where the id in not included
let objectsToDelete = realm.objects(Items.self).filter("NOT id IN %#", ids)
// and then just remove the set with
realm.delete(objectsToDelete)
I will get crash error if I delete like top vote answer.
Terminating app due to uncaught exception 'RLMException', reason: 'Can only add, remove, or create objects in a Realm in a write transaction - call beginWriteTransaction on an RLMRealm instance first.'
Delete in a write transaction:
let items = realm.objects(Items.self)
try! realm!.write {
realm!.delete(items)
}
func realmDeleteAllClassObjects() {
do {
let realm = try Realm()
let objects = realm.objects(SomeClass.self)
try! realm.write {
realm.delete(objects)
}
} catch let error as NSError {
// handle error
print("error - \(error.localizedDescription)")
}
}
// if you want to delete one object
func realmDelete(code: String) {
do {
let realm = try Realm()
let object = realm.objects(SomeClass.self).filter("code = %#", code).first
try! realm.write {
if let obj = object {
realm.delete(obj)
}
}
} catch let error as NSError {
// handle error
print("error - \(error.localizedDescription)")
}
}
What you can do is assign a primary key to the object you are inserting, and when receiving a new parsed JSON you verify if that key already exists or not before adding it.
class Items: Object {
dynamic var id = 0
dynamic var name = ""
override class func primaryKey() -> String {
return "id"
}
}
When inserting new objects first query the Realm database to verify if it exists.
let repeatedItem = realm.objects(Items.self).filter("id = 'newId'")
if !repeatedItem {
// Insert it
}
The first suggestion that comes to mind is to delete all objects before inserting new objects from JSON.
Lear more about deleting objects in Realm at https://realm.io/docs/swift/latest/#deleting-objects
do {
let realm = try Realm()
if let obj = realm.objects(Items.self).filter("id = %#", newId).first {
//Delete must be perform in a write transaction
try! realm.write {
realm.delete(obj)
}
}
} catch let error {
print("error - \(error.localizedDescription)")
}
There is an easier option to remove 1 object:
$item.delete()
remember to have the Observable object like:
#ObservedRealmObject var item: Items
var realm = try! Realm()
open func DeleteUserInformation(){
realm.beginWrite()
let mUserList = try! realm.objects(User.self)
realm.delete(mUserList)
try! realm.commitWrite()
}