Easy Map Annotation Clustering 📍

Overview

Cluster

Build Status Carthage Compatible Language Version License Platform

Cluster is an easy map annotation clustering library. This repository uses an efficient method (QuadTree) to aggregate pins into a cluster.

Demo Screenshots

Features

  • Adding/Removing Annotations
  • Clustering Annotations
  • Multiple Managers
  • Dynamic Cluster Disabling
  • Custom Cell Size
  • Custom Annotation Views
  • Animation Support
  • Documentation

Requirements

  • iOS 8.0+
  • Xcode 9.0+
  • Swift 5 (Cluster 3.x), Swift 4 (Cluster 2.x), Swift 3 (Cluster 1.x)

Demo

The Example is a great place to get started. It demonstrates how to:

  • integrate the library
  • add/remove annotations
  • reload annotations
  • configure the annotation view
  • configure the manager

Demo GIF

Demo Video

$ pod try Cluster

Installation

Cluster is available via CocoaPods and Carthage.

CocoaPods

To install Cluster with CocoaPods, add this to your Podfile:

pod "Cluster"

Carthage

To install Cluster with Carthage, add this to your Cartfile:

github "efremidze/Cluster"

Usage

The Basics

The ClusterManager class generates, manages and displays annotation clusters.

let clusterManager = ClusterManager()

Adding an Annotation

Create an object that conforms to the MKAnnotation protocol, or extend an existing one. Next, add the annotation object to an instance of ClusterManager with add(annotation:).

let annotation = Annotation(coordinate: CLLocationCoordinate2D(latitude: 21.283921, longitude: -157.831661))
manager.add(annotation)

Configuring the Annotation View

Implement the map view’s mapView(_:viewFor:) delegate method to configure the annotation view. Return an instance of MKAnnotationView to display as a visual representation of the annotations.

To display clusters, return an instance of ClusterAnnotationView.

extension ViewController: MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        if let annotation = annotation as? ClusterAnnotation {
            return CountClusterAnnotationView(annotation: annotation, reuseIdentifier: "cluster")
        } else {
            return MKPinAnnotationView(annotation: annotation, reuseIdentifier: "pin")
        }
    }
}

For performance reasons, you should generally reuse MKAnnotationView objects in your map views. See the Example to learn more.

Customizing the Appearance

The ClusterAnnotationView class exposes a countLabel property. You can subclass ClusterAnnotationView to provide custom behavior as needed. Here's an example of subclassing the ClusterAnnotationView and customizing the layer borderColor.

class CountClusterAnnotationView: ClusterAnnotationView {
    override func configure() {
        super.configure()

        self.layer.cornerRadius = self.frame.width / 2
        self.layer.masksToBounds = true
        self.layer.borderColor = UIColor.white.cgColor
        self.layer.borderWidth = 1.5
    }
}

See the AnnotationView to learn more.

Annotation Styling

You can customize the appearance of the StyledClusterAnnotationView by setting the style property of the annotation.

let annotation = Annotation(coordinate: CLLocationCoordinate2D(latitude: 21.283921, longitude: -157.831661))
annotation.style = .color(color, radius: 25)
manager.add(annotation)

Several styles are available in the ClusterAnnotationStyle enum:

  • color(UIColor, radius: CGFloat) - Displays the annotations as a circle.
  • image(UIImage?) - Displays the annotation as an image.

Once you have added the annotation, you need to return an instance of the StyledClusterAnnotationView to display the styled annotation.

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    if let annotation = annotation as? ClusterAnnotation {
        return StyledClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, style: style)
    }
}

Removing Annotations

To remove annotations, you can call remove(annotation:). However the annotations will still display until you call reload().

manager.remove(annotation)

In the case that shouldRemoveInvisibleAnnotations is set to false, annotations that have been removed may still appear on map until calling reload() on visible region.

Reloading Annotations

Implement the map view’s mapView(_:regionDidChangeAnimated:) delegate method to reload the ClusterManager when the region changes.

func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {
    clusterManager.reload(mapView: mapView) { finished in
        // handle completion
    }
}

You should call reload() anytime you add or remove annotations.

Configuring the Manager

The ClusterManager class exposes several properties to configure clustering:

