Parse query equalto PFUser Object - parse-platform

This is what I have pulled from the PFUser:
let currentUser = PFUser.currentUser()
currentUser!.refreshInBackgroundWithBlock { (object, error) -> Void in
print("Refreshed")
currentUser!.fetchIfNeededInBackgroundWithBlock { (result, error) -> Void in
let userSchool = currentUser!.objectForKey("school") as! String
And then I want to use the "userSchool" in a Query for Participants.
var query = PFQuery(className:"Participant")
query.whereKey("school", equalTo:userSchool)
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
}
How do I get the equalTo: to signify "userschool" so I can then pull the data?
This is all on the same table too, BTW.

Related

What does [weak self] do and what is this code structure means?

I have couple of questions about the structure of the following code.I assume progressBlock and completionhandlers are callback functions passed to downloadWithDownloadType function. Is my assumption correct? And What does [weak Self] before function parameters do? In what situation do you need that?
func downloadContent(key: String, pinOnCompletion: Bool) {
let manager = AWSUserFileManager.defaultUserFileManager()
let content = manager.contentWithKey(self.prefix + key)
content.downloadWithDownloadType(
.IfNewerExists,
pinOnCompletion: pinOnCompletion,
progressBlock: {[weak self](content: AWSContent?, progress: NSProgress?) -> Void in
guard self != nil else { return }
/* Show progress in UI. */
},
completionHandler: {[weak self](content: AWSContent?, data: NSData?, error: NSError?) -> Void in
guard self != nil else { return }
if let error = error {
// Handle Error
return
}
if let fileData = data {
let rawData = NSString(data: fileData, encoding:NSUTF8StringEncoding) as! String
// Do something
}
//Download Complete
})
}

Parse: Saving data to the main "User" class

I just have basic code for testing purposes.
let user = PFObject(className: "User")
user["email"] = userEmail
user.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
....
}
But I always get this result.
Is the main User class named differently?
You should be using PFUser rather than creating a PFObject with the classname of "User"
let user = PFUser()
user["email"] = userEmail
user.saveInBackgroundWithBlock {
(success: Bool, error: NSError?) -> Void in
...
}

Xcode 7 Error Code "Cannot convert value type([AnyObject]

