[
  {
    "path": ".gitignore",
    "content": ".DS_Store\n/.build\n/Packages\nxcuserdata/\nDerivedData/\n.swiftpm/configuration/registries.json\n.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata\n.netrc\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to SwiftUI MapView\n\nYou're welcome to contribute improvements and fixes to the project.\nThank you for your time investment!\n\nPlease read the following guide to ensure consistency and a shared level of quality for your contribution.\nThe goal is to have everything ready so that the process is as straight forward as possible for everyone.\nIf there are instructions missing, feel free to contribute changes to this guide as well.\n\n**Before you start contributing** please make sure of the following:\n\n1. Ensure that you have a clear goal in mind. Proposing or implementing changes should not divert from the project's goal.\n2. When unsure of whether your changes meet the project's goal open an issue to discuss your intentions and its consequences.\n\n**When opening issues or pull requests** please make sure of the following:\n\n1. Describe the specific goal of the issue or pull request. Focus on one topic so that it can be worked on in isolation.\n2. Add your thoughts and questions to the description so that issues can be addressed quickly.\n3. Highlight important sections in code that need attention and are critical to understanding the changes.\n4. Avoid mixing multiple changes or ideas in one contribution. Each one should be one logical unit (i.e. do not mix new features with fixes to existing ones).\n\nOnce you feel comfortable with these guidelines feel free to open [issues](https://github.com/sgade/swiftui-mapview/issues) or [pull requests](https://github.com/sgade/swiftui-mapview/pulls) on GitHub.\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 Sören Gade\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "MapViewExample/MapViewExample/Assets.xcassets/AccentColor.colorset/Contents.json",
    "content": "{\n  \"colors\" : [\n    {\n      \"idiom\" : \"universal\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "MapViewExample/MapViewExample/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"platform\" : \"ios\",\n      \"size\" : \"1024x1024\"\n    },\n    {\n      \"appearances\" : [\n        {\n          \"appearance\" : \"luminosity\",\n          \"value\" : \"dark\"\n        }\n      ],\n      \"idiom\" : \"universal\",\n      \"platform\" : \"ios\",\n      \"size\" : \"1024x1024\"\n    },\n    {\n      \"appearances\" : [\n        {\n          \"appearance\" : \"luminosity\",\n          \"value\" : \"tinted\"\n        }\n      ],\n      \"idiom\" : \"universal\",\n      \"platform\" : \"ios\",\n      \"size\" : \"1024x1024\"\n    }\n  ],\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "MapViewExample/MapViewExample/Assets.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "MapViewExample/MapViewExample/CLLocationCoordinate2D+Examples.swift",
    "content": "//\n//  CLLocationCoordinate2D+Examples.swift\n//  MapViewExample\n//\n//  Created by Sören Gade on 21.02.20.\n//\n\nimport CoreLocation\n\nextension CLLocationCoordinate2D {\n    \n    static let inifiniteLoop = CLLocationCoordinate2D(\n        latitude: 37.331836,\n        longitude: -122.029604\n    )\n    \n    static let applePark = CLLocationCoordinate2D(\n        latitude: 37.334780,\n        longitude: -122.009073\n    )\n    \n}\n"
  },
  {
    "path": "MapViewExample/MapViewExample/ContentView.swift",
    "content": "//\n//  ContentView.swift\n//  MapViewExample\n//\n//  Created by Sören Gade on 21.02.20.\n//\n\nimport SwiftUI\nimport SwiftUIMapView\nimport CoreLocation\nimport MapKit\n\nstruct ContentView: View {\n\n    @State\n    private var region: MKCoordinateRegion? = MKCoordinateRegion(\n        center: .applePark,\n        span: MKCoordinateSpan(\n            latitudeDelta: 0.05,\n            longitudeDelta: 0.05\n        )\n    )\n\n    @State\n    private var selectedAnnotations: [MapViewAnnotation] = []\n\n    private let locationManager = CLLocationManager()\n\n    var body: some View {\n        VStack {\n            MapView(\n                mapType: .standard,\n                region: $region,\n                showsUserLocation: true,\n                userTrackingMode: .none,\n                annotations: [ExampleAnnotation].examples,\n                selectedAnnotations: $selectedAnnotations\n            )\n            .edgesIgnoringSafeArea(.all)\n\n            ForEach(selectedAnnotations.compactMap { $0 as? ExampleAnnotation }) { annotation in\n                Text(\"\\( annotation.title ?? \"\" )\")\n            }\n\n            if let region {\n                Text(\"\\(region.center.latitude), \\(region.center.longitude)\")\n            }\n        }\n        .onAppear {\n            // this is required to display the user's current location\n            locationManager.requestWhenInUseAuthorization()\n        }\n    }\n\n}\n\n// MARK: - Previews\n\n#Preview {\n    ContentView()\n}\n"
  },
  {
    "path": "MapViewExample/MapViewExample/ExampleAnnotation.swift",
    "content": "//\n//  ExampleAnnotation.swift\n//  MapViewExample\n//\n//  Created by Sören Gade on 21.02.20.\n//\n\nimport SwiftUIMapView\nimport MapKit\n\nclass ExampleAnnotation: NSObject, MapViewAnnotation, Identifiable {\n    \n    let coordinate: CLLocationCoordinate2D\n    \n    let title: String?\n    \n    let id = UUID()\n    \n    let clusteringIdentifier: String? = \"exampleCluster\"\n    \n    let glyphImage: UIImage? = UIImage(systemName: \"e.circle.fill\")\n    \n    let tintColor: UIColor? = .green\n    \n    init(title: String, coordinate: CLLocationCoordinate2D) {\n        self.title = title\n        self.coordinate = coordinate\n    }\n    \n}\n\n// MARK: - Array+ExampleAnnotation\n\nextension Array where Element == ExampleAnnotation {\n\n    static let examples: [ExampleAnnotation] = [\n        ExampleAnnotation(title: \"Apple Park\", coordinate: .applePark),\n        ExampleAnnotation(title: \"Infinite Loop\", coordinate: .inifiniteLoop),\n    ]\n\n}\n"
  },
  {
    "path": "MapViewExample/MapViewExample/MapViewExampleApp.swift",
    "content": "//\n//  MapViewExampleApp.swift\n//  MapViewExample\n//\n//  Created by Sören Gade on 16.12.25.\n//\n\nimport SwiftUI\n\n@main\nstruct MapViewExampleApp: App {\n\n    var body: some Scene {\n        WindowGroup {\n            ContentView()\n        }\n    }\n\n}\n"
  },
  {
    "path": "MapViewExample/MapViewExample.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 77;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t45DDF4992EF1CFE5001077C5 /* SwiftUIMapView in Frameworks */ = {isa = PBXBuildFile; productRef = 45DDF4982EF1CFE5001077C5 /* SwiftUIMapView */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXFileReference section */\n\t\t45DDF4892EF1CF73001077C5 /* MapViewExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MapViewExample.app; sourceTree = BUILT_PRODUCTS_DIR; };\n/* End PBXFileReference section */\n\n/* Begin PBXFileSystemSynchronizedRootGroup section */\n\t\t45DDF48B2EF1CF73001077C5 /* MapViewExample */ = {\n\t\t\tisa = PBXFileSystemSynchronizedRootGroup;\n\t\t\tpath = MapViewExample;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXFileSystemSynchronizedRootGroup section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t45DDF4862EF1CF73001077C5 /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t45DDF4992EF1CFE5001077C5 /* SwiftUIMapView in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t45DDF4802EF1CF73001077C5 = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t45DDF48B2EF1CF73001077C5 /* MapViewExample */,\n\t\t\t\t45DDF48A2EF1CF73001077C5 /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t45DDF48A2EF1CF73001077C5 /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t45DDF4892EF1CF73001077C5 /* MapViewExample.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t45DDF4882EF1CF73001077C5 /* MapViewExample */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 45DDF4942EF1CF74001077C5 /* Build configuration list for PBXNativeTarget \"MapViewExample\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t45DDF4852EF1CF73001077C5 /* Sources */,\n\t\t\t\t45DDF4862EF1CF73001077C5 /* Frameworks */,\n\t\t\t\t45DDF4872EF1CF73001077C5 /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tfileSystemSynchronizedGroups = (\n\t\t\t\t45DDF48B2EF1CF73001077C5 /* MapViewExample */,\n\t\t\t);\n\t\t\tname = MapViewExample;\n\t\t\tpackageProductDependencies = (\n\t\t\t\t45DDF4982EF1CFE5001077C5 /* SwiftUIMapView */,\n\t\t\t);\n\t\t\tproductName = MapViewExample;\n\t\t\tproductReference = 45DDF4892EF1CF73001077C5 /* MapViewExample.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t45DDF4812EF1CF73001077C5 /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tBuildIndependentTargetsInParallel = 1;\n\t\t\t\tLastSwiftUpdateCheck = 2620;\n\t\t\t\tLastUpgradeCheck = 2620;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t45DDF4882EF1CF73001077C5 = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 26.2;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 45DDF4842EF1CF73001077C5 /* Build configuration list for PBXProject \"MapViewExample\" */;\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 45DDF4802EF1CF73001077C5;\n\t\t\tminimizedProjectReferenceProxies = 1;\n\t\t\tpackageReferences = (\n\t\t\t\t45DDF4972EF1CFE5001077C5 /* XCLocalSwiftPackageReference \"../../swiftui-mapview\" */,\n\t\t\t);\n\t\t\tpreferredProjectObjectVersion = 77;\n\t\t\tproductRefGroup = 45DDF48A2EF1CF73001077C5 /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t45DDF4882EF1CF73001077C5 /* MapViewExample */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t45DDF4872EF1CF73001077C5 /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t45DDF4852EF1CF73001077C5 /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin XCBuildConfiguration section */\n\t\t45DDF4922EF1CF74001077C5 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++20\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tENABLE_USER_SCRIPT_SANDBOXING = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu17;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 26.2;\n\t\t\t\tLOCALIZATION_PREFERS_STRING_CATALOGS = YES;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_ACTIVE_COMPILATION_CONDITIONS = \"DEBUG $(inherited)\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t45DDF4932EF1CF74001077C5 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++20\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_WEAK = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_DOCUMENTATION_COMMENTS = YES;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_USER_SCRIPT_SANDBOXING = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu17;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 26.2;\n\t\t\t\tLOCALIZATION_PREFERS_STRING_CATALOGS = YES;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tMTL_FAST_MATH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_COMPILATION_MODE = wholemodule;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t45DDF4952EF1CF74001077C5 /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tENABLE_APP_SANDBOX = YES;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;\n\t\t\t\tENABLE_PREVIEWS = YES;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_KEY_NSLocationWhenInUseUsageDescription = \"The app shows the user's location.\";\n\t\t\t\tINFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;\n\t\t\t\tINFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;\n\t\t\t\tINFOPLIST_KEY_UILaunchScreen_Generation = YES;\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = \"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = \"UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = de.sgade.MapViewExample;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tREGISTER_APP_GROUPS = YES;\n\t\t\t\tSTRING_CATALOG_GENERATE_SYMBOLS = YES;\n\t\t\t\tSUPPORTED_PLATFORMS = \"iphoneos iphonesimulator\";\n\t\t\t\tSUPPORTS_MACCATALYST = NO;\n\t\t\t\tSUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;\n\t\t\t\tSUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;\n\t\t\t\tSWIFT_APPROACHABLE_CONCURRENCY = YES;\n\t\t\t\tSWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;\n\t\t\t\tSWIFT_VERSION = 6.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t45DDF4962EF1CF74001077C5 /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tENABLE_APP_SANDBOX = YES;\n\t\t\t\tENABLE_HARDENED_RUNTIME = YES;\n\t\t\t\tENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;\n\t\t\t\tENABLE_PREVIEWS = YES;\n\t\t\t\tGENERATE_INFOPLIST_FILE = YES;\n\t\t\t\tINFOPLIST_KEY_NSLocationWhenInUseUsageDescription = \"The app shows the user's location.\";\n\t\t\t\tINFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;\n\t\t\t\tINFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;\n\t\t\t\tINFOPLIST_KEY_UILaunchScreen_Generation = YES;\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = \"UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tINFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = \"UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight\";\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"@executable_path/Frameworks\",\n\t\t\t\t);\n\t\t\t\tMARKETING_VERSION = 1.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = de.sgade.MapViewExample;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tREGISTER_APP_GROUPS = YES;\n\t\t\t\tSTRING_CATALOG_GENERATE_SYMBOLS = YES;\n\t\t\t\tSUPPORTED_PLATFORMS = \"iphoneos iphonesimulator\";\n\t\t\t\tSUPPORTS_MACCATALYST = NO;\n\t\t\t\tSUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;\n\t\t\t\tSUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;\n\t\t\t\tSWIFT_APPROACHABLE_CONCURRENCY = YES;\n\t\t\t\tSWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;\n\t\t\t\tSWIFT_EMIT_LOC_STRINGS = YES;\n\t\t\t\tSWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;\n\t\t\t\tSWIFT_VERSION = 6.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t45DDF4842EF1CF73001077C5 /* Build configuration list for PBXProject \"MapViewExample\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t45DDF4922EF1CF74001077C5 /* Debug */,\n\t\t\t\t45DDF4932EF1CF74001077C5 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t45DDF4942EF1CF74001077C5 /* Build configuration list for PBXNativeTarget \"MapViewExample\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t45DDF4952EF1CF74001077C5 /* Debug */,\n\t\t\t\t45DDF4962EF1CF74001077C5 /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\n/* Begin XCLocalSwiftPackageReference section */\n\t\t45DDF4972EF1CFE5001077C5 /* XCLocalSwiftPackageReference \"../../swiftui-mapview\" */ = {\n\t\t\tisa = XCLocalSwiftPackageReference;\n\t\t\trelativePath = \"../../swiftui-mapview\";\n\t\t};\n/* End XCLocalSwiftPackageReference section */\n\n/* Begin XCSwiftPackageProductDependency section */\n\t\t45DDF4982EF1CFE5001077C5 /* SwiftUIMapView */ = {\n\t\t\tisa = XCSwiftPackageProductDependency;\n\t\t\tproductName = SwiftUIMapView;\n\t\t};\n/* End XCSwiftPackageProductDependency section */\n\t};\n\trootObject = 45DDF4812EF1CF73001077C5 /* Project object */;\n}\n"
  },
  {
    "path": "MapViewExample/MapViewExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Package.swift",
    "content": "// swift-tools-version: 6.2\n\nimport PackageDescription\n\nlet package = Package(\n    name: \"swiftui-mapview\",\n    platforms: [\n        .iOS(.v13)\n    ],\n    products: [\n        .library(\n            name: \"SwiftUIMapView\",\n            targets: [\"SwiftUIMapView\"]\n        ),\n    ],\n    dependencies: [],\n    targets: [\n        .target(\n            name: \"SwiftUIMapView\",\n            dependencies: [],\n            swiftSettings: [\n                .defaultIsolation(MainActor.self)\n            ]\n        )\n    ]\n)\n"
  },
  {
    "path": "README.md",
    "content": "# swiftui-mapview\n\n![Swift Version](https://img.shields.io/badge/Swift-6.2-orange.svg?logo=swift)\n[![](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Fsgade%2Fswiftui-mapview%2Fbadge%3Ftype%3Dswift-versions)](https://swiftpackageindex.com/sgade/swiftui-mapview)\n![Platforms](https://img.shields.io/badge/Platforms-iOS-yellow.svg?logo=apple)\n\n[MKMapView](https://developer.apple.com/documentation/mapkit/mkmapview) in SwiftUI.\n\n**For iOS 17 and later, I recommend you use Apple's official [Map](https://developer.apple.com/documentation/mapkit/map) view.**\n\n[![Social Preview](assets/social-preview.png)](assets/screen.png)\n(Click the image to see the full screenshot)\n\n## Install\n\nUsing Xcode, select `File` -> `Swift Packages` -> `Add Package Dependency` and enter `https://github.com/sgade/swiftui-mapview`.\n\n## Usage\n\nIn your view, add the map.\nSee the [example project](MapViewExample) for how to integrate the map view.\n\n```swift\nimport SwiftUIMapView\n\nstruct ContentView: View {\n    var body: some View {\n        MapView()\n    }\n}\n```\n\n## Configuration\n\n### Map type\n\n```swift\nMapView(mapType: .standard)\n```\n\n### User location\n\n### Showing the current user location\n\nThe current location can be shown on the map.\nNote that the application requires permission to access the current user location.\nSee the documentation on `MapView.showsUserLocation` for more information.\n\n```swift\nMapView(showsUserLocation: true)\n```\n\n### Tracking the user's location\n\n```swift\nMapView(userTrackingMode: .follow)\n```\n\n### Setting the visible region\n\nThe binding passed in for `region` defines the visible map region. Use it to define the visible center and zoom.\nSetting it to `nil` will use the map's default region when loaded. It is also updated when the visible region changes.\n\n```swift\n@State var region: MKCoordinateRegion?\n\nMapView(region: $region)\n```\n\n### Annotations\n\n#### Adding annotations\n\nAnnotations are represented as objects of a custom class that implements the `MapViewAnnotation` protocol.\nIt might be helpful to subclass from existing classes like `MKPlacemark`.\n\n```swift\nlet annotations: [MapViewAnnotation] = ...\n\nMapView(annotations: annotations)\n```\n\n#### Selecting annotations\n\nA list of selected annotations can be passed in via a binding.\n\n```swift\n@State var selectedAnnotations: [MapViewAnnotation] = []\n\nMapView(selectedAnnotations: $selectedAnnotations)\n```\n\n## Contributing\n\nSee the [contributing guide](CONTRIBUTING.md).\n\n## License\n\nThis project is licensed unter the terms of the MIT license. See [LICENSE](./LICENSE) for more information.\n"
  },
  {
    "path": "Sources/SwiftUIMapView/AnnotationViews/MapAnnotationClusterView.swift",
    "content": "//\n//  MapAnnotationClusterView.swift\n//  SwiftUIMapView\n//\n//  Created by Sören Gade on 19.02.20.\n//  Copyright © 2020 Sören Gade. All rights reserved.\n//\n\nimport Foundation\nimport MapKit\n\n/// Custom annotation view for ``MapAnnotation`` view clusters.\n///\n/// This view draws its content itself and therefore has a pretty custom style.\n///\n/// - Seealso: ``MapAnnotationView``\nclass MapAnnotationClusterView: MKAnnotationView {\n\n    private static let annotationSize: CGFloat = 32\n\n    override var annotation: MKAnnotation? {\n        didSet {\n            guard let clusterAnnotation = annotation as? MKClusterAnnotation else {\n                return\n            }\n\n            let mapAnnotations = clusterAnnotation.memberAnnotations.compactMap { $0 as? MapViewAnnotation }\n            guard let mapAnnotation = mapAnnotations.first else {\n                return\n            }\n\n            collisionMode = .circle\n\n            image = drawGlyph(\n                sized: CGSize(\n                    width: Self.annotationSize,\n                    height: Self.annotationSize\n                ),\n                colored: mapAnnotation.tintColor,\n                withCount: mapAnnotations.count\n            )\n        }\n    }\n\n}\n\n// MARK: Drawing glyphs\n\nprivate extension MapAnnotationClusterView {\n\n    /// Draws the annotation's glyph.\n    func drawGlyph(\n        sized size: CGSize,\n        colored tintColor: UIColor?,\n        withCount count: Int\n    ) -> UIImage {\n        let renderer = UIGraphicsImageRenderer(size: size)\n        return renderer.image { _ in\n            // draw background\n            tintColor?.setFill()\n            UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: size.width, height: size.height)).fill()\n\n            if let image = UIImage(systemName: \"\\(count).circle\")?.withTintColor(.white) {\n                // draw glyph\n                let imageRect = CGRect(x: size.width / 2 - image.size.width / 2,\n                                       y: size.height / 2 - image.size.height / 2,\n                                       width: image.size.width,\n                                       height: image.size.height)\n                image.draw(in: imageRect)\n            } else {\n                // draw text\n                let fontSize: CGFloat = 24\n                let textAttributes: [NSAttributedString.Key: NSObject] = [\n                    NSAttributedString.Key.foregroundColor: UIColor.black,\n                    NSAttributedString.Key.font: UIFont.systemFont(ofSize: fontSize)\n                ]\n                let text = \"\\(count)\" as NSString\n                let textSize = text.size(withAttributes: textAttributes)\n                let textRect = CGRect(x: size.width / 2 - textSize.width / 2,\n                                      y: size.height / 2 - textSize.height / 2,\n                                      width: textSize.width,\n                                      height: textSize.height)\n                text.draw(in: textRect, withAttributes: textAttributes)\n            }\n        }\n    }\n    \n}\n"
  },
  {
    "path": "Sources/SwiftUIMapView/AnnotationViews/MapAnnotationView.swift",
    "content": "//\n//  MapAnnotationView.swift\n//  SwiftUIMapView\n//\n//  Created by Sören Gade on 19.02.20.\n//  Copyright © 2020 Sören Gade. All rights reserved.\n//\n\nimport Foundation\nimport MapKit\n\n/// Custom annotation view for ``MapAnnotation`` objects.\n///\n/// Sets the view's `glyphImage` and `markerTintColor` according to values of the annotation.\n/// Automatically takes advantage of clustering via an optionally set `clusteringIdentifier`.\nclass MapAnnotationView: MKMarkerAnnotationView {\n    \n    override var annotation: MKAnnotation? {\n        didSet {\n            guard let mapAnnotation = annotation as? MapViewAnnotation else {\n                return\n            }\n\n            clusteringIdentifier = mapAnnotation.clusteringIdentifier\n            markerTintColor = mapAnnotation.tintColor\n            glyphImage = mapAnnotation.glyphImage\n        }\n    }\n    \n}\n"
  },
  {
    "path": "Sources/SwiftUIMapView/Annotations/MKMapView+MapViewAnnotation.swift",
    "content": "//\n//  MKMapView+MapViewAnnotation.swift\n//  SwiftUIMapView\n//\n//  Created by Sören Gade on 21.02.20.\n//\n\nimport MapKit\n\nextension MKMapView {\n\n    /// All ``MapViewAnnotation``s set on the map view.\n    var mapViewAnnotations: [MapViewAnnotation] {\n        annotations.compactMap { $0 as? MapViewAnnotation }\n    }\n\n    /// All ``MapViewAnnotation``s selected on the map view.\n    var selectedMapViewAnnotations: [MapViewAnnotation] {\n        selectedAnnotations.compactMap { $0 as? MapViewAnnotation }\n    }\n    \n}\n"
  },
  {
    "path": "Sources/SwiftUIMapView/Annotations/MapViewAnnotation.swift",
    "content": "//\n//  MapViewAnnotation.swift\n//  SwiftUIMapView\n//\n//  Created by Sören Gade on 19.02.20.\n//  Copyright © 2020 Sören Gade. All rights reserved.\n//\n\nimport Foundation\nimport MapKit\n\n/// An annotation on a ``MapView``.\n///\n/// Annotations can be visualized using their `title`, `subtitle`, `glyphImage` and `tintColor`.\n///\n/// To support automatic clustering of annotations, specify a `clusterIdentifier`.\n///\n/// Note: `MapAnnotation` provides a custom view class implementation for displaying the annotation data on the map.\n/// Custom views are currently not supported.\npublic protocol MapViewAnnotation: MKAnnotation {\n\n    /// Identifier for clustering annotations.\n    /// Setting to a non-`nil` value marks the annotation as participant in clustering.\n    ///\n    /// - Seealso: MKAnnotationView.clusteringIdentifier\n    var clusteringIdentifier: String? {\n        get\n    }\n\n    /// The image to display as a glyph in the annotation's view.\n    var glyphImage: UIImage? {\n        get\n    }\n\n    /// The tint color of the annotations's view.\n    var tintColor: UIColor? {\n        get\n    }\n    \n}\n"
  },
  {
    "path": "Sources/SwiftUIMapView/CoreLocation+Equatable.swift",
    "content": "//\n//  CoreLocation+Equatable.swift\n//  SwiftUIMapView\n//\n//  Created by Sören Gade on 24.02.20.\n//\n\nimport Foundation\nimport CoreLocation\nimport MapKit\n\n// MARK: - CLLocationCoordinate2D\n\nextension CLLocationCoordinate2D: @retroactive Equatable {\n\n    public static func ==(lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool {\n        lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude\n    }\n\n}\n\n// MARK: - MKCoordinateSpan\n\nextension MKCoordinateSpan: @retroactive Equatable {\n\n    public static func ==(lhs: MKCoordinateSpan, rhs: MKCoordinateSpan) -> Bool {\n        lhs.latitudeDelta == rhs.latitudeDelta && lhs.longitudeDelta == rhs.longitudeDelta\n    }\n\n}\n"
  },
  {
    "path": "Sources/SwiftUIMapView/MapView+Xcode.swift",
    "content": "//\n//  MapView+Xcode.swift\n//  SwiftUIMapView\n//\n//  Created by Sören Gade on 26.06.20.\n//\n\n#if canImport(DeveloperToolsSupport)\nimport DeveloperToolsSupport\n\n@available(iOS 14.0, *)\nstruct LibraryViewContent: LibraryContentProvider {\n\n    var views: [LibraryItem] {\n        LibraryItem(MapView())\n    }\n\n}\n#endif\n"
  },
  {
    "path": "Sources/SwiftUIMapView/MapView.swift",
    "content": "//\n//  MapView.swift\n//  SwiftUIMapView\n//\n//  Created by Sören Gade on 14.01.20.\n//  Copyright © 2020 Sören Gade. All rights reserved.\n//\n\nimport SwiftUI\nimport MapKit\nimport Combine\nimport UIKit\n\n/// Displays a map.\n/// The contents of the map are provided by the Apple Maps service.\n///\n/// See the [official documentation](https://developer.apple.com/documentation/mapkit/mkmapview) for more information\n/// on the possibilities provided by the underlying service.\npublic struct MapView: UIViewRepresentable {\n\n    /// The region that is displayed.\n    ///\n    /// Note: The region might not be used as-is, as it might need to be fitted to the view's bounds.\n    /// See [regionThatFits(_:)](https://developer.apple.com/documentation/mapkit/mkmapview/1452371-regionthatfits).\n    @Binding\n    private var region: MKCoordinateRegion?\n\n    /// The currently selected annotations.\n    ///\n    /// When the user selects annotations on the map the value of this binding changes.\n    /// Likewise, setting the value of this binding to a value selects the given annotations.\n    @Binding\n    private var selectedAnnotations: [MapViewAnnotation]\n\n    /// Annotations that are displayed on the map.\n    ///\n    ///\n    /// See the `selectedAnnotation` binding for more information about user selection of annotations.\n    private let annotations: [MapViewAnnotation]\n\n    /// The map type that is displayed.\n    private let mapType: MKMapType\n\n    /// Determines whether the map can be zoomed.\n    private let isZoomEnabled: Bool\n\n    /// Determines whether the map can be scrolled.\n    private let isScrollEnabled: Bool\n\n    /// Determines whether the map can be rotated.\n    private let isRotateEnabled: Bool\n\n    /// Determines whether the current user location is displayed.\n    ///\n    /// This requires the `NSLocationWhenInUseUsageDescription` key in the Info.plist to be set.\n    /// In addition, you need to call [`CLLocationManager.requestWhenInUseAuthorization()`](https://developer.apple.com/documentation/corelocation/cllocationmanager/1620562-requestwheninuseauthorization)\n    /// to request for permission.\n    private let showsUserLocation: Bool\n\n    /// Sets the map's user tracking mode.\n    private let userTrackingMode: MKUserTrackingMode\n\n    /// Creates a new MapView.\n    ///\n    /// - Parameters:\n    ///     - mapType: The map type to display.\n    ///     - region: The region to display.\n    ///     - isZoomEnabled: Whether the map can be zoomed.\n    ///     - isScrollEnabled: Whether the map can be scrolled.\n    ///     - isRotateEnabled: Whether the map can be rotated.\n    ///     - showsUserLocation: Whether to display the user's current location.\n    ///     - userTrackingMode: The user tracking mode.\n    ///     - annotations: A list of `MapAnnotation`s that should be displayed on the map.\n    ///     - selectedAnnotation: A binding to the currently selected annotation, or `nil`.\n    public init(\n        mapType: MKMapType = .standard,\n        region: Binding<MKCoordinateRegion?> = .constant(nil),\n        isZoomEnabled: Bool = true,\n        isScrollEnabled: Bool = true,\n        isRotateEnabled: Bool = true,\n        showsUserLocation: Bool = false,\n        userTrackingMode: MKUserTrackingMode = .none,\n        annotations: [MapViewAnnotation] = [],\n        selectedAnnotations: Binding<[MapViewAnnotation]> = .constant([])\n    ) {\n        self.mapType = mapType\n        self._region = region\n        self.isZoomEnabled = isZoomEnabled\n        self.isScrollEnabled = isScrollEnabled\n        self.isRotateEnabled = isRotateEnabled\n        self.showsUserLocation = showsUserLocation\n        self.userTrackingMode = userTrackingMode\n        self.annotations = annotations\n        self._selectedAnnotations = selectedAnnotations\n    }\n\n}\n\n// MARK: - UIViewRepresentable\n\nextension MapView {\n\n    public func makeCoordinator() -> Coordinator {\n        Coordinator()\n    }\n\n    public func makeUIView(context: Context) -> MKMapView {\n        let mapView = MKMapView()\n        mapView.delegate = context.coordinator\n        // register custom annotation view classes\n        mapView.register(\n            MapAnnotationView.self,\n            forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier\n        )\n        mapView.register(\n            MapAnnotationClusterView.self,\n            forAnnotationViewWithReuseIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier\n        )\n\n        // perform initial view state\n        configure(\n            mapView,\n            context: context,\n            animated: false\n        )\n\n        return mapView\n    }\n\n    public func updateUIView(\n        _ mapView: MKMapView,\n        context: Context\n    ) {\n        configure(\n            mapView,\n            context: context,\n            animated: true\n        )\n    }\n\n}\n\n// MARK: Configuring view state\n\nprivate extension MapView {\n\n    /// Configures the `mapView`'s state according to the current view state.\n    func configure(\n        _ mapView: MKMapView,\n        context: Context,\n        animated: Bool\n    ) {\n        if let region {\n            let region = mapView.regionThatFits(region)\n\n            if region.center != mapView.region.center || region.span != mapView.region.span {\n                mapView.setRegion(region, animated: animated)\n            }\n        }\n        mapView.mapType = mapType\n        mapView.isZoomEnabled = isZoomEnabled\n        mapView.isScrollEnabled = isScrollEnabled\n        mapView.isRotateEnabled = isRotateEnabled\n        mapView.showsUserLocation = showsUserLocation\n        mapView.userTrackingMode = userTrackingMode\n        \n        // annotation configuration\n        updateAnnotations(in: mapView)\n        updateSelectedAnnotation(\n            in: mapView,\n            animated: animated\n        )\n\n        // update coordinator with new view instance\n        context.coordinator.onRegionChanged = { region in\n            Task {\n                // avoid modifying state during view update\n                self.region = region\n            }\n        }\n        context.coordinator.onAnnotationSelected = { annotation in\n            selectedAnnotations.append(annotation)\n        }\n        context.coordinator.onAnnotationDeselected = { annotation in\n            guard let index = selectedAnnotations.firstIndex(where: { annotation.isEqual($0) }) else {\n                return\n            }\n            selectedAnnotations.remove(at: index)\n        }\n    }\n    \n    /// Updates the annotation property of the `mapView`.\n    /// Calculates the difference between the current and new states and only executes changes on those diff sets.\n    ///\n    /// - Parameter mapView: The ``MKMapView`` to configure.\n    func updateAnnotations(in mapView: MKMapView) {\n        let currentAnnotations = mapView.mapViewAnnotations\n        // remove old annotations\n        let obsoleteAnnotations = currentAnnotations.filter { mapAnnotation in\n            !annotations.contains { $0.isEqual(mapAnnotation) }\n        }\n        mapView.removeAnnotations(obsoleteAnnotations)\n        \n        // add new annotations\n        let newAnnotations = annotations.filter { mapViewAnnotation in\n            !currentAnnotations.contains { $0.isEqual(mapViewAnnotation) }\n        }\n        mapView.addAnnotations(newAnnotations)\n    }\n    \n    /// Updates the selection annotations of the `mapView`.\n    /// Calculates the difference between the current and new selection states and only executes changes on those diff sets.\n    ///\n    /// - Parameters:\n    ///     - mapView: The ``MKMapView`` to configure.\n    ///     - animated: Whether to animate the change.\n    func updateSelectedAnnotation(\n        in mapView: MKMapView,\n        animated: Bool\n    ) {\n        // deselect annotations that are not currently selected\n        let oldSelections = mapView.selectedMapViewAnnotations.filter { oldSelection in\n            !selectedAnnotations.contains {\n                oldSelection.isEqual($0)\n            }\n        }\n        for annotation in oldSelections {\n            mapView.deselectAnnotation(annotation, animated: false)\n        }\n        \n        // select all new annotations\n        let newSelections = selectedAnnotations.filter { selection in\n            !mapView.selectedMapViewAnnotations.contains {\n                selection.isEqual($0)\n            }\n        }\n        for annotation in newSelections {\n            mapView.selectAnnotation(annotation, animated: animated)\n        }\n    }\n\n}\n\n// MARK: - Coordinator\n\npublic extension MapView {\n\n    final class Coordinator: NSObject, MKMapViewDelegate {\n\n        var onRegionChanged: (MKCoordinateRegion) -> Void = { _ in }\n\n        var onAnnotationSelected: (MapViewAnnotation) -> Void = { _ in }\n\n        var onAnnotationDeselected: (MapViewAnnotation) -> Void = { _ in }\n\n    }\n\n}\n\n// MARK: MKMapViewDelegate\n\nextension MapView.Coordinator {\n\n    public func mapView(\n        _ mapView: MKMapView,\n        didSelect view: MKAnnotationView\n    ) {\n        guard let mapAnnotation = view.annotation as? MapViewAnnotation else {\n            return\n        }\n\n        onAnnotationSelected(mapAnnotation)\n    }\n\n    public func mapView(\n        _ mapView: MKMapView,\n        didDeselect view: MKAnnotationView\n    ) {\n        guard let mapAnnotation = view.annotation as? MapViewAnnotation else {\n            return\n        }\n\n        onAnnotationDeselected(mapAnnotation)\n    }\n\n    public func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {\n        onRegionChanged(mapView.region)\n    }\n\n}\n\n// MARK: - Previews\n\n#Preview {\n    MapView()\n}\n"
  }
]