var zoomLevel: Double // The current zoom level of the visible map region.
var maxZoomLevel: Double // The maximum zoom level before disabling clustering.
var minCountForClustering: Int // The minimum number of annotations for a cluster. The default is `2`.
var shouldRemoveInvisibleAnnotations: Bool // Whether to remove invisible annotations. The default is `true`.
var shouldDistributeAnnotationsOnSameCoordinate: Bool // Whether to arrange annotations in a circle if they have the same coordinate. The default is `true`.
var distanceFromContestedLocation: Double // The distance in meters from contested location when the annotations have the same coordinate. The default is `3`.
var clusterPosition: ClusterPosition // The position of the cluster annotation. The default is `.nearCenter`.

ClusterManagerDelegate

The ClusterManagerDelegate protocol provides a number of functions to manage clustering and configure cells.

// The size of each cell on the grid at a given zoom level.
func cellSize(for zoomLevel: Double) -> Double? { ... }

// Whether to cluster the given annotation.
func shouldClusterAnnotation(_ annotation: MKAnnotation) -> Bool { ... }

Communication

  • If you found a bug, open an issue.
  • If you have a feature request, open an issue.
  • If you want to contribute, submit a pull request.

Mentions

Credits

License

Cluster is available under the MIT license. See the LICENSE file for more info.

