(Swift 2.1) Load annotations for visible region in MKMapView - ios

I am calling API and getting latitude, longitude, title and many other data and storing them into custom data structure. I get 20 results per request.
So i need to show only some of those 20 results into visible area of MKMapView. When user change the region of map, API call should be done and my custom data structure will be filled and again only in visible area annotation should be drawn.
I am calling API again into mapView:regionDidChangeAnimated method but i am not able to show annotation into visible Map area only.
Can anyone help me to figure out how I can show annotation into visible are only?
Note: This is a same question but for Objective-C and I don't understand the answer of #Shmidt, and how I can use that code.

MKMapView has attribute visibleMapRect, then you can use function MKMapRectContainsPoint
let point = CLLocationCoordinate2D(latitude: 0.0, longitude: 0.0)
let mapContainsPoint = MKMapRectContainsPoint(map.visibleMapRect, MKMapPointForCoordinate(point));`

Related

iOS Mapbox SDK - How to add MGLPointAnnotation markers into a map layer

I need to find a way to convert markers from MGLPointAnnotation to MGLShapeSource or similar, in order to add the markers to a map layer and have full control over how to display and cluster them on the map, for example.
I am building an iOS App using MapBox SDK v5.2.
The App generates markers internally (title, subtitle, coordinates and icon image name) and the markers are displayed on the map with a callout when tapped. The markers are created using MGLPointAnnotation() and added to the map using mapView.addAnnotation().
But in order to have full control on how the markers are displayed, for example clustering them based on zoom level or toggling them ON/OFF, I need to add the markers to a Map layer, using, for example, MGLShapeSource and then style.addSource() and style.addLayer().
The problem is I cannot find a way to the converter from MGLPointAnnotation to MGLShapeSource or similar.
I have investigated this but the only solution I can think of is to have the marker information contained in a GeoJSON file. But I want to avoid that as the markers are generated within the App when its running, and not from an external read-only GeoJSON file.
Example on how one single poi is created:
let poi1 = MGLPointAnnotation()
poi1.coordinate = CLLocationCoordinate2D(latitude: 38.788534, longitude: -9.494489)
poi1.title = "poi1"
poi1.subtitle = "This is the text for poi1"
poiTitleImage[poi1.title!] = "icon1"
mapView.addAnnotation(poi1)
You can create an MGLShapeSource with an array of MGLPointAnnotation or MGLPointFeature objects. From there, you can add a clustered layer similar to this clustering example.
If you would also like to assign text or other data for each point, use MGLPointFeature objects, then assign the text as an attributes value.
For example:
var features = [MGLPointFeature]()
for _ in 1...100 {
let point = MGLPointFeature()
let lat = Double(arc4random_uniform(180) / 2)
let lon = Double(arc4random_uniform(360) / 2)
point.coordinate = CLLocationCoordinate2D(latitude: lat, longitude: lon)
point.attributes["title"] = "\(lat) \(lon)"
features.append(point)
}
let source = MGLShapeSource(identifier: "clusteredFeatures",
features: features,
options: [.clustered: true, .clusterRadius: 20])
style.addSource(source)
An example of how to present a callout containing the information can be found on the Mapbox website. It seems like the handleMapTap method may contain what you're looking for.
Essentially, you'll query the map where the user taps. Access the attributes on the selected feature, then display a callout containing that information. The above example uses a UILabel to display the information.
If you would like to use a default callout, please see the handleMapTap method on the dynamically style interactive points example. This example also creates a shape source from JSON data loaded at runtime.

Mapbox: iOS : Calculate remaining Polyline points from location

I'm developing one navigation application, I want to calculate the remaining polyline left. I already drawn the route over the map. As user start navigation, I want to update the remaining polyline points
I have used Turf framework for this case.
import Turf
let stepPoints = LineString(step.coordinates)
let remainingPoints = stepPoints.sliced(from: location, to: nil)

Google Map iOS SDK - clear all markers within and without visible region

So the mapView.clear() method only removes the markers from the map within a visible region where I currently idle at.
I can still see other markers on the map by zooming out or moving around the map. Those markers couldn't be removed cause they were invisible the time I invoked clear().
My current solution is to loop through all markers stored in an array and invoke marker.mapView = nil to make sure each of them gets removed from the map.
Is there any other way to do this more efficiently?
Every time that you add a marker in your GMSMapView you can keep it in an array, and after that when you want to remove all of them you only have to cycle over them making .map = nil
for marker in self.markers {
marker.map = nil
}
self.markers.removeAll()
This is what you can read from GoogleDocumentation about this https://developers.google.com/maps/documentation/ios-sdk/marker#eliminar_un_marcador

How To Detect A User Is Within Range Of An Annotation

So I am working on a project that includes many uses placing annotations all around a map. The annotation, (which is a custom image with a much larger circular range) appears on the screen and, ideally, I would like for a user to be:
Notified if they are within the range of a annotation
and
Not be allowed to place another annotation within the range of another one if the circular pins overlap by, say, more than 25%
I think this is a pretty unique question and should be fun for somebody to help out with, so have fun! Thanks everybody!
You can check the distance from each annotation using
- (CLLocationDistance)distanceFromLocation:(const CLLocation *)location
This method measures the distance between the two locations by tracing
a line between them that follows the curvature of the Earth. The
resulting arc is a smooth curve and does not take into account
specific altitude changes between the two locations.
For more details refer Link
Try this:
let location = CLLocation(latitude: 1, longitude: 1)//Or user's location
let distance = location.distance(from: anotherLocation)
Edit:
As mentioned in the comments, you wanted to create an equidistant point. I suggest manually doing that:
Subtract the annotation's location from he user's location. Then add your distance back to the original one. For example:
The user's location = (1, 1)
The annotation's location = (3, 2)
Vertical difference would be 2
Horizontal difference would be 1
Then:
(3 + 2, 2 + 1)
Your result: (5, 3)
Now you would have two points (the one you just created and the user's location) at each end with a center point (original annotation)

iOS: (Swift) How to show distance from current location and exist annotation on annotation subtitle

I am currently working on map application base on iOS using Swift language. I would like an suggestion because after I plot all the pins on map view
(which I receive data from my server using JSON frameworks call Alamofire)
I would like the subtitle of all annotations on map to show distance from user current location.
Now it can add annotations onto map view but can only show title and subtitle base on information receive from my server.
Thank You.
If you have two CLLocation instances, you can calculate distance with the following code:
var one, two: CLLocation
// assign one and two
let distance = two.distanceFromLocation(one)
CLLocationDistance is just double and distance calculated in meters

Resources