Ok, so I have a Realm database (named AutoComplete) with the following structure
I
Now I do a call to the backend, to get make all the [Folder] items.
Alamofire.request(.GET, URL).responseObject { (response: Response<Folders, NSError>) in
if response.result.isSuccess {
let mappedObject = response.result.value
let realm = try! Realm()
// open AutoComplete model
let openAutoComplete = realm.objects(AutoComplete)
try! realm.write {
if let everythingUnderResult = mappedObject?.result {
// for folder in [Folder]
for item in everythingUnderResult {
//check if the search string you typed in exists in the database
let searchifExists = openAutoComplete.filter("search == %#", searchString)
let makeString = searchifExists.first
let getSearchColumn = makeString?.search
if searchString == getSearchColumn {
//item exists, now add the folder to the autocomplete DB
makeString?.folder.append(item)
realm.add(makeString!,update: true)
} else {
print(item)
realm.add(item)
makeString?.folder.append(item)
}
}
}
}
} else {
print("couldn't get mobileapp data")
}
}
}
My issue is that I can't add the folderobjects to the database. The makeString?.folder.append(item) line of code gives back the following error:
Can't set primary key property 'id' to existing value '65502'.'
I know that the id already exists in my Folders model of the database, with the same ID, but I just want to reference it in the Autocomplete model. (not update it or overwrite it).
Anyone has an idea on how to fix this?
In this part of code
if searchString == getSearchColumn {
//item exists, now add the folder to the autocomplete DB
makeString?.folder.append(item) // it's ok
realm.add(makeString!,update: true) // you don't need this
} else {
print(item)
realm.add(item)
makeString?.folder.append(item)
}
just remove
realm.add(makeString!,update: true)
You don't need to add this record one more time to the table.Adding it to the folder list is enough
Related
I am fetching data from FireBase and save it inside my realm but it is not working as expected :
for doc in docs {
let shopData = doc.data()
let newShop = RLMShop()
newShop.shopName = shopData["name"] as? String ?? "Empty Name"
self.saveShop(shop: newShop) // My issue is here
}
My saveShop function :
func saveShop(shop: RLMShop) {
do {
try realm.write {
realm.add(shop)
}
} catch {
print("Error saving shop \(error)")
}
}
Calling save function is not saving my object.
The problem you have is that you are creating a RLMShop object but it is not linked to a RLMShopsCategory object, therefore your shopsList will not contain the new object.
// Fetch the RLMShopsCategory that you wish to add the RLMShop too
// Using Primary Key here just as an example
let shopsCategory = realm.object(ofType: RLMShopsCategory.self, forPrimaryKey: "YourKey")
for doc in docs {
let shopData = doc.data()
let newShop = RLMShop()
newShop.shopName = // setting the properties etc
// This is the part you are missing
// You need to append the newShop to your shopsCategory object
try! realm.write {
shopsCategory.shopsList.append(newShop)
}
}
I've recently changed a lot on my iOS application and now I got stuck.
I'm trying to insert data from Firestore which looks like this:
So, as you can see I've 6 different names in here.
And here is the code to insert into pickerView.
func getPerson()
{
let authentication = Auth.auth().currentUser?.uid
db.collection("users").document(authentication!).collection("person").getDocuments { (QuerySnapshot, err) in
//If error is not equal to nil
if err != nil
{
print("Error getting documents: \(String(describing: err))");
}
//Succeded
else
{
//For-loop
for _ in QuerySnapshot!.documents
{
//Cleaning the array for the new values
self.personArray.removeAll()
let document = QuerySnapshot!.documents
let data = document.data() //HERE IS THE ERROR
data.forEach { (item) in
if let person1Data = data["name"] as? String
{
self.personArray.append(person1Data)
print(self.personArray)
}
}
}
self.pickerView.reloadAllComponents()
}
}
}
I'm getting the error:
Value of type '[QueryDocumentSnapshot]' has no member 'data'
It used to have QuerySnapshot!.documents.first
but it does not work anymore when I've changed the Firestore data.
Edit:
So. the output is now:
["Joche"] ["Joche", "Joche"] ["Putte"] ["Putte", "Putte"] ["Rebecca"]
["Rebecca", "Rebecca"] ["Fredrik"] ["Fredrik", "Fredrik"] ["Anna"]
["Anna", "Anna"] ["Vickan"] ["Vickan", "Vickan"]
which means it adds everything but x3. How to solve this problem?
data is an instance method of a single QueryDocumentSnapshot not an array , You need
self.personArray.removeAll()
for elem in querySnapshot!.documents {
let data = elem.document.data()
data.forEach {
if let person1Data = $0["name"] as? String {
self.personArray.append(person1Data)
print(self.personArray)
}
}
}
I am trying to remove an element from a list which is stored in NSUserDefaults. The getAll function is implemented below:
func getAllOrders() -> [Order] {
var orders = [Order]()
if let userDefaults = UserDefaults(suiteName: "group.com.johndoe.SoupChef.Shared") {
if let ordersData = userDefaults.data(forKey: "Orders") {
orders = try! JSONDecoder().decode([Order].self, from: ordersData)
}
}
return orders
}
And here is the code for deleting the order.
func delete(order :Order) {
var persistedOrders = getAllOrders()
persistedOrders.removeAll { persistedOrder in
persistedOrder.identifier.uuidString == order.identifier.uuidString
}
}
After deleting the order in the code above when I call getAllOrders I still see all the elements, meaning I don't see the order being deleted.
That's because you don't save your changes. Once you've performed the removal you need to turn persistedOrders back into JSON and then:
userDefaults.set(json, forKey:"Orders")
You need to use jsonEncoder and encode the edited array then store it again the user defaults
func delete(order :Order) {
var persistedOrders = getAllOrders()
persistedOrders.removeAll { persistedOrder in
persistedOrder.identifier.uuidString == order.identifier.uuidString
}
do {
let data = try JSONEncoder().encode(persistedOrders)
userDefaults.set(data, forKey:"Orders")
}
catch {
print(error)
}
}
You have to store correctly your UserDefaults
UserDefaults.standard.set(json, forKey:"Orders")
Now, you can remove them using:
UserDefaults.standard.removeObject(forKey: "Orders")
I want to search for the key id in the dictionary. I have a dictionary like this:
var tableData:[String:Any] = ["id":["path":"","type":"","parameters":[]]]
Table data has 307 items, and all id's unique. I want to search in dictionary key id, like when I write "get" , it need the show all the search results with "get" in table view.
func updateSearchResults(for searchController: UISearchController) {
let searchString = searchController.searchBar.text
if let entry = tableData.keys.first(where: { $0.lowercased().contains(searchString) }) {
print(entry)
} else {
print("no match")
}
tableView.reloadData()
}
func didChangeSearchText(searchText: String) {
if let entry = tableData.keys.first(where: { $0.lowercased().contains(searchText) }) {
print(entry)
} else {
print("no match")
}
// Reload the tableview.
tableView.reloadData()
}
When I try to search a word it prints "no match", in the debug, unable to read data writes for the value of the entry. Thank you in advance!
In fact your keys have to be unique and as in your case id is a top level key you don't have to perform filtering in order to access its value. Simply use tableData[searchText] to grab its value.
If you don't know the id value and you want to loop through all the keys you can do so like
for key in tableData.keys {
print(key)
let value = tableData[key]
// or do whatever else you want with your key value
}
As per what you already have in place you need to do the following
var tableData:[String:Any] = ["hello world":["path":"fgh","type":"dfghgfh","parameters":[]], "something else":["path":"sdfsdfsdf","type":"dfghfghfg","parameters":[]]]
if let entry = tableData.keys.first(where: { $0.lowercased().contains("hello") }) {
print(entry)
// prints 'hello world'
} else {
print("no match")
}
Or you can simply get a new filtered array from your data source like
let result = tableData.filter { (key, value) in
key.lowercased().contains("else") // your search text replaces 'else'
}
/*
* result would be an array with the objects based on your id search
* so you'll not only have the keys but the entire object as well
*/
print("Found \(result.count) matches")
To access an element in a Dictionary with a key, use the following code.
if let entry = tableData[searchText] {
print(entry)
}
For further information, have a look at:
how can i get key's value from dictionary in Swift?
Try using first(where:) directly on tableData, like this:
func updateSearchResults(for searchController: UISearchController) {
guard let searchString = searchController.searchBar.text else { return }
if let (id, entry) = tableData.first(where: { (key, value) -> Bool in key.lowercased().contains(searchString) }) {
print(entry)
} else {
print("no match")
}
tableView.reloadData()
}
func didChangeSearchText(searchText: String) {
if let (id, entry) = tableData.first(where: { (key, value) -> Bool in key.lowercased().contains(searchText) }) {
print(entry)
} else {
print("no match")
}
// Reload the tableview.
tableView.reloadData()
}
So what im trying to do is, retrieve the object that is already saved on Realm, modify some properties and then save it again, keeping only one record on the database.
Heres my code :
Getting the Realm already saved user
if let user = User.query() {
user.latitude = String(latitude)
user.longitude = String(longitude)
user.save()
}
User query func, inside User Obj
static func query() -> User? {
return User.allObjects().toArray(User.self).first
}
func save() -> User {
RealmPersister.saveObjects([self])
return self
}
And the RealmPersister class func
class func saveObjects(objects: [RLMObject]?) {
autoreleasepool {
guard let objects = objects where objects.count > 0 else { return }
do {
let realm = RealmEncrypted.realm()
realm.beginWriteTransaction()
realm.addObjects(objects)
try realm.commitWriteTransaction()}
catch {
print("Realm did not write objects! \(objects)")
}
}
}
class func deleteObjects(objects: [RLMObject]?) {
autoreleasepool {
guard let objects = objects where objects.count > 0 else { return }
do {
let realm = RealmEncrypted.realm()
realm.beginWriteTransaction()
realm.deleteObjects(objects)
try realm.commitWriteTransaction()
} catch {
print("Realm did not delete objects! \(objects)")
}
}
}
This appears that you need to be using primary keys on the User object. This way you can retrieve the same object quickly via the primary key, modify it, and then save it without the possibility of creating duplicates.