Comments
  • Cluster views change their location constantly when zooming (even very slightly) on low zoom

    Cluster views change their location constantly when zooming (even very slightly) on low zoom

    Issue Description

    (1) Cluster views change their location constantly when zooming (even very slightly) on low zoom, (2) they move far from the actual pins locations, (3) occasionally on very low zoom pins pop up.

    All this somehow linked to this method manager.shouldCenterAlignClusters = true

    Screenshots

    screenshot at nov 23 15-23-57

    Environment

    • iOS Version: IOS 11, IOS 10
    • Device(s): iPhone 6s+, iPhone 5
    bug 
    opened by IVANKRUPSKI 39
  • Exact Same Location.

    Exact Same Location.

    Hey guys and very nice work! Congrats to all of you :clap: Although I have one question.

    I'm running one app about Events. And some Venues have multiple Events in the exact same location (lat, lon) in the map. Do we have a workaround about it? Cause if i zoom in this location spot, the cluster doesn't break. And this is normal. Thanks a lot !

    enhancement 
    opened by kwstasna 19
  • Pins are clustered into two cluster, that are overlapping each other

    Pins are clustered into two cluster, that are overlapping each other

    Hey!

    Sometimes pins are clustered into more than one cluster, and these clusters are overlapping each other. That is really confusing, sometimes two overlapping cluster pins are exactly on the same place on the map, which looks like a mistake in calculation.

    Is that normal, expected behaviour of the framework?

    screenshot at oct 07 16-56-42

    bug 
    opened by IVANKRUPSKI 11
  • Remove all annotations, visible and invisible

    Remove all annotations, visible and invisible

    Issue Description

    Hey,

    Is there a way to remove all annotations.

    Right now if I call clusterManager.removeAll() seems like only invisible annotations are removed.

    In my app, I have searchBar which filters annotations, so I need them add/remove from map.

    Thank you for your help.

    Environment

    • iOS Version: [11.4.1]
    • Device(s): [iPhone 8]

    EDIT: Is it ok if I just add this line after calling clusterManager.removeAll(): mapView.removeAnnotations(mapView.annotations)

    bug 
    opened by DavidTomic 9
  • Roughly on 3000+ locations while scrolling the map (w/o zooming) cluster recalculation freezes the map for a couple of seconds (fully unresponsive).

    Roughly on 3000+ locations while scrolling the map (w/o zooming) cluster recalculation freezes the map for a couple of seconds (fully unresponsive).

    iOS 10/11 Any device

    • Roughly on 3000+ locations while scrolling the map (w/o zooming) cluster recalculation freezes the map for a couple of seconds (fully unresponsive). The older the processor the longer the freeze.

    • Even slight scrolling causes this freeze.

    • It's worth also to note that for the same map, with the same number of locations there is no such a freeze when zooming out/in, although recalculation should be similar.

    screenshot at apr 02 00-46-50

    enhancement help wanted 
    opened by IVANKRUPSKI 9
  • Pins grouping issue

    Pins grouping issue

    Hello again!

    As I am adding a lot of pins on my map, I am facing an issue with grouping. The grouping algorithm seems not to be predictive. If I zoom/unzoom a little bit, sometime a pin will be part of group 1, and sometime on group 2. This can lead to weird things (see attached video).

    Is it easy to fix or not? :)

    cluster-issue.mp4.zip

    opened by tdimeco 9
  • Missing styling of Annotation / View

    Missing styling of Annotation / View

    I upgraded from Cluster 2.2.8 to latest 2.4.1. After the upgrade, I had some errors stating that ClusterAnnotationStyle does not exists anymore.

    New Issue Checklist

    Issue Description

    How am I suppose to style my pins on the map now? I read a little bit and saw the style property have been made private but that's pretty much it.

    In the doc I see this:

    let annotation = Annotation()
    annotation.coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
    annotation.style = .color(color, radius: 25) // .image(UIImage(named: "pin"))
    clusterManager.add(annotation)
    

    But the style property doesn't exists anymore.

    I am clearly missing something here but can't find it...

    Thanks!

    Environment

    • iOS Version: 12.1
    • Device(s): Simulator / iPhone 6 / iPhone XR
    opened by sebleclerc 8
  • ClusteringManager crashing

    ClusteringManager crashing

    I'm having a problem with my program crashing while using clustering manager. I'm trying to build an app that will display the status of houses using coloured icons. screen shot 2017-06-29 at 3 39 38 pm

    It gives me an index out of range error when the map reloads, however the error only occurs occasionally. I can't tell from the stack trace where the error is occuring, since it takes me to a line Cluster.swift. Does anyone have any idea on what sort of thing could be causing the error? I have no idea what array could be out of range to cause this error.

    screen shot 2017-06-29 at 3 55 35 pm

    I'm thought the error is coming from the function below (as it sets the MKAnnotationView) but I swapped it for the function in the example project and it still crashes.

    //Display annotations and pins for the map
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
    
        var reuseId = ""
        let orangeColor = UIColor(red: 255/255, green: 149/255, blue: 0/255, alpha: 1)
        let redColor = UIColor(red: 255/255, green: 0/255, blue: 0/255, alpha: 1)
        let greenColor = UIColor(red: 6/255, green: 152/255, blue: 6/255, alpha: 1)
        
        if let annotation = annotation as? ClusterAnnotation {
            let identifier = "Cluster"
            var view = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
            if view == nil {
                if let annotation = annotation.annotations.first as? Annotation, let type = annotation.type {
                    view = BorderedClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: type, borderColor: .white)
                } else {
                    let allAnnos = annotation.annotations
                    if (!allAnnos.isEmpty && !addressStatus.isEmpty){
                        for anno in allAnnos {
                        if (addressStatus[anno.title!!] == "Offline") {
                            view = ClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: .color(redColor, radius: 25))
    
                            return view
                            
                        } else if (addressStatus[anno.title!!] == "Error"){
                            view = ClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: .color(orangeColor, radius: 25))
    
                            return view
                            
                        }
                        }
                    }
                    view = ClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: .color(greenColor, radius: 25))
                }
            } else {
                let allAnnos = annotation.annotations
                if (!allAnnos.isEmpty && !addressStatus.isEmpty) {
                    for anno in allAnnos {
                        if (addressStatus[anno.title!!] == "Offline") {
    
                            view = ClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: .color(redColor, radius: 25))
    
                            return view
                        
                        } else if (addressStatus[anno.title!!] == "Error"){
    
                            view = ClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: .color(orangeColor, radius: 25))
    
                            return view
                        
                        }
                    }
                    view = ClusterAnnotationView(annotation: annotation, reuseIdentifier: identifier, type: .color(greenColor, radius: 25))
                }
            }
    
            return view
            
        } else {
            reuseId = "Pin"
            var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId)
                pinView = MKAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
                pinView?.canShowCallout = true
                let address = annotation.title
            
                if (addressStatus[address!!] == "OK") {
                    pinView?.image = UIImage(named:"House Icon Green.png")!
                } else if (addressStatus[address!!] == nil) {
                    pinView?.image = UIImage(named:"House Icon Black.png")!
                } else if (addressStatus[address!!] == "Error") {
                    pinView?.image = UIImage(named:"House Icon Orange.png")!
                } else if (addressStatus[address!!] == "Offline") {
                    pinView?.image = UIImage(named:"House Icon Red.png")!
                }
    
            
                pinView?.frame = CGRect(x: 0, y: 0, width: 30, height: 30)
            
            return pinView
        }
    }
    

    Any help would be greatly appreciated thank you!

    opened by VSmallbon 8
  • Markers disappear when map view region changed

    Markers disappear when map view region changed

    New Issue Checklist

    Issue Description

    I attach a video with the problem.

    Environment

    • iOS Version: [iOS 12.1]
    • Device(s): [Simulator iPhone XR and iPhone 6S device]

    Gif:

    ezgif com-video-to-gif

    Congratulations for the project.

    Thank you.

    opened by elpatxificador 7
  • Crash in QuadTreeNode annotations(in rect: MKMapRect)

    Crash in QuadTreeNode annotations(in rect: MKMapRect)

    New Issue Checklist

    Issue Description

    I have noticed a few times that there has been a crash in QuadTree.swift:132 The line is for annotation in annotations where rect.contains(annotation.coordinate) and the crash is due to index out of bounds. Presumably this is due to iterating the annotations array while it is being modified. Perhaps a copy of this array should be made inside the method to be used for the iteration. I'm not sure if this fixes it.

    I cannot replicate this, however it has happened on multiple versions including the latest, 2.2.9. When this happened today the map was in memory but not visible on screen (page view controller sho8wing another page).

    Environment

    • iOS Version: 12.0, have seen it on 11 also
    • Device(s): iPhone 8, iPad Mini 4
    bug 
    opened by kylemay-gridstone 7
  • Support for multiple Cluster Managers

    Support for multiple Cluster Managers

    Hello,

    Kudos for the great work on the library so far :)

    I faced an issue when I tried to group pins based on a given type that I have. It would be really convenient if I could configure multiple Cluster Manager instances. I've seen that feature in some older libs.

    Do you think that would be possible to achieve in your library?

    Thank you, Granit

    opened by GranitGjevukaj 7
  • adding configuration

    adding configuration

    Hello

    Checklist

    • [ ] I've tested my changes.
    • [ ] I've read the Contribution Guidelines.
    • [ ] I've updated the documentation if necessary.

    Motivation and Context

    Description

    opened by aasimsayyad07 0
  • Quick Question Regarding 'IPHONEOS_DEPLOYMENT_TARGET'

    Quick Question Regarding 'IPHONEOS_DEPLOYMENT_TARGET'

    Hello,

    I have used the Swift Package Manger to install Cluster, but I get the following warning:

    The iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 14.3.99.

    Is there a reason for this, and how would I fix the warning? Thank you.

    opened by EdIzaguirre 0
  • User Location does not show

    User Location does not show

    Description User location does not show in the map. I want to update the user location when user moves but it does not show on map. Either I tried to show the user location with code and by checking the box "show user location" in the main.storyboard but it didn't worked.

    Checklist

    opened by ahmetsancaktaroglu 1
  • Total number of annotations on cluster does not match the number of annotations I added to the manager

    Total number of annotations on cluster does not match the number of annotations I added to the manager

    Description It is not necessarily a bug, maybe I'm not using the library right. When I add annotations to the manager I have a certain number of annotations in there, eg 362 But the if I sum up the numbers in all the cluster annotation view and isolated non-clustered annotations, or simply zoom out to the max, the total number of annotations is different (eg 231). And I get that number both on manager.annotations.count and on annotation.annotations.count:

    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
            if let annotation = annotation as? ClusterAnnotation {
                let identifier = "Cluster"
                let annotationView = mapView.annotationView(of: HTImageCountClusterAnnotationView.self, annotation: annotation, reuseIdentifier: identifier)
                annotationView.countLabel.textColor = UIColor.black
                annotationView.image = UIImage(named: "clusterpin")
                annotationView.canShowCallout = false
                print("Number of annotations in cluster: \(annotation.annotations.count)")
                print("Number of annotations in manager: \(manager.annotations.count)")
                return annotationView
            } else {
                ...
            }
        }
    

    This is how I initialize my manager:

    private lazy var manager: ClusterManager = { [unowned self] in
            let manager = ClusterManager()
            manager.delegate = self
            manager.maxZoomLevel = 17
            manager.minCountForClustering = 2
            manager.clusterPosition = .nearCenter
            manager.shouldRemoveInvisibleAnnotations = false
            return manager
        }()
    

    I don't understand this discrepancy. I don't remove any annotation from the manager.

    Smartphone

    • Device: iPhone 11 Pro
    • OS: iOS14
    • Version: 3.0.3

    Checklist

    opened by sarbogast 4
  • Background thread issue leading to a crash

    Background thread issue leading to a crash

    https://github.com/efremidze/Cluster/blob/3c70568c779456355895adf354a01e7fe5440ebf/Sources/Cluster.swift#L335

    The line of code above triggers UI update via KVO on background thread and it leads to a crash because of precondition.

    NSInternalInconsistencyException Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.
    0  CoreFoundation           __exceptionPreprocess + 220
    1  libobjc.A.dylib          objc_exception_throw + 56
    2  Foundation               -[NSISEngine tryToOptimizeReturningMutuallyExclusiveConstraints] + 0
    3  Foundation               -[NSISEngine withBehaviors:performModifications:] + 32
    4  UIKitCore                -[UIView(Hierarchy) _postMovedFromSuperview:] + 776
    5  UIKitCore                -[UIView(Internal) _addSubview:positioned:relativeTo:] + 1600
    6  MapKit                   -[MKAnnotationContainerView addAnnotationView:allowAnimation:] + 1444
    7  MapKit                   -[MKMapView addAnnotationRepresentation:allowAnimation:] + 588
    8  MapKit                   -[MKAnnotationManager _addRepresentationForAnnotation:] + 668
    9  MapKit                   -[MKAnnotationManager updateVisibleAnnotations] + 1008
    10 MapKit                   -[MKAnnotationManager observeValueForKeyPath:ofObject:change:context:] + 996
    11 Foundation               NSKeyValueNotifyObserver + 288
    12 Foundation               NSKeyValueDidChange.llvm.18207776532572868477 + 332
    13 Foundation               NSKeyValueDidChangeWithPerThreadPendingNotifications.llvm.18207776532572868477 + 148
    14 Foundation               NSKVOForwardInvocation + 336
    15 CoreFoundation           ___forwarding___ + 676
    16 CoreFoundation           _CF_forwarding_prep_0 + 92
    17 My App                   closure #3 in ClusterManager.distributeAnnotations(tree:mapRect:) + 824 (Cluster.swift)
    
    opened by letko-dmitry 3
  • More then 8000+ annotation at that time app stuck

    More then 8000+ annotation at that time app stuck

    Description We are add 8000+ annotation on mapview at that time app stuck and memory used 160+ MB.

    Screenshots If applicable, add screenshots to help explain your problem.

    Smartphone

    • Device: [e.g. iPhone7]
    • OS: [e.g. iOS13.3]

    Checklist

    opened by jigs777 0
