Save data from parse into a string - ios

I want to save data from my parse class into strings. I use the following code actually for retrieving data from my parse class.
#IBAction func readAction(sender: UIButton) {
var tagAutor = ""
var tagText = ""
var query = PFQuery(className:"Tags")
query.getObjectInBackgroundWithId("f3AXazT9JO") {
(tag: PFObject?, error: NSError?) -> Void in
if error == nil && tag != nil {
println(tag)
// tagAutor = tag["username"]
// tagText = tag["tagtext"]
} else {
println(error)
}
}
}
In the comments there is what I want to do, in my class called "Tags" there are two cols called "username" and "tagtext" I want to save them in the two string variables "tagAutor" and "tagText". The println(tag) is printing out the following:
How can I save the objects out of my query into this two string variables?

Tell the compiler to convert the AnyObject to a String:
if let author = tag["username"] as String {
tagAutor = author
}
And probably move the definition of tagAuthor so you can use I outside the function

Related

How to access & get nested values from IOS Swift 'Any' type?

I am trying to read from Firestore into a Dictionary[Any] type using Struct. I can get the values loaded into variable "data" dictionary with Any type.
However I cannot loop thru it to access normal nested Dictionary variable.
I cannot get Key, values printed.
Following is my code:
class PullQuestions {
//shared instance variable
**public var data = [Any]()**
private var qdb = Firestore.firestore()
public struct questionid
{
let qid : String
var questions : [basequestion]
var answers: [baseans]
}
public struct basequestion {
let category : String
let question : String
}
public struct baseans {
let answer : String
}
class var sharedManager: PullQuestions {
struct Static {
static let instance = PullQuestions()
}
return Static.instance
}
static func getData(completion: #escaping (_ result: [Any]) -> Void) {
let rootCollection = PullQuestions.sharedManager.qdb.collection("questions")
//var data = [Any]()
rootCollection.order(by: "upvote", descending: false).getDocuments(completion: {
(querySnapshot, error) in
if error != nil {
print("Error when getting data \(String(describing: error?.localizedDescription))")
} else {
guard let topSnapshot = querySnapshot?.documents else { return }
// var questiondoc = [basequestion]()
for questioncollection in topSnapshot {
rootCollection.document(questioncollection.documentID).collection("answers").getDocuments(completion: {
(snapshot, err) in
guard let snapshot = snapshot?.documents else { return }
var answers = [baseans]()
for document in snapshot { //There should be only one Document for each answer collection
//Read thru all fields
for i in 0..<document.data().count
{
let newAns = baseans(answer: answer)
print("Answer Docs=>", (answer))
answers.append(newAns)
}
}
let qid = questioncollection.documentID
let category = questioncollection.data()["category"] as! String
let question = questioncollection.data()["question"] as! String
let newQuestions = basequestion(category: category ,question: question)
let newQuestionDict = questionid(qid: qid, questions: [newQuestions], answers: answers)
PullQuestions.sharedManager.data.append(newQuestionDict)
//Return data on completion
completion(PullQuestions.sharedManager.data)
})
}
}
})
}
}
I can print like this
print("Count =>", (PullQuestions.sharedManager.data.count))
// print(PullQuestions.sharedManager.data.first ?? "Nil")
print(PullQuestions.sharedManager.data[0])
for element in PullQuestions.sharedManager.data
{
print("Elements in data:=>", (element))
}
I could access only the key.. how do i go and get the nested values ?
First of all, consider using Swift code conventions (e.g. your structs are named with small letters, but you should start with capital), this will make your code more readable.
Returning to your question. You use an array instead of dictionary (this piece of code: public var data = [Any]()). And here you are trying to print values:
for element in PullQuestions.sharedManager.data
{
print("Elements in data:=>", (element))
}
In this context element is an Any object, thus you cannot access any underlying properties. In order to do this you have two options:
1. You should specify the type of array's objects in it's declaration like this:
public var data = [questionid]()
or you can user this:
public var data: [questionid] = []
These two are equals, use the one you prefer.
2. If for any reasons you don't want to specify the type in declaration, you can cast it in your loop. Like this:
for element in PullQuestions.sharedManager.data
{
if let element = element as? quetionid {
print("Elements in data:=>", (element))
// you can also print element.qid, element.questions, element.answers
} else {
print("Element is not questionid")
}
}
You could of course use the force cast:
let element = element as! questionid
and avoid if let syntax (or guard let if you prefer), but I wouldn't recommend this, because it (potentially) can crash your app if element will be nil or any other type.

