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.
Related
I am making a running app and would like to have a viewController in which the user has running tips and facts randomly display on the field. I would like to query parse for the objectIds to then reference the id and assign the label the tip or fact. Currently I have hard coded the Ids into the app but I would like that array to contain the results from the query the code is as follows:
func GetObjectID(){
ObjectIDs = ["id1","id2","id3","id4","id5","id6","id7","id8"]
RandomID = Int(arc4random_uniform(UInt32(ObjectIDs.count)))
}
func TheInfo(){
GetObjectID()
var query : PFQuery = PFQuery(className: "FactsandTips")
query.getObjectInBackgroundWithId(ObjectIDs[RandomID]){
(ObjectHolder : PFObject?, error: NSError?) -> Void in
if (error == nil) {
self.fact = ObjectHolder!.valueForKey("Fact") as? String
self.tips = ObjectHolder!.valueForKey("Tips") as? Array
if(self.tips.count > 0){
self.factLabel.text = self.fact
self.Button1.setTitle(self.tips[0], forState: UIControlState.Normal)
self.Button2.setTitle(self.tips[1], forState: UIControlState.Normal)
self.Button3.setTitle(self.tips[2], forState: UIControlState.Normal)
self.Button4.setTitle(self.tips[3], forState: UIControlState.Normal)
}
} else {
print("There is something wrong!")
}
}
}
I am using swift, Xcode7, and parse as my backend
Below is the code I use to query a Parse table, retrieve all results and add it all into an array. I then use the array as the source for a pickerView.
var query:PFQuery = PFQuery(className: "Drivers")
query.addAscendingOrder("Name")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects as? [PFObject] {
for object in objects {
self.astrDrivers.append(object["Name"]! as! String)
}
}
self.pkvDriverTrack.reloadAllComponents()
} else {
print("Error: \(error) \(error!.userInfo)")
}
}
Note the line self.astrDrivers.append(object["Name"]! as! String). This is adding the Name column of each record to my self.astrDrivers array.
If you wanted to do retrieve multiple columns, your best bet is to create a custom object like below:
class ObjectNewFact:NSObject {
var column1:String = String() // You might want to choose more descriptive variable names (I just don't know what your column names are).
var column2:Int = Int()
// etc.
}
You could then create an array of ObjectNewFacts with a line like
var aFacts:[ObjectNewFact] = [ObjectNewFact]()
Then you could amend your routine to retrieve the data from Parse to:
var query:PFQuery = PFQuery(className: "Drivers")
query.addAscendingOrder("Name")
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects as? [PFObject] {
for object in objects {
var NewFact:ObjectNewFact = ObjectNewFact()
NewFact.column1 = object["Column1"] as! String
NewFact.column2 = object["Column2"] as! Int
self.aFacts.append(NewFact)
}
}
self.pkvDriverTrack.reloadAllComponents()
} else {
print("Error: \(error) \(error!.userInfo)")
}
}
Now you have an array full of facts. You might want to go down this custom object approach because you can also include things like the Fact ID or how many times the fact has been shown (if you're keeping track of that sort of thing). It provides a more flexible solution for any changes in the future.
I hope this helped.
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
I am building a checkin app, and am having trouble filling my tableview with guests stored using Parse. I get an error when trying to append the objects. I also have a user login that I followed from a Udemy course. In the course he showed how to display PFUsers, but I can't get it to work using PFObjects. Any help would be great on this.
Here is the working code with PFUsers.
var users = [""]
override func viewDidLoad() {
super.viewDidLoad()
var query = PFUser.query()
query!.findObjectsInBackgroundWithBlock({ (objects: [AnyObject]?, error: NSError?) -> Void in
self.users.removeAll(keepCapacity: true)
for object in objects! {
var user:PFUser = object as! PFUser
self.users.append(user.username!)
}
self.tableView.reloadData()
})
}
And here is the nonworking code with PFObjects.
var users = [""]
override func viewDidLoad() {
super.viewDidLoad()
var query = PFQuery(className: "TestObject")
query.findObjectsInBackgroundWithBlock({ (objects: [AnyObject]?, error: NSError?) -> Void in
self.users.removeAll(keepCapacity: true)
for object in objects! {
var guest = object as! PFObject
self.users.append(guest.foo!)
}
})
}
The error shows on the line
self.users.append(guest.foo!)
And the error says "'PFObject' does not have a member named 'foo'"
You define your PFUser object with the variable user, this will make the first example work (you get the name of the user) The second example doesn’t work cause you still define the PFObject as user but try to access the name of guest which is not defined.
You could either go with the first example or change
var user:PFObject = object as! PFObject
With
var guest:PFObject = object as! PFObject
Either way, it doesn’t matter for your code, it is just the name of the variable.
This explanation will fix your “Use of unresolved identifier ‘guest’”
But this isn’t your only problem,
the PFUser object which the first example uses is a special kind of a PFObject, the PFUser class does have a .name which refers to (obviously) the name of the user. Not every PFObject has a name though so you can’t just access the .name of a PFObject. Parse has an excellent documentation about retrieving objects I would first access this documentation. If this is still unclear to you, you can open another specific question about your new problem.
To retreive the data from an object you need to use []
Let’s suggest we have a class named gameScore with the following info
score: 1337, playerName: “Sean Plott”, cheatMode: false
We would do that as follows
var gameScore = PFObject(className:"GameScore")
gameScore["score"] = 1337
gameScore["playerName"] = "Sean Plott"
gameScore["cheatMode"] = false
gameScore.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
if (success) {
// The object has been saved.
} else {
// There was a problem, check error.description
}
}
To retrieve the object you need to query (as you already did in your post)
Ones you’ve received the data you can extract it as follows:
let score = gameScore["score"] as Int
let playerName = gameScore[“playerName"] as String
let cheatMode = gameScore["cheatMode"] as Bool
I figured it out, I needed to get the object label as a string before I could append it to the array to then add it to the tableview.
Here is the working code:
var users = [""]
override func viewDidLoad() {
super.viewDidLoad()
var query = PFQuery(className: "TestObject")
query.findObjectsInBackgroundWithBlock({ (objects: [AnyObject]?, error: NSError?) -> Void in
self.users.removeAll(keepCapacity: true)
for object in objects! {
var foo = object.objectForKey("foo") as? String
self.users.append(foo!)
}
self.tableView.reloadData()
})
}
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
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