Is it possible to add a dynamic amount of strings to Firestore?
This is my code:
I use a string array called names.
let newDoc = ref.collection("Docs").document()
for i in 0 ..< names.count{
newDoc.setData(["\(i)" : names[i]])
}
It's possible, but you probably don't want to be calling setData repetitively like that. Instead, you can translate names into a Dictionary<String,String> and then just call setData once:
let names = [String]()
let dictVersion = Dictionary(uniqueKeysWithValues: names.enumerated().map { index, value in
return ("\(index)",value)
})
let newDoc = ref.collection("Docs").document()
newDoc.setData(dictVersion)
Related
Consider a function which which assigns value to an array like so...
fileprivate func getMessages() {
if let myId = recipientGrp?.id,
let array = realm()?.objects(TheMessage.self)
.filter("ownerId = '\(myId)' || receiverId = '\(myId)'")
.sorted(byKeyPath: "id", ascending: true) {
allMessages = array
}
}
Here, allMessages is the array into which values are added. Also allMessages is declared like so....
var allMessages: Results<TheMessage>?
What I want to achieve is I want to remove all elements of the array allMessages. allMessages.removeAll doesn’t work. So how can I achieve that?
Because allMessages is a Results<Message>, you need to remove those objects from Realm to actually remove them.
let realm = // get a realm
try realm.write {
realm.delete(allMessages)
}
// allMessages will automatically become empty at this point.
I have an dictionary and the value containts the array of string as follows
arr = ["key":"["a","b","c","d","e","f","g"]"]
I want the new array to be like
let array = ["a","b","c","d","e","f","g"]
How to parse it
You can access dictionary items in few different ways, the easiest is:
let array = arr["key"]
You may need to conditionally unwrap it
if let array = arr["key"] as? [String] {
// rest of code with array
}
I am inserting an Array into my database as a String and after fetching it I want it to convert it again to Array. So that I can fetch my values again and I can do next operation.
Here below is my array inserting into database(TestQuestion) as a String:
let testQuestionModel : TestQuestion = NSEntityDescription.insertNewObject(forEntityName: "TestQuestion", into: AppDelegate.getContext()) as! TestQuestion
testQuestionModel.optionsArray = "\(question["options"] as! NSArray)"
Example: String Array I am getting from Database
(\n \"Rahul Abhyankar\",\n \"Pinkesh Shah\",\n \"Ramanan
Ganesan\",\n \"Dr. Marya Wani\",\n \"\",\n \"\"\n)".
Here is 4 options you can see this is my string after fetching from Database.
1) Rahul Abhyankar.
2) Pinkesh Shah.
3) Ramanan Ganesan.
4) Dr. Marya Wani.
Now how can I convert it into array?
I tried some methods.
let arr = NSArray(object: quetion.optionsArray!).
But I am getting only one object. How can I get my array values same as previous from this string array?
I don't know about the actual type of the "option" in your code, so I set up a fake Elem struct to represent it. The remaining logic is independent of the type as long as you provide a conversion logic to and from String.
struct Elem {
// let's say this is your element type in your array
let foo: Int;
}
extension Elem: CustomStringConvertible {
var description: String {
// provide a logic to convert your element to string
return "\(foo)";
}
}
let arrayToSave = [
Elem(foo: 1),
Elem(foo: 2),
Elem(foo: 3)
]
extension Elem {
init(string: String) {
// provide a function to construct your element type from a string
self.init(foo: Int(string)!)
}
}
let stringToSave = arrayToSave.map { $0.description }.joined(separator: "|")
// save this string
// at some point retrieve it from database, which hopefully same as the saved one
let retrivedString = stringToSave;
let retrivedArray = retrivedString.split(separator: "|").map { Elem(string: String($0)) }
print(retrivedArray) // [1, 2, 3]
Here below is my array inserting into database (TestQuestion) as a
String :
let testQuestionModel : TestQuestion = NSEntityDescription.insertNewObject(forEntityName: "TestQuestion", into: AppDelegate.getContext()) as! TestQuestion
testQuestionModel.optionsArray = "\(question["options"] as! NSArray)"
No, and No.
You are using -description method of an array to save it. Clearly no.
What's wrong? Apple can't affirm that in next OS release, it won't add an extra character. In some more complex cases, it's added <NSArray <0x address> or stuff similar like that.
Suggestion 1:
Modify your entity to have an ARRAY (or usually a Set) of String.
Learn about Core-Data relationship (but that's clearly a DataBase basic knownledge). A relationship one to many should be the thing to do.You could even keep in memory what were the choices, by adding for creating the entity Options, with a String property name (name of the option), another one boolean isChecked, etc.
Suggestion 2:
If you have a limited number of options (like says one to 5), add 5 options string to your entity, and iterate to set them
testQuestionModel.option1 = question["option"][0]
testQuestionModel.option2 = question["option"][1] (if it's of course not out of range for the array)
...
Suggestion 3:
Not really recommended (in my opinion it's missing the whole advantage of the database, especially fetch and predicates, on previous sample you could fetched easily which options were checked), but if you still want to save them as a String, save them as JSON (ie. stringified).
In pseudo code (I'm not sure about the exact syntax, there are no fail safe like try/catch, optional/wrapping):
let options = questions["options"] as [String]
let jsonData = JSONSerialization.data(withJSONObject: (question["options"], options:[])
let jsonString = String.init(data:jsonData encoding:.utf8)
To retrieve them:
let options = JSONSerialization.jsonObject(with data: myJSONString.data(encoding:.utf8), options:[]) as [String]
done using Library SwiftyJSON.
if let dataFromString = yourString?.data(using: String.Encoding.utf8, allowLossyConversion: false) {
do{
let json = try JSON(data: dataFromString)
print(json)
let arrayValue = json.rawValue as! NSArray
print(arrayValue)
} catch{
print(error.localizedDescription)
}
}
Source: https://github.com/SwiftyJSON/SwiftyJSON
I've been googling for a while, trying to find a solution to my problem and ended here. I'm trying to create a dictionary of dictionaries to load all the data in tableViewCells.
So I need a key for "name", another key for "description", another key for "image name" and like this..
I'm doing an async call so I've created a global var, nsDict which is a NSMutableDictionary and in the async parseJson Function I've created another NSMutableDictionary named jsonValues.
I use jsonValues to store the data inside the loop. The data is stored with keys too :
jsonValues["name"] = Name
And at the end of the loop I store jsonValues inside nsDict, my NSMutableDictionary global variable.
nsDict.setObject(jsonValues, forKey: c)
c += 1
At this point there is already somebody that knows for sure my issue and my mistake. But I've been trying and reading a lot of stackoverflow and didn't find the way to do something that easy.
My dictionary, is getting filled by all the jsonValues, but instead of inserting diferent values, it's copying all of them. Which is, in the first round of the loop, it insert the first value (dictionary of values). In the second loop, it insert the second dictionary of values in the first and in the second index...
At the end I got 43 same dictionaries. All of them are the copy of the last one...
Does anybody know why? I've spent two hours with this issue. Some help would be very appreciated, thanks!
private func parseJson(json : NSMutableArray, tableView : UITableView){
var jsonValues = NSMutableDictionary()
nsDict.removeAllObjects()
nsDict = NSMutableDictionary.init(capacity: 10)
var c : Int = 0
for j in json {
var nsData : NSMutableDictionary
//clean array
// jsonValues.removeAll()
//Create main value
guard let value = j.valueForKey("value")?.valueForKey("value")! else{
return
}
//Get name
guard let Name : String = (value.valueForKey("Name")?.valueForKey("en") as? String) else {
return
}
jsonValues["name"] = Name
title = "Address: "
//Get Address
if let Address = value.valueForKey("Address")?.valueForKey("en") as? String{
jsonValues["Address"] = Address
}
title = "Country: "
//Get country
if let country = geoposition.valueForKey("country") as? String{
let fCountry = title+country
jsonValues["Country"] = fCountry
}else{}
nsDict.setObject(jsonValues, forKey: c)
c += 1
}
doTableRefresh(tableView);
}
just move your var jsonValues = NSMutableDictionary() inside cycle
You create an NSMutableDictionary and insert it repeatedly. The object is inserted, not its contents. Therefore each entry contains the same object. You need to insert a new object at each index.
I have two separate arrays that I want to import into a dictionary. Order is extremely important because both arrays must match in index
struct MyVariables {
static var users:NSArray!
static var img:NSArray!
}
var data = SearchVC.getData()
MyVariables.users = data.users; //array 1 (key)
MyVariables.img = data.img; //array 2
// Goal is to insert these arrays into a dictionary while maintaing the matching indexes on both arrays
// Dictonary (MyVariables.img, key: MyVariables.users)
A Dictionary does not have a particular order. However, if both arrays have the same length, it is quite easy to iterate over them together:
var dictionary = [NSString: AnyObject]()
for var index = 0; index < data.users.count; index++ {
let img = data.img as! NSString
dictionary[img] = data.users[index]
}
Or, as #robertvojta suggested, use the zip() method:
var dictionary = [NSString: AnyObject]()
for (user, image) in zip(data.users, data.img) {
let img = image as! NSString
dictionary[img] = user
}
The key in a dictionary in swift must be hashable. i.e., not AnyObject.
Assuming you can replace some of your untyped Swift arrays, or cast them like so:
struct MyVariables {
var users:Array<AnyObject>
var img:Array<String>
}
then you can iterate through 1 array using a preferred Swift method and access the second using indexing:
var dictionary = Dictionary<String, AnyObject>()
for (index, element) in enumerate(MyVariables.img) {
dictionary[element] = MyVariables.users[index]
}
Use for loop for travels the array in that as per index access keys and values respective array and add it in dictionary. Its so simple so you can achive your goal using it.
I hope it will help you!