Parse queries do not show most recent data

import UIKit
import Parse
class loadMainViewController: UIViewController {
//create new pfQuery - This is the bridge between our app and Parse: "trivia" is our class name on Parse
let queryTrivia: PFQuery = PFQuery(className:"trivia")
#IBOutlet weak var label1: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
//retrieve data from parse query
retrieveTrivia()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func retrieveTrivia() {
//This CLOSURE gives access to all objects in "trivia" class using our queryTrivia Bridge
queryTrivia.findObjectsInBackgroundWithBlock { (objects:[PFObject]?, error:NSError?) -> Void in
if( error == nil ){
print("error is nil")
}
var didLoad = true
// Loop through the objects array
for triviaObject in objects!{
// Retrieve data for each object (key, question, ans2, ans3, correctAns)
let triviaQuest : String? = (triviaObject as PFObject)["question"] as? String
let triviaAns2 : String? = (triviaObject as PFObject)["ans2"] as? String
let triviaAns3 : String? = (triviaObject as PFObject)["ans3"] as? String
let triviaAns : String? = (triviaObject as PFObject)["correctAns"] as? String
let triviaKey : Int? = (triviaObject as PFObject)["key"] as? Int
//Check that items are not nil, and create trivia object, add to triviaQuestions Array
if ( triviaKey != nil && triviaQuest != nil && triviaAns2 != nil && triviaAns3 != nil && triviaAns != nil){
let trivia = triviaQuestion(Key: triviaKey!, Question: triviaQuest!, Answer: triviaAns!, WrongAnswer: triviaAns2!, WrongAnswer2: triviaAns3!)
triviaQuestions.append(trivia) // append to the global array of trivia questions
}else{
self.label1.text = "Network Error"
didLoad = false
}
}
for element in triviaQuestions{
print(element.Key)
}
if (didLoad == true) {
//perform segue to View Controller : Main menu
self.performSegueWithIdentifier("finnishLoad", sender: self)
}
}
}
}
My problem Lies when I query the data in the retrieveTrivia() method. The queries apeare to work with a few Problems. The data being saved in to the TriviaQuestion, TriviaAns, TriviaAns2, TriviaAns3 is old data that I have since changed using The parse website by simply clicking in the cell and editing each feild by hand. Furthermore I cannot seem to get the key field and it is always coming back as nil.
When I run this the triviaAns variable contains "Cow" but, online when looking at the data it says "Mozzarella."
Any idea as to why I would be receiving the wrong data after updating the fields and why the key field is coming back as nil?
Here is what the data looks like now
enter image description here
Make sure that you are connecting to the correct Parse app - Check the keys in the call to setApplicationId:clientKey in your App Delegate match those shown in your app's settings on Parse.com

Passing objectId from viewDidLoad to another function using Parse method getObjectInBackgroundWithId not working

I'm a beginner working with Parse and Swift. I need to update the object referred to in my viewDidLoad in another function within the same controller. How do I pass the currently loaded object's objectId without having to hardcode it like this:
query.getObjectInBackgroundWithId("8DkYgraEJq")
Here is my viewDidLoad function:
override func viewDidLoad() {
var query = PFQuery(className: "CheckedBaggage")
query.orderByAscending("createdAt")
query.whereKey("respondedTo", notEqualTo: true)
query.getFirstObjectInBackgroundWithBlock {
(CheckedBaggage: PFObject!, error: NSError!) -> Void in
if error != nil {
println("The getFirstObject request failed.")
} else {
// The find succeeded.
self.randomBaggageLabel.text = CheckedBaggage.objectForKey("message") as? NSString
CheckedBaggage.save()
println(CheckedBaggage.objectId)
let baggageId = CheckedBaggage.objectId
println("Successfully retrieved the object.")
}
}
I would like to try and pass the variable baggageId, which should be the object's ID as a string, as an argument to the getObjectInBackgroundWithId block in my carryIt function:
#IBAction func carryIt(sender: AnyObject!) {
println("CarryIt is being called")
var query = PFQuery(className: "CheckedBaggage")
query.getObjectInBackgroundWithId(baggageId) {
(CheckedBaggage: PFObject?, error: NSError?) -> Void in
if error != nil {
println(error)
} else if let CheckedBaggage = CheckedBaggage {
println("object hello!")
CheckedBaggage["respondedTo"] = true
CheckedBaggage["response"] = self.kindnessMessage.text
CheckedBaggage.save()
}
}
}
But I'm getting an "unresolved identifier" error. It updates my Parse database perfectly fine if I hardcode the object ID, but I can't do it this way. Here's a screenshot of the error:
Thank you so much for your help!
You have to initialize baggageId. To use it in multiple functions, it must be scoped at class level as the comment said. To set it after it has been declared, it must be a "var", not a constant "let".
var baggageId = ""
func viewDidload() {
var query = ...
query.get... {
baggageId = CheckedBaggege.objectId
}
}
func shipIt() {
var query = ...
query.getObjectWithId(baggageId) ...
}