Releases(2.4.5)
  • 2.4.5(Mar 7, 2019)

    Released on 2019-03-07.

    Fixed

    • Issue where the count of the annotations in the cluster annotation gets messed up when shouldDistributeAnnotationsOnSameCoordinate is set to true.
      • Fixed in Pull Request #107 regards to Issue #86.
    Source code(tar.gz)
    Source code(zip)
  • 2.4.3(Jan 29, 2019)

    Released on 2019-01-28.

    Added

    • Added style property to Annotation class to customize appearance of StyledClusterAnnotationView.
    • Renamed ClusterAnnotationView to StyledClusterAnnotationView.
    Source code(tar.gz)
    Source code(zip)
Owner
Lasha Efremidze
#iOS Engineer @amzn @EdisonJunior (Ring). Previously @eBay @stubhub @calaborate (Klutch). Open source enthusiast.
Lasha Efremidze
Demo in SwiftUI of Apple Map, Google Map, and Mapbox map

SNMapServices SNMapServices is a serices for iOS written in SwiftUI. It provides Map capability by subclassing Mapbox, Google map and Apple map. This

Softnoesis 3 Dec 16, 2022
Use any custom view as custom callout view for MKMapView with cool animations. Use any image as annotation view.

MapViewPlus About MapViewPlus gives you the missing methods of MapKit which are: imageForAnnotation and calloutViewForAnnotationView delegate methods.

