I'm iterating over JSON data and taking the data and assigning it to a global variable, when I print the variable within the loop I get all the data, however, when I print the variable outside the loop I'm only getting the last pieces of data from the JSON object. My objective is to take the data and pass it as a parameter of a function. How do I get all the data outside the loop?
var stockParam = [String]()
for info in stockInfo {
self.stockParam = [info.symbol]
print("inside \(stockParam)")
}
print("outside \(stockParam)")
fetchProfileData(stock: stockParam)
Thats because you are setting stockParam as array of one element (info.symbol):
self.stockParam = [info.symbol]
To hold all info symbols in stockParam array you have to append element on every iteration:
for info in stockInfo {
self.stockParam.append(info.symbol)
}
Or simply use map function:
var stockParam = stockInfo.map {$0.symbol}
Related
I have an array of Strings which represent Firebase Document IDs like so:
var idArray = [“PuLDb90jgz3a5P8bLQoy”, “PMKoZIp46umXQnUlA64a”, “cVGbD3Wy4gWjZ9fZP7h1”]
This Array is dynamic and has been generated by a previous getDocuments call. It could have up to 15 ID strings in it, so it cannot be hard coded.
Within each Firebase Document I have an Int field called menuPosition set to a current value.
What I am trying to do is update each document which appears in the idArray and simply -1 from the menuPosition field value in one go.
What should be so straightforward is driving me crazy - does anyone know a simple way to do it? Obviously, if I put it in a for loop then the code will run too many times and my menuPosition value would be wrong. I just want each operation to perform once.
Any help would be greatly appreciated
Just run a loop over the document IDs and decrement the field in each iteration.
var idArray = ["J2LovReBF0v8F4e0RSBU", "UcW8tsgld2ZuUo92xfP8", "oHTJ4iO1NWCK7x1aryne"]
for docId in idArray {
Firestore.firestore().document("someCollection/\(docId)").updateData([
"menuPosition": FieldValue.increment(Int64(-1))
])
}
If you want this operation to be atomic then just wrap it in a batch write.
var idArray = ["J2LovReBF0v8F4e0RSBU", "UcW8tsgld2ZuUo92xfP8", "oHTJ4iO1NWCK7x1aryne"]
let db = Firestore.firestore()
let batch = db.batch()
for docId in idArray {
batch.updateData([
"menuPosition": FieldValue.increment(Int64(-1))
], forDocument: db.document("someCollection/\(docId)"))
}
batch.commit()
I have a variable:
reas : [String:[User]]?
I want to sort it and put it in another view controller variable
vc.OrederReas = reas.sorted { $0.1.count > $1.1.count }
I'm getting an error that orderReas needs to be of type
[Dictionary<String, [User]>.Element]()
Which I made, Now I want to put a signal element from orderReas (which should be String:[User], and maybe sometimes all the elements, but this is not the issue).
but I don't know how to define it, I'm getting errors such as:
Cannot assign value of type 'Dictionary<String, [User]>.Element' (aka '(key: String, value: Array<User>)') to type '[Dictionary<String, [User]>.Element]' (aka 'Array<(key: String, value: Array<User>)>')
But I can't define a variable as
var OrederReas = Dictionary<String, [User]>.Element
To sum up I want a variable which holds [String:[User]], sort him into another variable, and Another variable which will hold one either one element or all the elements from the original variable.
Thank you!
When you are sorting a Dictionary the result will be a array Tuple of Key and Value.
in your case, if you want to have dictionaries of the same type you can convert your Result(Tuple) to a Dictionary so you can do this:
let tupleOrederReas = reas.sorted { $0.value.count > $1.value.count }
let dictionaryOrederReas = tupleOrederReas.reduce(into: [:]) { $0[$1.key] = $1.value }
//Finally Pass the Dictionary to VC variable
vc.OrederReas = dictionaryOrederReas
I have a dictionary var items = [String:String]()
Then I assign values :
for i in itemInCart {
items["param_id"] = i.modelId
//items["param_id"]?.append(i.modelId!)
}
print(items)
I have just a last value.
I know that the method append() is not applicable to dictionaries, but how can I fill it then?
This is because you are replacing param_id every time for loop i so it will always a last element you will found
You have two options, either create a unique key for each element (a bad idea) or if you want all the elements you have to create array and add it into the param_id key like:
items["param_id"] = itemInCart.map { $0.modelId }
so now your dictionary is [String:Any]() or [String:[String]]()
I find only in the docs how the query can look like to select data.
As far as I see, there is only one way to collect 1 or many results:
var query = PFQuery(className:"GameScore")
query.whereKey("playerName", equalTo:"Sean Plott")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]!, error: NSError!) -> Void in
if error == nil {
// The find succeeded.
NSLog("Successfully retrieved \(objects.count) scores.")
// Do something with the found objects
for object in objects {
NSLog("%#", object.objectId)
}
} else {
// Log details of the failure
NSLog("Error: %# %#", error, error.userInfo!)
}
}
What I cant figure out (as I am a beginner!) is how to access the object data. Lets say I have the fields "name", how can I get it? What is the right syntax? Especially if I have more than 1 result?
For just one result I would do:
var name = object["name"] as String
myArray.append(name)
Even that can't be right? To use "var xx = xx" within the loop?
And what do I do when I have more than one result?
Other thought:
Declaring the var name: String! before I do the query and then:
name = object["name"] as String
self.myArray.append(name)
Returns the error: Immutable vaue of type [String] only has mutating members named 'append'
What would be the correct way to "work" with the data the query returns?
Another question: as those querys are async, they finished later and the method is "done" much more earlier, this way my array with names is empty when the view is shown and I receive the data at a later stage. What is the best practice here to have all data available before the view is delivered to the device?
Thanks so much!!
You can use objectForKey on your object. So instead of using var name = object["name"] as String you can use:
for object in objects {
var name = object.valueForKey("name") as String
}
But the other parts are absolutely fine. You can create an array somewhere in you code and then add the objects to it. to do that, you can loop through your objects and than add the objects to your array. Like that:
if error == nil {
// The find succeeded.
NSLog("Successfully retrieved \(objects.count) scores.")
// Do something with the found objects
for object in objects {
var name = object["name"] as String
myArray.append(name)
}
}
Because you can reuse the var name because every loop-element will be filled into the variable name and will erase the last value. But the array will get the new value appended. For example:
First loop. The value at the first index of your objects gets loaded into the object. For example with the value "John".
variable name's value is now the value of the object["name"] of the current loop. So name has the value John
Now you add the value to your array.
The second loop starts and the second element gets loaded inside object which now has the string Michael.
The Variable name's new value is now the value of object. So name's value is now Michael
and so on.
Code snippets:
This is from a struct called Static:
static var messages: Dictionary = [:]
This is inside a class function:
if Static.messages[sender] == nil{ //no message history, create array then append
var messages: [NSMutableDictionary] = [message]
Static.messages[sender] = messages
}
else{ //there is message history, so append
(Static.messages[sender] as Array).append(message)
}
Error:
Immutable value of type 'Array<T>' only has mutating members named 'append'
I'm trying to make a Dictionary of conversations with each item being a person. Each array will be a list of messages. The messages are of type dictionary. Any idea why I'm getting this message?
If you're clear with the compiler about what your dictionary contains, you won't need the cast that is making this difficult. From what you've posted, the actual type of Static.messages will need to be something like Dictionary<NSObject, Array<NSMutableDictionary>>.
Your current attempt casts a dictionary value as an Array and then tries to append -- this fails because Swift treats the result of this kind of cast as immutable. What you need to do instead is to simply use optional chaining:
// instead of:
(Static.messages[sender] as Array).append(message)
// use:
Static.messages[sender]?.append(message)