Hello I want to get some data from my parse.com class called "Tags" in this class there are two 3 cols "objectID", "username" and "tagtext". I want to read a record finding by ID and afterwords I want to save "useername" and "tagtext" into two strings. I have done it like it is in the parse.com documentation:
#IBAction func readAction(sender: UIButton) {
var query = PFQuery(className:"Tags")
query.getObjectInBackgroundWithId("IsRTwW1dHY") {
(gameScore: PFObject?, error: NSError?) -> Void in
if error == nil && gameScore != nil {
println(gameScore)
} else {
println(error)
}
}
let username = gameScore["username"] as! String
let tagtext = gameScore["tagtext"] as! String
println(username)
println(tagtext)
}
I get an error called fatal error: unexpectedly found nil while unwrapping an Optional value , please tell me what is wrong in my code.
My class:
The problem is that:
let username = gameScore["username"] as! String
let tagtext = gameScore["tagtext"] as! String
gameScore["username"] and gameScore["tagtext"] can return nil values, and when you say as! String you say that it will be a String, and it is nil.
Try something like:
let username = gameScore["username"] as? String
let tagtext = gameScore["tagtext"] as? String
your error is happening because of that, but your final code should look like this:
#IBAction func readAction(sender: UIButton) {
var query = PFQuery(className:"Tags")
query.getObjectInBackgroundWithId("f3AXazT9JO") {
(gameScore: PFObject?, error: NSError?) -> Void in
let username = gameScore["username"] as? String
let tagtext = gameScore["tagtext"] as? String
println(username)
println(tagtext)
if error == nil && gameScore != nil {
println(gameScore)
} else {
println(error)
}
}
}
Because the getObjectInBackgroundWithId is async.
You are trying to read from your response object gameScore but it is still nil because getObjectInBackgroundWithId is an asynchronous method meaning that it will return a result once it is finished. Put the two lines inside the handler and start from there.
Related
I have a Cloud Code function that returns several objects, with some of them being Booleans. I would like to do something in my Swift code, based on the boolean values of the returned objects, as seen below. However, I keep getting multiple errors in my implementation.
Cloud Code
Parse.Cloud.define("checkCharge", function(request, response){
stripe.charges.retrieve(request.params.charge, function(err, charge) {
if(err){
console.log(err);
response.error(err);
}else{
console.log("Successfully checked the charge");
response.success(charge);
}
});
});
Swift Code
PFCloud.callFunctionInBackground("checkCharge", withParameters: ["charge": orderCharge]) { (success: AnyObject?, error: NSError?) -> Void in
// if let responseJSON: [String: Bool] = success as? [String: Bool] {
if error == nil{
// let responseString = response as? String
// let chargeCaptured: Bool = success["captured"]
let objects = success as! NSArray
for object in objects {
let chargeCaptured = object["captured"] as! Bool
let chargeRefunded: Bool = success["refunded"]
let chargePaid: Bool = success["paid"]
if chargeCaptured == true || chargeRefunded == true || chargePaid == true{
print("charge already processed charge")
object.deleteInBackground()
}else{
self.storyboard
}
I get errors such as ambiguous use of subscript and type AnyObject has no subscript members, whenever I try to set a constant. I also get the error cannot convert type Bool to Bool.
Problem:
After casting into an NSArray you were trying to use it like a dictionary.
Code:
See if this fixes the issues for you:
PFCloud.callFunctionInBackground("checkCharge", withParameters: ["charge": orderCharge]) { data, error in
//If there is an error, code will not proceed, it will exit
guard error == nil else {
print("error = \(error!)")
return
}
//If data is not a dictionary of the type [String : Any] it will exit
guard let objects = data as? [String : Any] else {
print("data is not of the type [String : Any]")
print("actual data type of data = \(type(of: data))")
return
}
if let chargeCaptured = objects["captured"] as? Bool,
let chargeRefunded = objects["refunded"] as? Bool,
let chargePaid = objects["paid"] as? Bool,
chargeCaptured == true || chargeRefunded == true || chargePaid == true {
print("charge already processed charge")
object.deleteInBackground()
}
else {
print("Else condition")
}
}
Suggestion:
Please use Swift native types where ever possible
Use guard, if let to conditionally unwrap optionals
It would help if you learn the Swift basics.
Use Control + I shortcut to format your code in Xcode
It turned out the cloud code returned values as NSDictionary. So this is what I did in Swift.
PFCloud.callFunctionInBackground("checkCharge", withParameters: ["charge": orderCharge]) { (success: AnyObject?, error: NSError?) -> Void in
if error == nil{
let objects2 = success as! NSDictionary
let chargeCaptured = objects2.objectForKey("captured") as! Bool
let chargeRefunded = objects2.objectForKey("refunded") as! Bool
let chargePaid = objects2.objectForKey("paid") as! Bool
}
}
I am saving a parse query to a array but i ket the following error on if let objects = objects as? [PFObject]
And the following error happens Downcast from '[PFObject]?' to '[PFObject]' only unwraps optionals.
any one know how to solve this?
func getArray(funcstring: String){
var userGeoPoint: PFGeoPoint
PFGeoPoint.geoPointForCurrentLocationInBackground {
(geoPoint: PFGeoPoint?, error: NSError?) -> Void in
if error == nil {
userGeoPoint = geoPoint!
}
}
var searchQuery: [String] = [String]()
var query = PFQuery(className:"User")
query.whereKey("geoLocation", nearGeoPoint:userGeoPoint)
query.limit = 100
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
if error == nil {
if let objects = objects as? [PFObject] {
for object in objects {
self.searchQuery.append(object.objectForKey("objectId") as! String)
}
}
} else {
print("\(error?.userInfo)")
}
}
}
objects is declared as [PFObject]?.
You're going to downcast the object to something the compiler already knows.
Just check for nil
if let unwrappedObjects = objects {
for object in unwrappedObjects {
self.searchQuery.append(object.objectForKey("objectId") as! String)
}
}
or still "swiftier"
if let unwrappedObjects = objects {
self.searchQuery = unwrappedObjects.map{ $0["objectId"] as! String }
}
I have a className called SearchPreferences and it is empty until the current user makes a selection. When they make a selection a new row is created in this class with the updated info. The problem is if the user goes back and makes another selection I am creating a new row again instead of just updating the column. Here is the code that is saving the info but on a new row:`
let music = PFObject(className: "SearchPreferences")
music["music"] = table_data[indexPath.row]
// music["user"] = PFUser.currentUser()!.username!
music.saveInBackgroundWithBlock{(success, error) -> Void in
if error == nil {
music.saveInBackground()
print("success")
} else {
print("error")
}
}
`
All I can find is SQL and PHP online help. I tried the code below to call objId but I don't know it as its empty so it returns the below error.
The code below returns the error
No results matched the query. (Code: 101, Version: 1.7.5)
let query = PFQuery(className:"SearchPreferences")
query.getObjectInBackgroundWithId("musicSearch") {
(searchPreference: PFObject?, error: NSError?) -> Void in
if error != nil {
if let searchPreference = searchPreference {
searchPreference["musicSearch"] = self.table_data[indexPath.row]
searchPreference.saveInBackground()
if error == nil {
query.whereKeyDoesNotExist("musicSearch")
let searchPreference = PFObject(className: "SearchPreferences")
searchPreference["musicSearch"] = self.table_data[indexPath.row]
searchPreference.saveInBackgroundWithBlock{(success, error) -> Void in
The same can be send for this attempt:
var query = PFQuery(className:"SearchPreferences")
query.getObjectInBackgroundWithId("musicSearch") {
(searchPreference: PFObject?, error: NSError?) -> Void in
if error != nil {
print(error)
} else if let searchPreference = searchPreference {
searchPreference["musicSearch"] = self.table_data[indexPath.row]
searchPreference.saveInBackground()
}
}
I am trying to figure out how to either before running the query check if it is empty and if it is carry out my initial query. Parse docs only tell you how to save to classname _User not a second classname.
Here is an example on duplicated record update from parse community, you can use the same method to apply it with your code.
let adventureQuery = PFQuery(className: “Class Name“)
adventureQuery.limit = 1000
adventureQuery.addDescendingOrder(“Column Name”)
adventureQuery.getFirstObjectInBackground { (Success, error) in
Success?.setValue(self.toolsTitleTextField.text, forKey: "toolsTitle")
Success?.setValue(self.locationTextField.text, forKey: "location")
Success?.setValue(self.dateTextField.text, forKey: "createrDate")
Success?.saveInBackground(block: { (success, error) in
if (success){
Utility.showAlert("Success!", message: "Insert SuccessFully", viewController: self)
}
else{
let viewController = self.storyboard?.instantiateViewController(withIdentifier: "") as! ViewController
self.navigationController?.pushViewController(viewController, animated: true)
}
})
}
The line in question is "let productImageFile = productData!["productImage"] as! PFFile" which gives me the error "fatal error: unexpectedly found nil while unwrapping an Optional value
(lldb)". The only answers I've found have involved making sure I am not trying to unwrap explicitly defined optionals (I think that's the term), but I messed around with the optionals, and which I unbind and when, but I'm having no luck. No other source has been able to solve this specific issue for me and I'm stuck. Please help.
override func viewDidLoad() {
super.viewDidLoad()
//Create new PFQuery to retrieve info from Parse
var query: PFQuery = PFQuery(className: "MyProduct")
//function to get the data
func getProductData (){
//call function to get the data from parse by specifyng an objectId
query.getObjectInBackgroundWithId("XXXXXXXXXX") {
(productData:PFObject?, error:NSError?) -> Void in
if error == nil && productData != nil {
//Extract values from the productData PFObject and store them in constants
let dayOfTheWeek = productData!.objectForKey("day") as! String
let productTitle = productData!.objectForKey("productTitle") as! String
//-----start image loading
let productImageFile = productData!["productImage"] as! PFFile
productImageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
if let imageData = imageData {
let image = UIImage(data:imageData)
self.productImageView.image = image!
} else {println("Could not load image.")}
}
}
//-----end image loading
let productPrice = productData!.objectForKey("productPrice") as! String
let productDescription = productData!.objectForKey("productDescription") as! String
//take the saved constants and assign their values to the labels and UIImage on screen
self.productTitleLabel.text = productTitle
self.dayOfTheWeekLabel.text = dayOfTheWeek
self.productPriceLabel.text = productPrice
self.productDescriptionLabel.text = productDescription
} else if error != nil {
println("Could not load data from Parse")
}
}
}
I assume not for all products you have an image, so you need to update your code as following:
if let productImageFile = productData!["productImage"] as? PFFile {
productImageFile.getDataInBackgroundWithBlock {
(imageData: NSData?, error: NSError?) -> Void in
if error == nil {
if let imageData = imageData {
let image = UIImage(data:imageData)
self.productImageView.image = image!
} else {println("Could not load image.")}
}
}
}
This will guarantee that productImageFile will be processed only if response of productImage is PFFile.
Ensure you are getting valid data if your error is not printing anything useful. Check the data length and see if it corresponds to the file size.
Also, check to see if the imageView is setting the image on the main thread, it will not show if called from a background thread.
dispatch_async(dispatch_get_main_queue(), ^ {
self.productImageView.image = image!
}
Then i try to convert a key from PFObject to a String it gives me a error. I can't find anything on Parses website. Please help
var findProgram = PFQuery(className: "Programs")
findProgram.getObjectInBackgroundWithId(data["program"] as! String!, block: { (object: PFObject?, error) -> Void in
if error == nil {
var objects = object["name"] as! String
print(objects)
self.programUpdated.append(object?.createdAt as NSDate!)
}
})
I think this is what you're going to have to do, try this:
//explicitly giving the objects var a type of String
var objects:String = object["name"] as! String
You shouldn't get an error after that.
Good luck!
I think this will be the batter way to do that:
if let objects = object?.objectForKey("name") as? String{
print(objects)
self.programUpdated.append(objects?.createdAt as NSDate!)
}