Swift Not Presenting All text Within Text Field

I am querying information from the parse database, and want to display all the data in a text field. My code prints everything into the output box, however the actual iOS simulator only displays one piece of the entire data. Would appreciate any suggestions!
#IBOutlet var Groupnames: UITextView!
#IBAction func QueryDataAction(sender: AnyObject) {
var query = PFQuery(className: "BeaterGroups")
query.findObjectsInBackgroundWithBlock { (object: [AnyObject]?, error: NSError?) -> Void in
if error == nil && object != nil {
if let object = object as? [PFObject] {
for objects in object {
println(objects.valueForKey("GroupName")!)
let groupname = objects.valueForKey("GroupName") as! String
self.Groupnames.text = groupname
}
}
}
}
}
You are probably only getting the text for the last object. You need to append to the text, not assign to it.
For example, initialize the text field to "" prior to entering the loop, then change the assignment line as follows as in this excerpt:
self.Groupnames.text = ""
for objects in object {
println(objects.valueForKey("GroupName")!)
let groupname = objects.valueForKey("GroupName") as! String
self.Groupnames.text = self.Groupnames.text + groupname + " "
}
This will separate the objects with a space; you can change the separator if you wish.

swift - retrieve objectId field causes fatal error

Here is my code:
#IBAction func saveSettings(sender: AnyObject) {
var settings:PFObject = PFObject(className: "Settings")
settings["routes"] = routesSetting as String
settings["sortBy"] = sortBySetting as String
settings["user"] = PFUser.currentUser()
settings.saveInBackgroundWithBlock{(success:Bool!, error:NSError!) ->Void in
if success != nil {
NSLog("%#","OK-settings data saved")
NSLog("%#",self.routesSetting as String)
}
else
{
NSLog("%#",error)
}
}
}
#IBAction func updateSettings(sender: AnyObject) {
var settings:PFObject = PFObject(className:"Settings")
var id = settings["objectId"] as String
var query = PFQuery(className:"Settings")
println(settings)
println(id)
println(query)
query.getObjectInBackgroundWithId(id) {
(settings: PFObject!, error: NSError!) -> Void in
if error != nil {
NSLog("%#", error)
} else {
settings["routes"] = self.routesSetting as String
settings["sortBy"] = self.sortBySetting as String
settings.save()
}
}
I can run the saveSettings code with no issues. I have set it up to run when a new user signs up with the application. I have verified that a new row is inserted into the settings table in the Parse cloud DB. But I would now like to simply UPDATE the single row instead of create a new row every time there is a save. So I have been working on the updateSettings function. I have followed the Parse documentation for updating objects (https://parse.com/docs/ios_guide#objects-updating/iOS). When I click on the Update button to run the function, I get:
fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)
The line it points to is:
var id = settings["objectId"] as String
I am a complete beginner to Parse.
Some recent additional information:
The results of the println statements:
<Settings: 0x7fd423805260,
objectId: new, localId: (null)> {
}
nil
<PFQuery: 0x7fd4217191f0>
So part of the problem is it is not retrieving the objectId?
PFObject has a property called "objectId", it is not stored in a dictionary, so you can return it as
var id = settings.objectId

Resources