Search code examples
cocoa-touchmkannotation

Setting MKAnnotation coordinates in real time


I have a Map Point object which conforms to MKAnnotation Protocol. It works as expected until I try to change its coordinates in real time.

In the beginning I tried to use :

[map_point setCoordinate : new_coordinate];

It did not work because the property is "read-only". Apple documentation says I should add a custom "setCoordinate" and it needs to be KVO compliant.

Have read documentation about KVO. Wish somebody could give a basic example on how to make setCoordinate KVO compliant.


Solution

  • Simply implementing a setCoordinate: method with that exact format will automatically comply with KVO/KVC. You don't need to do anything extra:

    - (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate
    {
        //In this example, the ivar in this class that holds the coordinate
        //is named "coord".  Simply assign the new value to it...
        coord = newCoordinate;
    }
    

    With the method named exactly like that (you can change the parameter name newCoordinate though), KVO notifications will automatically be issued for you.

    See Do you need to call willChangeValueForKey: and didChangeValueForKey:? for details on this.

    However, if you need to change the coordinate in a non-compliant method, you could generate the KVO notifications manually:

    - (void)someNonCompliantMethod
    {
        [self willChangeValueForKey:@"coordinate"];
        coord = someNewCoordinate;
        [self didChangeValueForKey:@"coordinate"];
    }
    


    Note that you can entirely avoid implementing a setCoordiante: method (and ivar) manually simply by declaring the coordinate property as assign or readwrite instead of readonly:

    @property (nonatomic, assign) CLLocationCoordinate2D coordinate;
    //and @synthesize in the @implementation
    

    Now, you don't need to write a custom getter or setter and will be able to directly assign to coordinate from the code that instantiates this class:

    [map_point setCoordinate : new_coordinate];
    

    or:

    map_point.coordinate = new_coordinate;
    


    Finally, if the only properties you need for your annotation are title, subtitle, and coordinate, you can also avoid creating a custom class at all and use the built-in MKPointAnnotation class instead which implements a writeable coordinate property.