I'm trying to add data to array inside for loop and again to array in another for loop.
Its working on first for loo, but in second data is empty. How to fix that
This is how it currently looks inside firestore and you can see scores missing.
this is code:
func updateCourseData() {
var data = ["endTime": Timestamp(date: Date()),
"players": []] as [String : Any]
for i in 0..<players.count {
var playerData = ["playerId": games[i].id,
"scores": []] as [String : Any]
var existingItems = data["players"] as? [[String: Any]] ?? [[String: Any]]()
existingItems.append(playerData)
data["players"] = existingItems
for score in 0..<selectedPage + 1 {
let scoreData = ["hole": games[i].scores[score].hole,
"score": games[i].scores[score].score] as [String : Any]
var existingScores = playerData["scores"] as? [[String: Any]] ?? [[String: Any]]()
existingScores.append(scoreData)
playerData["scores"] = existingScores
}
}
Constants.FirebaseCollection.gamesCollection.document(documentId).updateData(data) { error in
if let error = error {
print(error.localizedDescription)
}
print("Game updated")
}
}
Related
using swift vapor and elasticsearch, got a response like:
{
"_shards": {
"failed": 0,
"successful": 5,
"total": 5
},
"hits": {
"hits": [
{
"_id": "3",
"_index": "items_v1",
"_score": 1.2029922,
"_source": {
"property1": "test",
"property2": "another test",
...
},
"_type": "item"
},
...
inside "hits" -> "hits" -> "_source" I got all the properties of my model "Item". How can I create an array of Items "[Item]" from this json response?
Small enhancement, use a guard statement to avoid the nested ifs...
guard
let dict = response as? [String : Any],
let hits = dict["hits"] as? [String : Any],
let hitArray = hits["hits"] as? [[String : Any]]
else
{ throw Abort}
for hit in hitArray {
if let source = hit["_source"] {
arrayOfItems.append(Item(with: source))
}
}
Parse your response in this way, so there will be no crashes if some value will not be sent.
if let dict = response as? [String : Any] {
if let hits = dict["hits"] as? [String : Any] {
if let hitArray = hits["hits"] as? [[String : Any]] {
for hit in hitArray {
if let source = hit["_source"] {
arrayOfItems.append(Item(with: source))
}
}
}
}
}
Int your Item class create init method, where you will initialize item's properties.
init(with dict: [String : Any]) {
if let property1 = dict["property1"] as? Int {
self.property1 = property1
}
super.init()
}
Try like this! I assume that you get the Response and that response in saved in response variable
var myarray = [String]()
let hitDict = response["hits"] as! [String:AnyObject]
let hitArray = hitDict["hits"] as! Array
let someDict = hitArray[0] as! [String:AnyObject]
let sourcDict = someDict["_source"] as! [String:AnyObject]
let property1 = sourcDict["property1"] as! String
let property2 = sourcDict["property2"] as! String
myarray.append(property1)
myarray.append(property2)
var myArray = [String:String]()
//response from try drop.client.get(…)
let bodyReceived = responseFirebaseAssigned?.body.bytes
//JSON object made of bodyReceived
let JsonFirebase:JSON?
for val in JsonFirebase?.object ?? [:]{
let valKey = val.key.string
let valValue = val.value.string
arrayFB[valKey!] = valValue
print("arrayFB is \(arrayFB)")
}
I have a json string converted to string array like below:
let str = "{ \"dtResult\": [ { \"itmdtl_item_no\": \"AO406705959SE3\" }, { \"itmdtl_item_no\": \"AO406708959SE3\" } ] }"
let data = str.data(using: String.Encoding.utf8, allowLossyConversion: false)!
do {
let json = try JSONSerialization.jsonObject(with: data, options: []) as! [String: AnyObject]
let result = json["dtResult"] as? [[String:Any]] ?? [ ]
let item = result[0] as! [String:Any]
print(item)
} catch let error as NSError {
print("Failed to load: \(error.localizedDescription)")
}
When i print out the result of item, i got the value like this:
["itmdtl_item_no": AO406705959SE3]
But i just want the string "AO406705959SE3", how can i do? Thanks.
First of all don't write
let result = json["dtResult"] as? [[String:Any]] ?? [ ]
If result is nil or empty the app will crash on result[0]
Instead write to check if the array exists and is not empty
if let result = json["dtResult"] as? [[String:Any]], !result.isEmpty {
let item = result[0] as! [String:Any]
// Now get the value for key "itmdtl_item_no"
if let itemNo = item["itmdtl_item_no"] as? String {
print(itemNo)
}
}
i have the following object class:
class NewsItem: NSObject {
var storyCategory: String?
var titleText: String?
var paragraph1: String?
var paragraph2: String?
var featureImage: String?
var secondImage: String?
var storyDate: String?
var majorReference: String?
var fact: String?
var actualFeatureImage: UIImage? // Using these two to pass the image from home to story view
var actualSecondImage: UIImage?
var referencesArray = [AnyObject]()
...
init?(dictionary: [String: AnyObject]) {
guard
let storyCategory = dictionary["category"] as? String,
let titleText = dictionary["title"] as? String,
let paragraph1 = dictionary["paragraph1"] as? String,
let paragraph2 = dictionary["paragraph2"] as? String,
let featureImage = dictionary["headerImage"] as? String,
let storyDate = dictionary["date"] as? String,
let majorReference = dictionary["majorReference"] as? String,
let secondImage = dictionary["secondImage"] as? String
else {
return nil
}
self.storyCategory = storyCategory
self.titleText = titleText
self.paragraph2 = paragraph2
self.paragraph1 = paragraph1
self.featureImage = featureImage
self.storyDate = storyDate
self.majorReference = majorReference
self.fact = dictionary["fact"] as? String //if there's a fact in the dict, it will be assigned and if not there'll be nil
self.secondImage = secondImage
let referenceObject = dictionary["reference"] as? [[String: AnyObject]]
for object in referenceObject! {
self.referencesArray.append(object)
//print(object)
}
//bellow is a snippet from the method that's serializing the JSON data
do {
let json = try NSJSONSerialization.JSONObjectWithData(data, options: .AllowFragments)
if let newsArticles = json["stories"] as? [[String: AnyObject]] {
for article in newsArticles {
let newsArticle = NewsItem(dictionary: article)
newsItems.append(newsArticle!)
}
}
} catch {
print("error in the news items delivery: \(error)")
let displayError = EHPlainAlert(title: "hmmm...", message: "\(error)", type: ViewAlertError)
displayError.show()
}
}
in the backend of the app, i have JSON objects and one of the values of each of the objects is as follows:
... "reference" : [
{
"refName": "CNN",
"refURL": "http://edition.cnn.com/2016/07/19/football/brexit-effect-on-english-premier-league/index.html"
},
{
"refName": "Telegraph",
"refURL": "http://www.telegraph.co.uk/football/2016/06/21/what-would-brexit-mean-for-the-premier-league/"
}
], ...
i don't know if i have the JSON wrong o' something but what i intend to have is an array of references, each reference having a reference name(refName) and the url of the reference (refURL).
my question is, what would be the best method to have the JSON object above be added to the referencesArray in my object class. Would it be better to use a dictionary instead of an array? if so, how should i re-write my code?
if you need any more details about the code, ask and ye shall receive an update. Thanks!
EDIT
Here's the JSON in full :
{
"stories" : [
{
"title" : "English Premier League vs BREXIT: Who will win?",
"headerImage" : "http://i2.cdn.turner.com/cnnnext/dam/assets/160117112140-rooney-goal-exlarge-169.jpg",
"category" : "Sports",
"paragraph1" : "Paragraph text",
"paragraph2" : "More text goes here",
"date" : "21st July",
"majorReference" : "CNN",
"reference" : [
{
"refName": "CNN",
"refURL": "http://edition.cnn.com/2016/07/19/football/brexit-effect-on-english-premier-league/index.html"
},
{
"refName": "Telegraph",
"refURL": "http://www.telegraph.co.uk/football/2016/06/21/what-would-brexit-mean-for-the-premier-league/"
}
],
"secondImage" : "http://www.telegraph.co.uk/content/dam/football/2016/06/14/02-leicester-afp-xlarge_trans++Wy_u4a9GUNQgLIY2EGV3qvLCN329DeTLuwi-bwi35Bo.jpg",
"fact" : "Talent will go missing"
}, ...
Thats just one story... after the comma, is another story.
First, define a data model for your reference:
struct NewsItemReference {
var refName: String
var refURL: NSURL
}
Then modify your NewsItem class as below:
class NewsItem: NSObject {
var referencesArray = [NewsItemReference]()
init?(dictionary: [String: AnyObject]) {
...
if let references = dictionary["reference"] as? [[String: AnyObject]] {
for object in references {
guard let refName = object["refName"] as? String,
let refURLString = object["refURL"] as? String,
let refURL = NSURL(string: refURLString) else {
continue
}
self.referencesArray.append(NewsItemReference(refName: refName, refURL: refURL))
}
}
}
If you see yourself quickly outgrowing this model (the code is too verbose), take a look at some JSON-to-object mapping framework like ObjectMapper.
Trying to store an array of dictionaries with NSUserDefaults.
var theTasks: [[String:Any]] = [["num":1,"title":"example","colour":"red"]]
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setObject(theTasks, forKey: "myTasks")
defaults.synchronize()
let selected = theTasks[1]
Gives error:
Cannot convert value of type '[[String:Any]]' to expected argument of type 'AnyObject?'
Swift 3.x
In Swift 3 it has changed so now it needs to be saved as [Any] Any Array and use UserDefaults array(forKey:) method to load it:
let theTasks: [Any] = [["num": 1, "title": "example", "colour": "red"]]
UserDefaults.standard.set(theTasks, forKey: "myTasks")
if let loadedTasks = UserDefaults.standard.array(forKey: "myTasks") as? [[String: Any]] {
print(loadedTasks)
}
var theTasks: [[String: Any]] {
get {
return UserDefaults.standard.array(forKey: "myTasks") as? [[String: Any]] ?? []
}
set {
UserDefaults.standard.set(newValue as [Any], forKey: "myTasks")
}
}
Swift 2.x
You just need to save it as a AnyObject array and use NSUserDefaults method arrayForKey to load it:
let theTasks: [AnyObject] = [["num": 1, "title": "example", "colour": "red"]]
NSUserDefaults.standardUserDefaults().setObject(theTasks, forKey: "myTasks")
if let loadedTasks = NSUserDefaults.standardUserDefaults().arrayForKey("myTasks") as? [[String: AnyObject]] {
print(loadedTasks)
}
You can also create a computed property with a getter and a setter to do all the work behind the scenes for you as follow:
var theTasks: [[String: AnyObject]] {
get {
return NSUserDefaults.standardUserDefaults().arrayForKey("myTasks") as? [[String: AnyObject]] ?? []
}
set {
NSUserDefaults.standardUserDefaults().setObject(newValue as [AnyObject], forKey: "myTasks")
}
}
print(theTasks) // [["title": example, "colour": red, "num": 1]]
theTasks[0]["title"] = "another example"
print(theTasks) // [["title": another example, "colour": red, "num": 1]]
Just call the .setObject() method directly from NSUserDefaults()and it should work fine.
NSUserDefaults().setObject(theTasks, forKey: "myTasks")
i need to save with NSUserDefaults an array that i get from jSON, the problem is it save only the first string and not all the array. So if the array is like NewYork,London,Rome .. it save only NewYork. I use it for a picker view.
This is the code:
EDIT
For save the Array from jSON:
if let jsonData = NSJSONSerialization.JSONObjectWithData(urlData!, options: nil, error: &error) as? [String:AnyObject] { // dictionary
if let locationsArray = jsonData["locations"] as? [[String:AnyObject]] { // array of dictionaries
for locationDictionary in locationsArray { // we loop in the array of dictionaries
if let location = locationDictionary["location_name"] as? String { // finally, access the dictionary like you were trying to do
// println(location)
var locationSave: Void = save.setObject(location, forKey: "Location")
}
}
}
}
}
and for request the Array:
var Location = save.objectForKey("Location")!
var pickerviewFields = Location
return pickerviewFields.count
Thanks in advance!
You can only save an NSArray, if the Array is a Swift Array, you will need to convert it. Also, NSArray and NSDictionary objects, their contents must be property list objects.
Here's how you would convert the Array:
var MyArray = ["a", "b", "c"]
var MyNSArray: NSArray
MyNSArray = MyArray as NSArray
println("\(MyNSArray)")
Prints: (a,b,c)
I have a small example with some sample JSON:
var myJSONString: NSString = "{ \"locations\" : [ { \"location_name\" : \"A\" }, { \"location_name\" : \"B\" }, { \"location_name\" : \"C\" }, { \"location_name\" : \"D\" } ] }"
var urlData: NSData? = NSData()
var error: NSError?
var save = NSUserDefaults.standardUserDefaults()
urlData = myJSONString.dataUsingEncoding(NSUTF8StringEncoding)
if let jsonData = NSJSONSerialization.JSONObjectWithData(urlData!, options: nil, error: &error) as? NSDictionary { // dictionary
if let locationsArray = jsonData["locations"] as? NSArray { // array of dictionaries
for locationDictionary in locationsArray { // we loop in the array of dictionaries
if let location = locationDictionary["location_name"] as? NSString {
println(location)
}
}
NSUserDefaults.standardUserDefaults().setObject(locationsArray, forKey: "locationArray")
}
}
println(save.dictionaryRepresentation())
You can try this:
Writing
let locationArray = ["London", "NewYork", "Rome"]
let locationData = NSKeyedArchiver.archivedDataWithRootObject(locationArray)
NSUserDefaults.standardUserDefaults().setObject(locationData, forKey: "Location")
NSUserDefaults.standardUserDefaults().synchronize()
Reading
let locationData = NSUserDefaults.standardUserDefaults().objectForKey("Location") as? NSData
if let locationData = locationData {
let locationArray = NSKeyedUnarchiver.unarchiveObjectWithData(locationData) as? [String]
if let locationArray = locationArray {
println(locationArray)
}
}