Okhan Okbay 162 Nov 16, 2022
MSFlightMapView allows you to easily add and animate geodesic flights to Google map

MSFlightMapView Demo Requirements iOS 10.0+ Xcode 9.0+ Installation Just add the MSFlightMapView folder to your project. or use CocoaPods: pod 'MSFlig

Muhammad Abdul Subhan 48 Aug 13, 2022
A Swift package for parsing Clang module map files

Clangler is a Swift package used to parse Clang module map files into an abstract syntax tree (AST) representation. Once parsed, you can inspect or manipulate the nodes in the file, then generate and save a new file reflecting your changes.

Dalton Claybrook 9 Apr 7, 2022
Campus Atlas -- a Mapping & GIS solution which provides easy access to navigating the campus around you.

Campus Atlas Welcome to Campus Atlas -- a Mapping & GIS solution which provides easy access to navigating the campus around you. Technical Implementat

Larry Tseng 5 Nov 12, 2021
An iOS map clustering framework targeting MapKit, Google Maps and Mapbox.

ClusterKit is an elegant and efficiant clustering controller for maps. Its flexible architecture make it very customizable, you can use your own algor

null 502 Dec 25, 2022
Demo in SwiftUI of Apple Map, Google Map, and Mapbox map

SNMapServices SNMapServices is a serices for iOS written in SwiftUI. It provides Map capability by subclassing Mapbox, Google map and Apple map. This

