Not very well versed with iOS Development. I have a very stupid question to ask!! is there a difference between Placemarks and Annotations. Ive been through some Apple Developer documents. Somewhere it was mentioned Placemarks have areaOfInterest property. Im not sure if annotations have one too.
Apart from that how do Placemarks differ from Annotations??
Thanks in Advance!! Cheers
Annotations offer a way to highlight specific coordinates on the map and provide additional information about them. You can use annotations to call out specific addresses, points of interest, and other types of destinations. When displayed on a map, annotations typically have some sort of image to identify their location and may also have a callout bubble providing information and links to more content.
For Placemarks See This Link
http://ioscreator.com/display-placemarks-with-mapkit/
From the MKPlacemark class reference:
A placemark is also an annotation and conforms to the MKAnnotation protocol, whose properties and methods include the placemark coordinate and other information. Because they are annotations, you can add them directly to the map view.
MKPlacemark inherits from CLPlacemark, which has property areasOfInterest.
A look at the class references for both classes and the protocol should clear things up.
Related
I'm coding an iOS app with a Mapbox MGLMapView displayed on my view controller, on this mapView I draw a route using a MGLShapeSource, MGLLineStyleLayer and MGLPolylineFeature objects.
Here is the code :
let newSource = MGLShapeSource(identifier: "polylineBlue", shape: self.polylines, options: nil)
mapView.style?.addSource(newSource)
let newStyle = MGLLineStyleLayer(identifier: "polylineBlueLayer", source: source)
...styling my layer...
mapView.style?.addLayer(newStyle)
source.shape = self.polylines // a MGLPolylineFeature object
Works great for the route but there is one issue : is appears on top of my annotations.
I add the annotation with regular mapView function :
mapView.addAnnotations([..my MGLPointAnnotation objects...])
I've tried searching here and other websites, I only found one topic and there is nothing helpful except someone saying that we can't set a z layer position on annotations so no fix for that.
Does someone know a workaround ? Do I have to use that : https://docs.mapbox.com/ios/maps/examples/add-marker-symbol/ ?
if so, do I need to create one MGLSymbolStyleLayer per annotation ?
Sounds like a painful solution for a so basic need...
Thanks !
In the code snippets that you provided, it appears that your annotations are MGLPointAnnotations. If this is the case, you would need to add your MGLPointAnnotations to an MGLShapeSource using MGLShapeSource(initWithIdentifier:shapes:) and then use this shape source to create your MGLSymbolStyleLayer.
To ensure that the annotations show on top of your route, you will need to verify when each layer is being added, as layers are “baked” into the map before rendering. If you add the MGLSymbolStyleLayer responsible for the annotations after the route is added to the map, they will appear on top. If you add them before the route loads, they will appear below the route line layer. Only one MGLSymbolStyleLayer is needed.
For additional information on markers and annotations, please take a look at Mapbox’s documentation here.
I've been working with gmaps for iOS sdk and have this problem: each time the map pans or zooms and finishes(Im using the Delegate idleAtCameraPosition) in my serverside I compare the coordinates of the center of the map, in order to mark pins of places around it. I save the places in an array of "Places" objects, when they are close enough(1km) from the center coordinates.
My problem is that I haven't been able to avoid adding repeated objects to the array, so every time I do pan the map but don't change the camera position that much, the existing markers in the screen are re-added to the Places array. I tried using this code, but it doesn't work and the array can grow infinitely until crashing the app:
if(!arrayProp.contains(place)){
arrayProp.append(place)
}
but it doesn't work.
I also have another array of GMSMarkers that feeds itself from the Places array; tried this code to avoid re-creating markers in the map with Places objects that already existed:
for place in arrayProp {
let pinPlace = PlaceMarker(propied: place)//custom GMSMarker class
if(self.markerArray.contains(pinPlace) == false ) {
self.markerArray.append(pinPlace)
pinPlace.map = self.mapaGoogle
} else {
pinPlace.map = nil
}
}
Any help would be greatly appreciated; thank you
Probably your Place is using a default definition of Equatable which is not what you expect. You'll need something like this for contains() to work as expected:
struct Place: Equatable {
let there: Bool
}
func ==(lhs: Place, rhs: Place) -> Bool {
return lhs.there == rhs.there
}
Check Place's definition, or create one if it's using a default that checks only the necessary fields.
Have you tried using a Set? Swift supports a Set collection type that handles uniqueness for you. The type you store in the set just needs to implement Hashable, which you can implement on your GMSMarker class. (Or, if it's not your class, you can add an extension to implement the Hashable protocol)
See Apple's documentation on Sets.
If you're loading all of the new objects anyways, then you can just empty out the existing array before adding the new values. self.markerArray.removeAll() then add your new objects.
I queried a set of coordinates for users around me from Parse(PFGeoPoint) and I have created annotations for said locations/coordinates. I will be updating the users location every 5 seconds and updating the location of the annotations, everything is working fine except for the fact that I'm having to remove and add annotations instead of them moving on their own similar to lyft, is there a way to do this in swift? please reply, thank you!!
Yes it is. As I can see from your tags, you are using MKPointAnnotation , so you an access its coordinate property and update it as you wish.
var coordinate: CLLocationCoordinate2D
So all you have to do is set it up like this:
annotation.coordinate = newCoordinate
For more information, please look at Accessing the Annotation’s Location.
I have added a button on my .xib file with which I want to delete the last annotation that has been added.
So on the Touch-Down action I have implemented this:
-(IBAction)DeleteAnnotation:(id)sender {
[mapview removeAnnotation:[mapview.annotations lastObject]];
}
and I have even tried it this way:
-(IBAction)DeleteAnnotation:(id)sender {
[self.mapview removeAnnotation:self.mapview.annotations.lastObject]];
}
where mapview is my MKMapView Outlet.
The problem I encounter with both ways is that I have to press this specific button quite a few times before an annotation is removed.
Furthermore, the annotations remove themselves in a quite random way.
Is there something I am doing wrong or is it a software and simulator matter?
The annotations property of MKMapView is not guaranteed to return the annotations in the same order that you added them.
Making the assumption that the annotations array property will return the annotations in the same order that you added them is most likely the reason for the "strange" behavior you see. Please see these related answers for some more details:
MKMapView annotations changing/losing order?
How to reorder MKMapView annotations array
To get the behavior you want (which I assume is simply "remove the last annotation that was added explicitly by my code"), here are three possible approaches (there may be others):
Simplest approach is to keep a reference in a strong property to the last annotation you add (update the reference when you call addAnnotation). When you want to remove the "last annotation added", pass that saved reference to removeAnnotation. For example:
//in the interface...
#property (nonatomic, strong) id<MKAnnotation> lastAnnotationAdded;
//in the implementation...
//when you add an annotation:
[mapview addAnnotation:someAnnotation];
self.lastAnnotationAdded = someAnnotation; //save the reference
//when you want to remove the "last annotation added":
if (self.lastAnnotationAdded != nil)
{
[mapview removeAnnotation:self.lastAnnotationAdded];
self.lastAnnotationAdded = nil;
}
Another option is to loop through the map view's annotations array and search for the "last" annotation (or whatever attribute you're interested in). Once you have a reference to the "last" one (which may not necessarily be the last object in the array), you can call removeAnnotation on it. This approach assumes you have some property in the annotation objects themselves that let you identify an annotation as the "last" one. This may not always be possible.
Another option is to keep your own array of annotations and add annotation objects to this array whenever you call addAnnotation. This is similar to keeping the single reference to just the "last annotation added" except you keep track of the entire list in an order you can rely on. To remove the "last" one, you would get lastObject from your array instead of the map view's (assuming you keep the array in that order). You have to make sure to keep your array in sync as you add/remove annotations from the map.
Simple Question: Seems I cannot find the tag attribute for MKPointAnnotation class. It return error;
MKPointAnnotation *annotation = [[HCIAnnotationViewController alloc]
initwithHouse:house];
The following returns error (Property tag not found ob object of type "MKPointAnnotation"
NSLog(#"%d",annotation.tag);
My question is, if Im not allowed to set the tag, How am I supposed to detect which annotation was clicked.
The other approaches I followed are
Setting tag for MkAnnotationView, However in this what I found out is that the last annotation when added doesn't immediately call for viewForAnnotation (Might be because I'm adding around 1000 MkPointAnnotations to a small map, so it only calls when it comes to view.).
Please tell me how to resolve this?
Since MKPointAnnotation is not a subclass of UIView, has not a property called tag. Bu you have the property coordinate. I assume you have different coordinates for all of your annotations. So you can detect which one.
You just need to compare the coordinates.