Heres a copy of my code where the error is giving me, the error is on the line where it says query.findobjectsInBackgroundWithBlock. The full error message is this: `Cannot convert value type ([AnyObject]!, NSError!) -> Void to expected argument type 'PFQueryArrayResultBlock?'
// Retrieve Messages
func retrieveMessages() {
// Create a new PFQuery
var query:PFQuery = PFQuery(className: "Message")
// Call findobjectsinbackground
query.findObjectsInBackgroundWithBlock {(objects:[AnyObject]!, error:NSError!) -> Void in
// Clear the messagesArray
self.messageArray = [String]()
// Loops through the objects
for messageObject in objects {
// Retrieve the text column value of each PFObject
let messageText:String? = (messageObject as! PFObject)["Text"] as? String
// Assign it into our messagesArray
if messageText != nil {
self.messageArray.append(messageText!)
}
}
// Reload the tableview
self.messageTableView.reloadData()
}
}
The method signature had improved in Swift 2.0 with Parse SDK 1.10.0. Replace [AnyObject]! with [PFObject]?. [PFObject] is an optional because Swift doesn't know if it will exist or not.
func retrieveMessages() {
var query:PFQuery = PFQuery(className: "Message")
query.findObjectsInBackgroundWithBlock { (objects: [PFObject]?, error: NSError?) -> Void in
self.messageArray = [String]()
for messageObject in objects {
let messageText:String? = (messageObject as! PFObject)["Text"] as? String
if messageText != nil {
self.messageArray.append(messageText!)
}
}
self.messageTableView.reloadData()
}
}

Parse.com - Download Objects From Database - Show Progress With ProgressBlock

I have Parse class called Product that has 238 rows. Note that this class is not the Parse.com implementation of Product, it is a custom class implemented by myself, as I didn't require all the columns Parse adds to their Product class.
The Product class has a Pointer column (basically a foreign key in SQL tables), called ShopId, because each product belongs to a specific Shop (I have a Parse class called Shop with an ObjectId column used in the Product Pointer.
My Product class also has a File column called imageFile that holds the image of the product.
I want to download all Products from a specific shop, unpackage their image file and put it in my Swift Product class which consists of the PFObject of the Parse Product, and a UIImageView and a UIImage. Here is my Product Class in Swift:
class Product {
private var object: PFObject
private var imageView: MMImageView!
private var image: UIImage
init(object: PFObject, image: UIImage) {
self.object = object
self.image = image
}
func getName() -> String {
if let name = object["name"] as? String {
return name
} else {
return "default"
}
}
func setImageView(size: CGFloat, target: DressingRoomViewController) {
self.imageView = MMImageView(frame:CGRectMake(0, 0, size, size))
imageView.contentMode = UIViewContentMode.ScaleAspectFit
imageView.image = self.image
imageView.setName(object["category"] as! String)
imageView.backgroundColor = UIColor.clearColor()
imageView.userInteractionEnabled = true
let tapGestureRecognizer =
UITapGestureRecognizer(target: target, action: "imageTapped:")
tapGestureRecognizer.numberOfTapsRequired = 1
imageView.addGestureRecognizer(tapGestureRecognizer)
}
func getImageView() -> MMImageView {
return self.imageView
}
}
I am currently downloading all the products just fine, and getting their image file and creating my Swift Products with their images. However my UIProgressView logic is slightly off. I have the UIProgressView running for every product, every time I unpackage the product image. I need to shift the Parse.com ProgressBlock out of the getProduct swift function and into the loadProducts #IBAction. When I try it, it causes a lot of errors before compilation. How do I shift the ProgressBlock up to the loadProducts #IBAction? Here is my current code:
//
// ChooseShopViewController.swift
// MirrorMirror
//
// Created by Ben on 12/09/15.
// Copyright (c) 2015 Amber. All rights reserved.
//
import UIKit
import Parse
class ChooseShopViewController: UIViewController {
var progressView: UIProgressView?
private var allProducts: [Product] = []
private var categories: [ProductCategory] = []
#IBAction func loadProducts(sender: AnyObject) {
let shopQuery = PFQuery(className:"Shop")
shopQuery.getObjectInBackgroundWithId("QjSbyC6k5C") {
(glamour: PFObject?, error: NSError?) -> Void in
if error == nil && glamour != nil {
let query = PFQuery(className:"Product")
query.whereKey("shopId", equalTo: glamour!)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
self.getAllProductsAndCategories(objects, error: error)
}
} else {
print(error)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Create Progress View Control
progressView = UIProgressView( progressViewStyle:
UIProgressViewStyle.Default)
progressView?.center = self.view.center
view.addSubview(progressView!)
}
override func prepareForSegue( segue: UIStoryboardSegue,
sender: AnyObject?) {
if (segue.identifier == "dressingRoom") {
ShopDisplay.sharedInstance.setAllProducts(self.allProducts)
ShopDisplay.sharedInstance.setAllProductCategories(self.categories)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func getAllProductsAndCategories(objects: [AnyObject]?, error: NSError?) {
if error == nil {
if let objects = objects as? [PFObject] {
for product in objects {
self.getCategory(product)
self.getProduct(product)
}
}
} else {
print("Error: \(error!) \(error!.userInfo)")
}
}
func getCategory(product: PFObject) {
if let category = product["category"] as? String {
var alreadyThere: Bool = false
for item in self.categories {
if category == item.rawValue {
alreadyThere = true
break
}
}
if alreadyThere == false {
self.categories.append(ProductCategory(rawValue: category)!)
}
}
}
func getProduct(product: PFObject) {
if let productImage = product["imageFile"] as? PFFile {
productImage.getDataInBackgroundWithBlock ({
(imageData: NSData?, error: NSError?) -> Void in
if let imageData = imageData {
let image = UIImage(data:imageData)
self.allProducts.append(
Product(object: product, image: image!))
}
if let downloadError = error {
print(downloadError.localizedDescription)
}
}, progressBlock: {
(percentDone: Int32) -> Void in
self.progressView?.progress = Float(percentDone)
if (percentDone == 100) {
//self.performSegueWithIdentifier("dressingRoom", sender: UIColor.greenColor())
}
})
}
}
}
I decided to not use the progressBlock, and instead to update my UIProgressView manually with a calculation. So here is the code. It's a little rusty. I could refactor now and maybe implement a calculated variable to make it cleaner. If my solution is a bad practice then I'm appreciative if that gets pointed out, and a better solution suggested (It doesn't seem good for performance to check the UIProgressView.progress value every iteration to perform the completion task of performing the segue).
import UIKit
import Parse
class ChooseShopViewController: UIViewController {
var progressView: UIProgressView?
private var allProducts: [Product] = []
private var categories: [ProductCategory] = []
static var numberOfProducts: Float = 0
#IBAction func loadProducts(sender: AnyObject) {
let shopQuery = PFQuery(className:"Shop")
shopQuery.getObjectInBackgroundWithId("QjSbyC6k5C") {
(glamour: PFObject?, error: NSError?) -> Void in
if error == nil && glamour != nil {
let query = PFQuery(className:"Product")
query.whereKey("shopId", equalTo: glamour!)
query.findObjectsInBackgroundWithBlock {
(objects: [AnyObject]?, error: NSError?) -> Void in
ChooseShopViewController.numberOfProducts =
Float((objects?.count)!)
print(ChooseShopViewController.numberOfProducts)
self.getAllProductsAndCategories(objects, error: error)
}
} else {
print(error)
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Create Progress View Control
progressView = UIProgressView( progressViewStyle:
UIProgressViewStyle.Default)
progressView?.center = self.view.center
progressView?.progress = 0.00
view.addSubview(progressView!)
}
override func prepareForSegue( segue: UIStoryboardSegue,
sender: AnyObject?) {
if (segue.identifier == "dressingRoom") {
ShopDisplay.sharedInstance.setAllProducts(self.allProducts)
ShopDisplay.sharedInstance.setAllProductCategories(self.categories)
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
func getAllProductsAndCategories(objects: [AnyObject]?, error: NSError?) {
if error == nil {
if let objects = objects as? [PFObject] {
for product in objects {
self.getCategory(product)
self.getProduct(product)
}
}
} else {
print("Error: \(error!) \(error!.userInfo)")
}
}
func getCategory(product: PFObject) {
if let category = product["category"] as? String {
var alreadyThere: Bool = false
for item in self.categories {
if category == item.rawValue {
alreadyThere = true
break
}
}
if alreadyThere == false {
self.categories.append(ProductCategory(rawValue: category)!)
}
}
}
func getProduct(product: PFObject) {
if let productImage = product["imageFile"] as? PFFile {
productImage.getDataInBackgroundWithBlock ({
(imageData: NSData?, error: NSError?) -> Void in
if let imageData = imageData {
let image = UIImage(data:imageData)
self.allProducts.append(
Product(object: product, image: image!))
self.progressView?.progress += (100.00 /
ChooseShopViewController.numberOfProducts) / 100.00
print(self.progressView?.progress)
if self.progressView?.progress == 1 {
self.performSegueWithIdentifier("dressingRoom",
sender: UIColor.greenColor())
}
}
if let downloadError = error {
print(downloadError.localizedDescription)
}
})
}
}
}
I found this on the Parse website. It may be useful as it has a block that shows the percentage done that updates regularly during the download!
let str = "Working at Parse is great!"
let data = str.dataUsingEncoding(NSUTF8StringEncoding)
let file = PFFile(name:"resume.txt", data:data)
file.saveInBackgroundWithBlock({
(succeeded: Bool, error: NSError?) -> Void in
// Handle success or failure here ...
}, progressBlock: {(percentDone: Int32) -> Void in
// Update your progress spinner here. percentDone will be between 0 and 100.
})
Did you find a better solution? besides this? I am trying to do something similar.

Xcode 6.3.1 Swift 1.2 library wherekey can't be invoked

Recently note that wherekey on PFQuery does not work. I tried 3 approaches but all failed. I am using parse-library-1.7.2 on Xcode 6.3.
Error for approach1: Cannot invoke 'whereKey' with an argument list of type '(String, AnyObject)'
Error for approach2: 'String?'is not convertible to 'StringLiteralConvertible'
Error for approach3: 'AnyObject?' is not convertible to 'String'
Code is as below. Anyone can help with this please? Thanks in advance.
// Define the query that will provide the data for the table view
class MyController: PFQueryTableViewController {
override func queryForTable() -> PFQuery {
var query = PFQuery(className: "Ticket")
//Approach 1
query.whereKey(sellerIdKey, equalTo: currentPhoneUser["objectId"]!)
//Approach 2
if let sellerId = currentPhoneUser["objectId"] as? String {
query.whereKey(sellerIdKey, equalTo: sellerId)
query.orderByDescending("createdAt")
return query
} else {
fatalError("Can't get Object Id of this user")
}
//Approach 3
if let sellerId = currentPhoneUser["objectId"] as! String {
query.whereKey(sellerIdKey, equalTo: sellerId)
query.orderByDescending("createdAt")
return query
} else {
fatalError("Can't get Object Id of this user")
}
}
}
Turns out to be a swift 1.2 issue.
How to cast AnyObject? to String in Swift 1.2
Below is my final solution that compiles:
override func queryForTable() -> PFQuery {
var query = PFQuery(className: "Ticket")
let objectId = currentPhoneUser?["objectId"] as? String
if let constObjectId = objectId {
query.whereKey(sellerIdKey, equalTo: constObjectId)
} else {
fatalError("Cannot find Object Id of current user")
}
return query
}

Resources