Softnoesis 3 Dec 16, 2022
An exercise to use a map(google map) for navigation.

map-navigation An exercise to use a map(google map) for navigation. It have the features of navigating your for a destination, drawing your travel pat

HongXing Liao 2 Dec 16, 2022
Use any custom view as custom callout view for MKMapView with cool animations. Use any image as annotation view.

MapViewPlus About MapViewPlus gives you the missing methods of MapKit which are: imageForAnnotation and calloutViewForAnnotationView delegate methods.

Okhan Okbay 162 Nov 16, 2022
Annotation - Generate files to train with Object Detection by Create ML

CreateML Annotation Generate files to train with Object Detection by Create ML.

Vaida 10 Nov 7, 2022
A simple way to map XML to Objects written in Swift

XMLMapper XMLMapper is a framework written in Swift that makes it easy for you to convert your model objects (classes and structs) to and from XML. Ex

Giorgos Charitakis 109 Jan 6, 2023
A charting library to visualize and interact with a vector map on iOS. It's like Geochart but for iOS!

FSInteractiveMap A charting library to visualize data on a map. It's like geochart but for iOS! The idea behind this library is to load a SVG file of

Arthur 544 Dec 30, 2022
A native iOS client to map the Pokemon around you!

Pokemap client for iOS This is a client for the Pokemap server (https://github.com/RocketMap/RocketMap) iPokeGO is now officially available on the App

Dimitri Dessus 640 Oct 12, 2022
CarListing app allows user to see list of cars on map as well as in the list

Car Listing CarListing app allows user to see list of cars on map as well as in the list. Features See List of cars on map in the home screen. User ca

Niraj Kumar Jha 0 Oct 13, 2021
Snap Scraper enables users to download media uploaded to Snapchat's Snap Map using a set of latitude and longitude coordinates.

Snap Scraper Description Snap Scraper is an open source intelligence tool which enables users to download media uploaded to Snapchat's Snap Map using

Dr Richard Matthews 58 Dec 12, 2022
Async and concurrent versions of Swift’s forEach, map, flatMap, and compactMap APIs.

CollectionConcurrencyKit Welcome to CollectionConcurrencyKit, a lightweight Swift package that adds asynchronous and concurrent versions of the standa

John Sundell 684 Jan 9, 2023
MSFlightMapView allows you to easily add and animate geodesic flights to Google map

MSFlightMapView Demo Requirements iOS 10.0+ Xcode 9.0+ Installation Just add the MSFlightMapView folder to your project. or use CocoaPods: pod 'MSFlig

Muhammad Abdul Subhan 48 Aug 13, 2022
A Simple Weather App Using the Open Weather Map api

The Weather, a Simple Weather App Using the Open Weather Map api. This app demos use of the Open Weather Map api. The UI is simple, with views of the

null 1 Feb 17, 2022
A Swift package for parsing Clang module map files

Clangler is a Swift package used to parse Clang module map files into an abstract syntax tree (AST) representation. Once parsed, you can inspect or manipulate the nodes in the file, then generate and save a new file reflecting your changes.

Dalton Claybrook 9 Apr 7, 2022
A data visualisation tool that adds publicly available crime data from UK police forces to an interactive map.

CrimeMapper A data visualisation tool that adds publicly available crime data from UK police forces to an interactive map. Download on the App Store Y

sam woolf 11 Jul 20, 2022