简体   繁体   中英

Parse and Swift - PFGeoPoint with CLLocationManager?

I'm fairly new to the understanding of using CoreLocation and Parse so please bear with me! I code with swift and a lot of SO posts I've been searching have been in Obc-C which i am very unfamiliar with.

.................................................................UPDATE....................................................................... Trying to store current users location into the Parse database but its not working. I get the error:

[Error]: invalid session token (Code: 209, Version: 1.9.1) Optional(Error Domain=kCLErrorDomain Code=0 "(null)")"

Any suggestions / help to point me in the right direction?

import UIKit
import Parse
import CoreLocation

class ViewController: UIViewController, CLLocationManagerDelegate {

var manager: CLLocationManager!
var activityIndicator:UIActivityIndicatorView = UIActivityIndicatorView()

@IBOutlet weak var username: UITextField!
@IBOutlet weak var password: UITextField!

@IBAction func signUp(sender: AnyObject) {

    activityIndicator = UIActivityIndicatorView(frame: CGRectMake(0, 0, 50, 50))
    activityIndicator.center = self.view.center
    activityIndicator.hidesWhenStopped = true
    activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
    view.addSubview(activityIndicator)
    activityIndicator.startAnimating()
    UIApplication.sharedApplication().beginIgnoringInteractionEvents()

    let user = PFUser()
    user.username = username.text
    user.password = password.text

    user.signUpInBackgroundWithBlock { (success, error) -> Void in
        self.activityIndicator.stopAnimating()
        UIApplication.sharedApplication().endIgnoringInteractionEvents()

        if error == nil {

            PFGeoPoint.geoPointForCurrentLocationInBackground { (geoPoint: PFGeoPoint?, error: NSError?) -> Void in
                if error == nil {
                    print("got location successfully")
                    PFUser.currentUser()!.setValue(geoPoint, forKey:"location")
                    PFUser.currentUser()!.saveInBackground()

                } else {
                    print(error)
                }
            }

            self.performSegueWithIdentifier("login", sender: self)

        } else {
            print(error)
        }
    }
}

@IBAction func login(sender: AnyObject) {

    activityIndicator = UIActivityIndicatorView(frame: CGRectMake(0, 0, 50, 50))
    activityIndicator.center = self.view.center
    activityIndicator.hidesWhenStopped = true
    activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyle.Gray
    view.addSubview(activityIndicator)
    activityIndicator.startAnimating()
    UIApplication.sharedApplication().beginIgnoringInteractionEvents()

    PFUser.logInWithUsernameInBackground(username.text!, password: password.text!) { (success, error) -> Void in
        if error == nil {
            self.activityIndicator.stopAnimating()
            UIApplication.sharedApplication().endIgnoringInteractionEvents()
            self.performSegueWithIdentifier("login", sender: self)
        } else {
            print(error)
        }
    }

}

override func viewDidLoad() {
    super.viewDidLoad()

    manager = CLLocationManager()
    manager.delegate = self
    manager.desiredAccuracy = kCLLocationAccuracyBest
    manager.requestWhenInUseAuthorization()
    manager.startUpdatingLocation()

}

I would recommend storing the geopoint within your User class. Also, rather than adding a geopoint to each Post , you should add a pointer to the User who created it. This eliminates the redundancy of storing the location twice and makes sure you don't have to mess with keeping the two variables in sync. Additionally, this is also much better practice than storing the objectId directly.

Update your Post class to have a User pointer column called user . Then instead of

postEvent["userId"] = PFUser.currentUser()!.objectId!

Use

postEvent["user"] = PFUser.currentUser()!

It's also worth pointing out that Parse includes helper methods to get the current user's locations . It's as simple as the following

PFGeoPoint.geoPointForCurrentLocationInBackground {
    (geoPoint: PFGeoPoint?, error: NSError?) -> Void in
    if error == nil {
        // do something with the new geoPoint
    }
}

If you do decide to handle the CLLocationManager yourself, make sure to call stopUpdatingLocation() to save battery life once you've updated the user's location, assuming you don't need continuous location updates.

From there, you can use query constraints and a compound query to get all of the nearby Post objects. In particular, you will want to use whereKey: matchesQuery: as the compound query which only counts as 1 API request.

// User's location
let userGeoPoint = userObject["location"] as PFGeoPoint

// Query nearby Users
let nearbyUserQuery : PFQuery = PFUser.query()
nearbyUserQuery.whereKey("location", nearGeoPoint:userGeoPoint)

// Query Posts constrained to nearby Users
let nearbyPostQuery : PFQuery = PFQuery(className: "Post")

// Use a compound query to constrain the results to nearby Users
nearbyPostQuery.whereKey("user", matchesQuery: nearbyUserQuery)

// Limit the number of Posts if needed
nearbyPostQuery.limit = 20

nearbyPostQuery.findObjectsInBackgroundWithBlock {
    (posts: [PFObject]?, error: NSError?) -> Void in
    // Do something with the Posts
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM