0

Summary: Linking (NOT Query) Annotation with Parse from app

Completed: What I'm trying to do is have the newly created annotation, become a PFObject as a result. The way I am attempting to do this is to get the coordinates based off of the MKPointAnnotation. Then turn that into a PFObject with coordinates. Then able to be Query later as a live update.

Problem Still an issue is that with the code mentioned I'm not able to have the MKPointAnnotation which allows for me to add the title and UIImage, other than that all I would need tips on would be combining all of that together to finally be able to be queried from parse.

func handleLongPress(getstureRecognizer : UIGestureRecognizer) {
    if getstureRecognizer.state != .Began { return }

    let touchPoint = getstureRecognizer.locationInView(self.mapView)
    let touchMapCoordinate = mapView.convertPoint(touchPoint, toCoordinateFromView: mapView)
    createAnnotation(touchMapCoordinate)

}

private func createAnnotation(coordinate: CLLocationCoordinate2D) {
    print("createAnnotation")
    let myAnnotation = MyAnnotation(coordinate: coordinate)
    mapView.addAnnotation(myAnnotation)
    myAnnotation.saveInBackground()


}

    func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
        if !(annotation is MKPointAnnotation) {
    return nil
}

let reuseId = "test"

var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId)
if pinView == nil {
    pinView = MyAnnotation(annotation: annotation, reuseIdentifier: reuseId)
    pinView!.image = UIImage(named:"Cloud9")
    pinView!.canShowCallout = true

    let rightButton: AnyObject! = UIButton(type: UIButtonType.ContactAdd)
    pinView?.rightCalloutAccessoryView = rightButton as? UIView
  • I think you only need to save to Lat and Long values from the annotation you created in Parse. Not the entire object. Then you just recreate the annotation where you fetch the data from Parse. – DogCoffee Jan 28 '16 at 01:37
  • @DogCoffee , I'm attempting to do it the other way around where you create the lat and long + a topic value and saving that with parse. So what happens is when I attempt to save just the coordinates it still conflicts with my let annotation = MKPointAnnotation. – Jamal Rasool Jan 28 '16 at 02:27
  • Just to be clear, what you are trying to achieve is to get the user's latest location and show this on a map with a small region, plus saving the latitude and longitude of the location in Parse? And of course, doing all of this in a simple and readable way. What do you mean by `Query later as a live update`? Query Parse? Or to continue receiving location updates? – Kumuluzz Jan 29 '16 at 07:41
  • @Kumuluzz query parse – Jamal Rasool Jan 29 '16 at 16:27
  • @JamalRasool my posted solution allows you to query Parse relatively easy since it is based on the `PFGeoPoint` model from Parse which exposes some nice location relevant APIs. In your other comment about the solution crashing, could you please elaborate a bit more in order to figure out why it is crashing? – Kumuluzz Jan 29 '16 at 21:59
  • @Kumuluzz I've updated the question with the issue i'm trying to solve. – Jamal Rasool Jan 30 '16 at 02:29
  • FYI Parse is going away in 12 months. – DogCoffee Jan 30 '16 at 05:47
  • I know, what I'll do is build it around it's framework then create my own server to host it in that way. – Jamal Rasool Jan 30 '16 at 05:55

1 Answers1

0

It is not quite clear to me what you are asking about (for example with Linking (NOT Query) or become a PFObject as a result).

I have understood your problem as being the following:

  • A series of CLLocationCoordinate2D are created by the user
  • You want to easily add these coordinates to the MKMapView
  • You want to easily store these coordinates in the Parse backend

I think the best solution for you is to create a custom class which subclasses PFObject and implements MKAnnotation (I'm not quite sure what you mean by and that the only solution is to subclass the PFObject, which at its current state there is no help with that either.)

I've tried to put together a sample project with the following three files. It's nice and clean since you can have the following three lines of code to achieve the two goals outlined above:

let myAnnotation = MyAnnotation(coordinate: coordinate)
mapView.addAnnotation(myAnnotation)
myAnnotation.saveInBackground() // Handle this background save better

Let me know if this helps with your problem, otherwise please rephrase your question to be more clear.


UPDATE 1: OP wanted title, subtitle and image functionality.

The title and subtitle properties are not unique to MKPointAnnotation, but rather a part of the MKAnnotation protocol, which is used to create the MyAnnotation in my example. This means you simply need to add these two properties to MyAnnotation in order to get the functionality you want.

Concerning the image, then this is it not a unique feature for MKPinAnnotationView, but again for the more generic MKAnnotationView. In reality, the image property has not purpose in the MKPinAnnotationView. As described in the documentation for the image property:

You can use the `MKAnnotationView` class as is or subclass it to provide custom behavior as needed. 
The `image` property of the class lets you set the appearance of the annotation view without subclassing directly.

When using the MKPinAnnotationView, then the view will always be a pin, which is why the image property has not purpose.

So in order to use this image property, then you'll need to make use of MKAnnotationView in the delegation method mapView:viewForAnnotation: from MKMapViewDelegate.

Remember to set the delegate property of the mapView (I've set it in the storyboard).

I've updated my answer in order to reflect the changes.


The code:

//
//  ViewController.swift
//  ParseAnnotationFun
//
//  Created by Stefan Veis Pennerup on 28/01/16.
//  Copyright © 2016 Kumuluzz. All rights reserved.
//

import UIKit
import MapKit

class ViewController: UIViewController, MKMapViewDelegate {

    // MARK: - Storyboard outlets

    @IBOutlet weak var mapView: MKMapView!

    // MARK: - Gesture Recognizers

    @IBAction func longPressed(sender: UILongPressGestureRecognizer) {
        print("longPressed")
        if sender.state != .Began { return }

        let touchPoint = sender.locationInView(mapView)
        let touchMapCoordinate = mapView.convertPoint(touchPoint, toCoordinateFromView: mapView)
        createAnnotation(touchMapCoordinate)
    }

    // MARK: - Model

    private func createAnnotation(coordinate: CLLocationCoordinate2D) {
        print("createAnnotation")
        let myAnnotation = MyAnnotation(coordinate: coordinate)
        mapView.addAnnotation(myAnnotation)
        myAnnotation.saveInBackground() // Handle this background save better
    }

    // MARK: - MKMapViewDelegate

    func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
        let id = "someIdentifier"
        var view = mapView.dequeueReusableAnnotationViewWithIdentifier(id)

        if view == nil {
            view = MKAnnotationView(annotation: annotation, reuseIdentifier: id)
            view?.canShowCallout = true
            view?.image = UIImage(named: "oranges")
        }

        view?.annotation = annotation
        return view
    }

}    

//
//  MyAnnotation.swift
//  ParseAnnotationFun
//
//  Created by Stefan Veis Pennerup on 28/01/16.
//  Copyright © 2016 Kumuluzz. All rights reserved.
//

import Foundation
import Parse
import MapKit

class MyAnnotation: PFObject, PFSubclassing, MKAnnotation {

    // MARK: - Properties

    @NSManaged var location: PFGeoPoint

    // MARK: - Initializers

    init(coordinate: CLLocationCoordinate2D) {
        super.init()
        location = PFGeoPoint(latitude: coordinate.latitude, longitude: coordinate.longitude)
    }

    override class func initialize() {
        struct Static {
            static var onceToken : dispatch_once_t = 0;
        }
        dispatch_once(&Static.onceToken) {
            self.registerSubclass()
        }
    }

    // MARK: - PFSubclassing protocol

    static func parseClassName() -> String {
        return "AnnotationPins"
    }

    // MARK: - MKAnnotation protocol

    var coordinate: CLLocationCoordinate2D {
        return CLLocationCoordinate2DMake(location.latitude, location.longitude)
    }

    var title: String? = "Awesome title"

    var subtitle: String? = "Random subtitle"

}

//
//  AppDelegate.swift
//  ParseAnnotationFun
//
//  Created by Stefan Veis Pennerup on 28/01/16.
//  Copyright © 2016 Kumuluzz. All rights reserved.
//

import UIKit
import Parse

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

        MyAnnotation.initialize()
        Parse.setApplicationId("xxx",
        clientKey: "xxx")

        return true
    }

}
Kumuluzz
  • 2,012
  • 1
  • 13
  • 17
  • I updated my question on what I'm trying to achieve, but in your fix still doesn't work, in the subclass, it gives me an issue when PFGeopoint has no member coordinate. – Jamal Rasool Jan 29 '16 at 02:50
  • Could you specify which line is failing for you? – Kumuluzz Jan 29 '16 at 07:42
  • I still want the annotation to be able to change image and still retain the title / subtitle proprtion that mkpointannotation provides – Jamal Rasool Jan 30 '16 at 22:10
  • I've updated my answer to include the `image`, `title` and `subtitle` features. If you have any more changes (for example if the `image` functionality is not what you expected), then I will recommend you to create a new question since this is starting to get off topic from the original question of combining an annotation with PFObject. – Kumuluzz Jan 31 '16 at 09:34
  • An irrelevant question, but how would I be able to transfer the GeoPoint to another ViewController, to be saved in an array?. http://stackoverflow.com/questions/35263473/cannot-assign-value-of-type-cllocationcoordinate2d-to-type-pfgeopoint is pretty much my attempt on doing such that. – Jamal Rasool Feb 09 '16 at 02:33