Repository: sgade/swiftui-mapview
Branch: main
Commit: b29e45510019
Files: 21
Total size: 38.7 KB
Directory structure:
gitextract_pa7cjpmw/
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── MapViewExample/
│ ├── MapViewExample/
│ │ ├── Assets.xcassets/
│ │ │ ├── AccentColor.colorset/
│ │ │ │ └── Contents.json
│ │ │ ├── AppIcon.appiconset/
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── CLLocationCoordinate2D+Examples.swift
│ │ ├── ContentView.swift
│ │ ├── ExampleAnnotation.swift
│ │ └── MapViewExampleApp.swift
│ └── MapViewExample.xcodeproj/
│ ├── project.pbxproj
│ └── project.xcworkspace/
│ └── contents.xcworkspacedata
├── Package.swift
├── README.md
└── Sources/
└── SwiftUIMapView/
├── AnnotationViews/
│ ├── MapAnnotationClusterView.swift
│ └── MapAnnotationView.swift
├── Annotations/
│ ├── MKMapView+MapViewAnnotation.swift
│ └── MapViewAnnotation.swift
├── CoreLocation+Equatable.swift
├── MapView+Xcode.swift
└── MapView.swift
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
.DS_Store
/.build
/Packages
xcuserdata/
DerivedData/
.swiftpm/configuration/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to SwiftUI MapView
You're welcome to contribute improvements and fixes to the project.
Thank you for your time investment!
Please read the following guide to ensure consistency and a shared level of quality for your contribution.
The goal is to have everything ready so that the process is as straight forward as possible for everyone.
If there are instructions missing, feel free to contribute changes to this guide as well.
**Before you start contributing** please make sure of the following:
1. Ensure that you have a clear goal in mind. Proposing or implementing changes should not divert from the project's goal.
2. When unsure of whether your changes meet the project's goal open an issue to discuss your intentions and its consequences.
**When opening issues or pull requests** please make sure of the following:
1. Describe the specific goal of the issue or pull request. Focus on one topic so that it can be worked on in isolation.
2. Add your thoughts and questions to the description so that issues can be addressed quickly.
3. Highlight important sections in code that need attention and are critical to understanding the changes.
4. 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).
Once 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.
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2020 Sören Gade
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: MapViewExample/MapViewExample/Assets.xcassets/AccentColor.colorset/Contents.json
================================================
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: MapViewExample/MapViewExample/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
"images" : [
{
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "tinted"
}
],
"idiom" : "universal",
"platform" : "ios",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: MapViewExample/MapViewExample/Assets.xcassets/Contents.json
================================================
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
================================================
FILE: MapViewExample/MapViewExample/CLLocationCoordinate2D+Examples.swift
================================================
//
// CLLocationCoordinate2D+Examples.swift
// MapViewExample
//
// Created by Sören Gade on 21.02.20.
//
import CoreLocation
extension CLLocationCoordinate2D {
static let inifiniteLoop = CLLocationCoordinate2D(
latitude: 37.331836,
longitude: -122.029604
)
static let applePark = CLLocationCoordinate2D(
latitude: 37.334780,
longitude: -122.009073
)
}
================================================
FILE: MapViewExample/MapViewExample/ContentView.swift
================================================
//
// ContentView.swift
// MapViewExample
//
// Created by Sören Gade on 21.02.20.
//
import SwiftUI
import SwiftUIMapView
import CoreLocation
import MapKit
struct ContentView: View {
@State
private var region: MKCoordinateRegion? = MKCoordinateRegion(
center: .applePark,
span: MKCoordinateSpan(
latitudeDelta: 0.05,
longitudeDelta: 0.05
)
)
@State
private var selectedAnnotations: [MapViewAnnotation] = []
private let locationManager = CLLocationManager()
var body: some View {
VStack {
MapView(
mapType: .standard,
region: $region,
showsUserLocation: true,
userTrackingMode: .none,
annotations: [ExampleAnnotation].examples,
selectedAnnotations: $selectedAnnotations
)
.edgesIgnoringSafeArea(.all)
ForEach(selectedAnnotations.compactMap { $0 as? ExampleAnnotation }) { annotation in
Text("\( annotation.title ?? "" )")
}
if let region {
Text("\(region.center.latitude), \(region.center.longitude)")
}
}
.onAppear {
// this is required to display the user's current location
locationManager.requestWhenInUseAuthorization()
}
}
}
// MARK: - Previews
#Preview {
ContentView()
}
================================================
FILE: MapViewExample/MapViewExample/ExampleAnnotation.swift
================================================
//
// ExampleAnnotation.swift
// MapViewExample
//
// Created by Sören Gade on 21.02.20.
//
import SwiftUIMapView
import MapKit
class ExampleAnnotation: NSObject, MapViewAnnotation, Identifiable {
let coordinate: CLLocationCoordinate2D
let title: String?
let id = UUID()
let clusteringIdentifier: String? = "exampleCluster"
let glyphImage: UIImage? = UIImage(systemName: "e.circle.fill")
let tintColor: UIColor? = .green
init(title: String, coordinate: CLLocationCoordinate2D) {
self.title = title
self.coordinate = coordinate
}
}
// MARK: - Array+ExampleAnnotation
extension Array where Element == ExampleAnnotation {
static let examples: [ExampleAnnotation] = [
ExampleAnnotation(title: "Apple Park", coordinate: .applePark),
ExampleAnnotation(title: "Infinite Loop", coordinate: .inifiniteLoop),
]
}
================================================
FILE: MapViewExample/MapViewExample/MapViewExampleApp.swift
================================================
//
// MapViewExampleApp.swift
// MapViewExample
//
// Created by Sören Gade on 16.12.25.
//
import SwiftUI
@main
struct MapViewExampleApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
================================================
FILE: MapViewExample/MapViewExample.xcodeproj/project.pbxproj
================================================
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 77;
objects = {
/* Begin PBXBuildFile section */
45DDF4992EF1CFE5001077C5 /* SwiftUIMapView in Frameworks */ = {isa = PBXBuildFile; productRef = 45DDF4982EF1CFE5001077C5 /* SwiftUIMapView */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
45DDF4892EF1CF73001077C5 /* MapViewExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MapViewExample.app; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
/* Begin PBXFileSystemSynchronizedRootGroup section */
45DDF48B2EF1CF73001077C5 /* MapViewExample */ = {
isa = PBXFileSystemSynchronizedRootGroup;
path = MapViewExample;
sourceTree = "<group>";
};
/* End PBXFileSystemSynchronizedRootGroup section */
/* Begin PBXFrameworksBuildPhase section */
45DDF4862EF1CF73001077C5 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
45DDF4992EF1CFE5001077C5 /* SwiftUIMapView in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
45DDF4802EF1CF73001077C5 = {
isa = PBXGroup;
children = (
45DDF48B2EF1CF73001077C5 /* MapViewExample */,
45DDF48A2EF1CF73001077C5 /* Products */,
);
sourceTree = "<group>";
};
45DDF48A2EF1CF73001077C5 /* Products */ = {
isa = PBXGroup;
children = (
45DDF4892EF1CF73001077C5 /* MapViewExample.app */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
45DDF4882EF1CF73001077C5 /* MapViewExample */ = {
isa = PBXNativeTarget;
buildConfigurationList = 45DDF4942EF1CF74001077C5 /* Build configuration list for PBXNativeTarget "MapViewExample" */;
buildPhases = (
45DDF4852EF1CF73001077C5 /* Sources */,
45DDF4862EF1CF73001077C5 /* Frameworks */,
45DDF4872EF1CF73001077C5 /* Resources */,
);
buildRules = (
);
dependencies = (
);
fileSystemSynchronizedGroups = (
45DDF48B2EF1CF73001077C5 /* MapViewExample */,
);
name = MapViewExample;
packageProductDependencies = (
45DDF4982EF1CFE5001077C5 /* SwiftUIMapView */,
);
productName = MapViewExample;
productReference = 45DDF4892EF1CF73001077C5 /* MapViewExample.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
45DDF4812EF1CF73001077C5 /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastSwiftUpdateCheck = 2620;
LastUpgradeCheck = 2620;
TargetAttributes = {
45DDF4882EF1CF73001077C5 = {
CreatedOnToolsVersion = 26.2;
};
};
};
buildConfigurationList = 45DDF4842EF1CF73001077C5 /* Build configuration list for PBXProject "MapViewExample" */;
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 45DDF4802EF1CF73001077C5;
minimizedProjectReferenceProxies = 1;
packageReferences = (
45DDF4972EF1CFE5001077C5 /* XCLocalSwiftPackageReference "../../swiftui-mapview" */,
);
preferredProjectObjectVersion = 77;
productRefGroup = 45DDF48A2EF1CF73001077C5 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
45DDF4882EF1CF73001077C5 /* MapViewExample */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
45DDF4872EF1CF73001077C5 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
45DDF4852EF1CF73001077C5 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
45DDF4922EF1CF74001077C5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 26.2;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
name = Debug;
};
45DDF4932EF1CF74001077C5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_USER_SCRIPT_SANDBOXING = YES;
GCC_C_LANGUAGE_STANDARD = gnu17;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 26.2;
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
SWIFT_COMPILATION_MODE = wholemodule;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
45DDF4952EF1CF74001077C5 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "The app shows the user's location.";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = de.sgade.MapViewExample;
PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = YES;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
45DDF4962EF1CF74001077C5 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
ENABLE_APP_SANDBOX = YES;
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_OUTGOING_NETWORK_CONNECTIONS = YES;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSLocationWhenInUseUsageDescription = "The app shows the user's location.";
INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchScreen_Generation = YES;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
PRODUCT_BUNDLE_IDENTIFIER = de.sgade.MapViewExample;
PRODUCT_NAME = "$(TARGET_NAME)";
REGISTER_APP_GROUPS = YES;
STRING_CATALOG_GENERATE_SYMBOLS = YES;
SUPPORTED_PLATFORMS = "iphoneos iphonesimulator";
SUPPORTS_MACCATALYST = NO;
SUPPORTS_MAC_DESIGNED_FOR_IPHONE_IPAD = NO;
SUPPORTS_XR_DESIGNED_FOR_IPHONE_IPAD = NO;
SWIFT_APPROACHABLE_CONCURRENCY = YES;
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
SWIFT_VERSION = 6.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
45DDF4842EF1CF73001077C5 /* Build configuration list for PBXProject "MapViewExample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
45DDF4922EF1CF74001077C5 /* Debug */,
45DDF4932EF1CF74001077C5 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
45DDF4942EF1CF74001077C5 /* Build configuration list for PBXNativeTarget "MapViewExample" */ = {
isa = XCConfigurationList;
buildConfigurations = (
45DDF4952EF1CF74001077C5 /* Debug */,
45DDF4962EF1CF74001077C5 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCLocalSwiftPackageReference section */
45DDF4972EF1CFE5001077C5 /* XCLocalSwiftPackageReference "../../swiftui-mapview" */ = {
isa = XCLocalSwiftPackageReference;
relativePath = "../../swiftui-mapview";
};
/* End XCLocalSwiftPackageReference section */
/* Begin XCSwiftPackageProductDependency section */
45DDF4982EF1CFE5001077C5 /* SwiftUIMapView */ = {
isa = XCSwiftPackageProductDependency;
productName = SwiftUIMapView;
};
/* End XCSwiftPackageProductDependency section */
};
rootObject = 45DDF4812EF1CF73001077C5 /* Project object */;
}
================================================
FILE: MapViewExample/MapViewExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata
================================================
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>
================================================
FILE: Package.swift
================================================
// swift-tools-version: 6.2
import PackageDescription
let package = Package(
name: "swiftui-mapview",
platforms: [
.iOS(.v13)
],
products: [
.library(
name: "SwiftUIMapView",
targets: ["SwiftUIMapView"]
),
],
dependencies: [],
targets: [
.target(
name: "SwiftUIMapView",
dependencies: [],
swiftSettings: [
.defaultIsolation(MainActor.self)
]
)
]
)
================================================
FILE: README.md
================================================
# swiftui-mapview

[](https://swiftpackageindex.com/sgade/swiftui-mapview)

[MKMapView](https://developer.apple.com/documentation/mapkit/mkmapview) in SwiftUI.
**For iOS 17 and later, I recommend you use Apple's official [Map](https://developer.apple.com/documentation/mapkit/map) view.**
[](assets/screen.png)
(Click the image to see the full screenshot)
## Install
Using Xcode, select `File` -> `Swift Packages` -> `Add Package Dependency` and enter `https://github.com/sgade/swiftui-mapview`.
## Usage
In your view, add the map.
See the [example project](MapViewExample) for how to integrate the map view.
```swift
import SwiftUIMapView
struct ContentView: View {
var body: some View {
MapView()
}
}
```
## Configuration
### Map type
```swift
MapView(mapType: .standard)
```
### User location
### Showing the current user location
The current location can be shown on the map.
Note that the application requires permission to access the current user location.
See the documentation on `MapView.showsUserLocation` for more information.
```swift
MapView(showsUserLocation: true)
```
### Tracking the user's location
```swift
MapView(userTrackingMode: .follow)
```
### Setting the visible region
The binding passed in for `region` defines the visible map region. Use it to define the visible center and zoom.
Setting it to `nil` will use the map's default region when loaded. It is also updated when the visible region changes.
```swift
@State var region: MKCoordinateRegion?
MapView(region: $region)
```
### Annotations
#### Adding annotations
Annotations are represented as objects of a custom class that implements the `MapViewAnnotation` protocol.
It might be helpful to subclass from existing classes like `MKPlacemark`.
```swift
let annotations: [MapViewAnnotation] = ...
MapView(annotations: annotations)
```
#### Selecting annotations
A list of selected annotations can be passed in via a binding.
```swift
@State var selectedAnnotations: [MapViewAnnotation] = []
MapView(selectedAnnotations: $selectedAnnotations)
```
## Contributing
See the [contributing guide](CONTRIBUTING.md).
## License
This project is licensed unter the terms of the MIT license. See [LICENSE](./LICENSE) for more information.
================================================
FILE: Sources/SwiftUIMapView/AnnotationViews/MapAnnotationClusterView.swift
================================================
//
// MapAnnotationClusterView.swift
// SwiftUIMapView
//
// Created by Sören Gade on 19.02.20.
// Copyright © 2020 Sören Gade. All rights reserved.
//
import Foundation
import MapKit
/// Custom annotation view for ``MapAnnotation`` view clusters.
///
/// This view draws its content itself and therefore has a pretty custom style.
///
/// - Seealso: ``MapAnnotationView``
class MapAnnotationClusterView: MKAnnotationView {
private static let annotationSize: CGFloat = 32
override var annotation: MKAnnotation? {
didSet {
guard let clusterAnnotation = annotation as? MKClusterAnnotation else {
return
}
let mapAnnotations = clusterAnnotation.memberAnnotations.compactMap { $0 as? MapViewAnnotation }
guard let mapAnnotation = mapAnnotations.first else {
return
}
collisionMode = .circle
image = drawGlyph(
sized: CGSize(
width: Self.annotationSize,
height: Self.annotationSize
),
colored: mapAnnotation.tintColor,
withCount: mapAnnotations.count
)
}
}
}
// MARK: Drawing glyphs
private extension MapAnnotationClusterView {
/// Draws the annotation's glyph.
func drawGlyph(
sized size: CGSize,
colored tintColor: UIColor?,
withCount count: Int
) -> UIImage {
let renderer = UIGraphicsImageRenderer(size: size)
return renderer.image { _ in
// draw background
tintColor?.setFill()
UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: size.width, height: size.height)).fill()
if let image = UIImage(systemName: "\(count).circle")?.withTintColor(.white) {
// draw glyph
let imageRect = CGRect(x: size.width / 2 - image.size.width / 2,
y: size.height / 2 - image.size.height / 2,
width: image.size.width,
height: image.size.height)
image.draw(in: imageRect)
} else {
// draw text
let fontSize: CGFloat = 24
let textAttributes: [NSAttributedString.Key: NSObject] = [
NSAttributedString.Key.foregroundColor: UIColor.black,
NSAttributedString.Key.font: UIFont.systemFont(ofSize: fontSize)
]
let text = "\(count)" as NSString
let textSize = text.size(withAttributes: textAttributes)
let textRect = CGRect(x: size.width / 2 - textSize.width / 2,
y: size.height / 2 - textSize.height / 2,
width: textSize.width,
height: textSize.height)
text.draw(in: textRect, withAttributes: textAttributes)
}
}
}
}
================================================
FILE: Sources/SwiftUIMapView/AnnotationViews/MapAnnotationView.swift
================================================
//
// MapAnnotationView.swift
// SwiftUIMapView
//
// Created by Sören Gade on 19.02.20.
// Copyright © 2020 Sören Gade. All rights reserved.
//
import Foundation
import MapKit
/// Custom annotation view for ``MapAnnotation`` objects.
///
/// Sets the view's `glyphImage` and `markerTintColor` according to values of the annotation.
/// Automatically takes advantage of clustering via an optionally set `clusteringIdentifier`.
class MapAnnotationView: MKMarkerAnnotationView {
override var annotation: MKAnnotation? {
didSet {
guard let mapAnnotation = annotation as? MapViewAnnotation else {
return
}
clusteringIdentifier = mapAnnotation.clusteringIdentifier
markerTintColor = mapAnnotation.tintColor
glyphImage = mapAnnotation.glyphImage
}
}
}
================================================
FILE: Sources/SwiftUIMapView/Annotations/MKMapView+MapViewAnnotation.swift
================================================
//
// MKMapView+MapViewAnnotation.swift
// SwiftUIMapView
//
// Created by Sören Gade on 21.02.20.
//
import MapKit
extension MKMapView {
/// All ``MapViewAnnotation``s set on the map view.
var mapViewAnnotations: [MapViewAnnotation] {
annotations.compactMap { $0 as? MapViewAnnotation }
}
/// All ``MapViewAnnotation``s selected on the map view.
var selectedMapViewAnnotations: [MapViewAnnotation] {
selectedAnnotations.compactMap { $0 as? MapViewAnnotation }
}
}
================================================
FILE: Sources/SwiftUIMapView/Annotations/MapViewAnnotation.swift
================================================
//
// MapViewAnnotation.swift
// SwiftUIMapView
//
// Created by Sören Gade on 19.02.20.
// Copyright © 2020 Sören Gade. All rights reserved.
//
import Foundation
import MapKit
/// An annotation on a ``MapView``.
///
/// Annotations can be visualized using their `title`, `subtitle`, `glyphImage` and `tintColor`.
///
/// To support automatic clustering of annotations, specify a `clusterIdentifier`.
///
/// Note: `MapAnnotation` provides a custom view class implementation for displaying the annotation data on the map.
/// Custom views are currently not supported.
public protocol MapViewAnnotation: MKAnnotation {
/// Identifier for clustering annotations.
/// Setting to a non-`nil` value marks the annotation as participant in clustering.
///
/// - Seealso: MKAnnotationView.clusteringIdentifier
var clusteringIdentifier: String? {
get
}
/// The image to display as a glyph in the annotation's view.
var glyphImage: UIImage? {
get
}
/// The tint color of the annotations's view.
var tintColor: UIColor? {
get
}
}
================================================
FILE: Sources/SwiftUIMapView/CoreLocation+Equatable.swift
================================================
//
// CoreLocation+Equatable.swift
// SwiftUIMapView
//
// Created by Sören Gade on 24.02.20.
//
import Foundation
import CoreLocation
import MapKit
// MARK: - CLLocationCoordinate2D
extension CLLocationCoordinate2D: @retroactive Equatable {
public static func ==(lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool {
lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
}
}
// MARK: - MKCoordinateSpan
extension MKCoordinateSpan: @retroactive Equatable {
public static func ==(lhs: MKCoordinateSpan, rhs: MKCoordinateSpan) -> Bool {
lhs.latitudeDelta == rhs.latitudeDelta && lhs.longitudeDelta == rhs.longitudeDelta
}
}
================================================
FILE: Sources/SwiftUIMapView/MapView+Xcode.swift
================================================
//
// MapView+Xcode.swift
// SwiftUIMapView
//
// Created by Sören Gade on 26.06.20.
//
#if canImport(DeveloperToolsSupport)
import DeveloperToolsSupport
@available(iOS 14.0, *)
struct LibraryViewContent: LibraryContentProvider {
var views: [LibraryItem] {
LibraryItem(MapView())
}
}
#endif
================================================
FILE: Sources/SwiftUIMapView/MapView.swift
================================================
//
// MapView.swift
// SwiftUIMapView
//
// Created by Sören Gade on 14.01.20.
// Copyright © 2020 Sören Gade. All rights reserved.
//
import SwiftUI
import MapKit
import Combine
import UIKit
/// Displays a map.
/// The contents of the map are provided by the Apple Maps service.
///
/// See the [official documentation](https://developer.apple.com/documentation/mapkit/mkmapview) for more information
/// on the possibilities provided by the underlying service.
public struct MapView: UIViewRepresentable {
/// The region that is displayed.
///
/// Note: The region might not be used as-is, as it might need to be fitted to the view's bounds.
/// See [regionThatFits(_:)](https://developer.apple.com/documentation/mapkit/mkmapview/1452371-regionthatfits).
@Binding
private var region: MKCoordinateRegion?
/// The currently selected annotations.
///
/// When the user selects annotations on the map the value of this binding changes.
/// Likewise, setting the value of this binding to a value selects the given annotations.
@Binding
private var selectedAnnotations: [MapViewAnnotation]
/// Annotations that are displayed on the map.
///
///
/// See the `selectedAnnotation` binding for more information about user selection of annotations.
private let annotations: [MapViewAnnotation]
/// The map type that is displayed.
private let mapType: MKMapType
/// Determines whether the map can be zoomed.
private let isZoomEnabled: Bool
/// Determines whether the map can be scrolled.
private let isScrollEnabled: Bool
/// Determines whether the map can be rotated.
private let isRotateEnabled: Bool
/// Determines whether the current user location is displayed.
///
/// This requires the `NSLocationWhenInUseUsageDescription` key in the Info.plist to be set.
/// In addition, you need to call [`CLLocationManager.requestWhenInUseAuthorization()`](https://developer.apple.com/documentation/corelocation/cllocationmanager/1620562-requestwheninuseauthorization)
/// to request for permission.
private let showsUserLocation: Bool
/// Sets the map's user tracking mode.
private let userTrackingMode: MKUserTrackingMode
/// Creates a new MapView.
///
/// - Parameters:
/// - mapType: The map type to display.
/// - region: The region to display.
/// - isZoomEnabled: Whether the map can be zoomed.
/// - isScrollEnabled: Whether the map can be scrolled.
/// - isRotateEnabled: Whether the map can be rotated.
/// - showsUserLocation: Whether to display the user's current location.
/// - userTrackingMode: The user tracking mode.
/// - annotations: A list of `MapAnnotation`s that should be displayed on the map.
/// - selectedAnnotation: A binding to the currently selected annotation, or `nil`.
public init(
mapType: MKMapType = .standard,
region: Binding<MKCoordinateRegion?> = .constant(nil),
isZoomEnabled: Bool = true,
isScrollEnabled: Bool = true,
isRotateEnabled: Bool = true,
showsUserLocation: Bool = false,
userTrackingMode: MKUserTrackingMode = .none,
annotations: [MapViewAnnotation] = [],
selectedAnnotations: Binding<[MapViewAnnotation]> = .constant([])
) {
self.mapType = mapType
self._region = region
self.isZoomEnabled = isZoomEnabled
self.isScrollEnabled = isScrollEnabled
self.isRotateEnabled = isRotateEnabled
self.showsUserLocation = showsUserLocation
self.userTrackingMode = userTrackingMode
self.annotations = annotations
self._selectedAnnotations = selectedAnnotations
}
}
// MARK: - UIViewRepresentable
extension MapView {
public func makeCoordinator() -> Coordinator {
Coordinator()
}
public func makeUIView(context: Context) -> MKMapView {
let mapView = MKMapView()
mapView.delegate = context.coordinator
// register custom annotation view classes
mapView.register(
MapAnnotationView.self,
forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier
)
mapView.register(
MapAnnotationClusterView.self,
forAnnotationViewWithReuseIdentifier: MKMapViewDefaultClusterAnnotationViewReuseIdentifier
)
// perform initial view state
configure(
mapView,
context: context,
animated: false
)
return mapView
}
public func updateUIView(
_ mapView: MKMapView,
context: Context
) {
configure(
mapView,
context: context,
animated: true
)
}
}
// MARK: Configuring view state
private extension MapView {
/// Configures the `mapView`'s state according to the current view state.
func configure(
_ mapView: MKMapView,
context: Context,
animated: Bool
) {
if let region {
let region = mapView.regionThatFits(region)
if region.center != mapView.region.center || region.span != mapView.region.span {
mapView.setRegion(region, animated: animated)
}
}
mapView.mapType = mapType
mapView.isZoomEnabled = isZoomEnabled
mapView.isScrollEnabled = isScrollEnabled
mapView.isRotateEnabled = isRotateEnabled
mapView.showsUserLocation = showsUserLocation
mapView.userTrackingMode = userTrackingMode
// annotation configuration
updateAnnotations(in: mapView)
updateSelectedAnnotation(
in: mapView,
animated: animated
)
// update coordinator with new view instance
context.coordinator.onRegionChanged = { region in
Task {
// avoid modifying state during view update
self.region = region
}
}
context.coordinator.onAnnotationSelected = { annotation in
selectedAnnotations.append(annotation)
}
context.coordinator.onAnnotationDeselected = { annotation in
guard let index = selectedAnnotations.firstIndex(where: { annotation.isEqual($0) }) else {
return
}
selectedAnnotations.remove(at: index)
}
}
/// Updates the annotation property of the `mapView`.
/// Calculates the difference between the current and new states and only executes changes on those diff sets.
///
/// - Parameter mapView: The ``MKMapView`` to configure.
func updateAnnotations(in mapView: MKMapView) {
let currentAnnotations = mapView.mapViewAnnotations
// remove old annotations
let obsoleteAnnotations = currentAnnotations.filter { mapAnnotation in
!annotations.contains { $0.isEqual(mapAnnotation) }
}
mapView.removeAnnotations(obsoleteAnnotations)
// add new annotations
let newAnnotations = annotations.filter { mapViewAnnotation in
!currentAnnotations.contains { $0.isEqual(mapViewAnnotation) }
}
mapView.addAnnotations(newAnnotations)
}
/// Updates the selection annotations of the `mapView`.
/// Calculates the difference between the current and new selection states and only executes changes on those diff sets.
///
/// - Parameters:
/// - mapView: The ``MKMapView`` to configure.
/// - animated: Whether to animate the change.
func updateSelectedAnnotation(
in mapView: MKMapView,
animated: Bool
) {
// deselect annotations that are not currently selected
let oldSelections = mapView.selectedMapViewAnnotations.filter { oldSelection in
!selectedAnnotations.contains {
oldSelection.isEqual($0)
}
}
for annotation in oldSelections {
mapView.deselectAnnotation(annotation, animated: false)
}
// select all new annotations
let newSelections = selectedAnnotations.filter { selection in
!mapView.selectedMapViewAnnotations.contains {
selection.isEqual($0)
}
}
for annotation in newSelections {
mapView.selectAnnotation(annotation, animated: animated)
}
}
}
// MARK: - Coordinator
public extension MapView {
final class Coordinator: NSObject, MKMapViewDelegate {
var onRegionChanged: (MKCoordinateRegion) -> Void = { _ in }
var onAnnotationSelected: (MapViewAnnotation) -> Void = { _ in }
var onAnnotationDeselected: (MapViewAnnotation) -> Void = { _ in }
}
}
// MARK: MKMapViewDelegate
extension MapView.Coordinator {
public func mapView(
_ mapView: MKMapView,
didSelect view: MKAnnotationView
) {
guard let mapAnnotation = view.annotation as? MapViewAnnotation else {
return
}
onAnnotationSelected(mapAnnotation)
}
public func mapView(
_ mapView: MKMapView,
didDeselect view: MKAnnotationView
) {
guard let mapAnnotation = view.annotation as? MapViewAnnotation else {
return
}
onAnnotationDeselected(mapAnnotation)
}
public func mapViewDidChangeVisibleRegion(_ mapView: MKMapView) {
onRegionChanged(mapView.region)
}
}
// MARK: - Previews
#Preview {
MapView()
}
gitextract_pa7cjpmw/
├── .gitignore
├── CONTRIBUTING.md
├── LICENSE
├── MapViewExample/
│ ├── MapViewExample/
│ │ ├── Assets.xcassets/
│ │ │ ├── AccentColor.colorset/
│ │ │ │ └── Contents.json
│ │ │ ├── AppIcon.appiconset/
│ │ │ │ └── Contents.json
│ │ │ └── Contents.json
│ │ ├── CLLocationCoordinate2D+Examples.swift
│ │ ├── ContentView.swift
│ │ ├── ExampleAnnotation.swift
│ │ └── MapViewExampleApp.swift
│ └── MapViewExample.xcodeproj/
│ ├── project.pbxproj
│ └── project.xcworkspace/
│ └── contents.xcworkspacedata
├── Package.swift
├── README.md
└── Sources/
└── SwiftUIMapView/
├── AnnotationViews/
│ ├── MapAnnotationClusterView.swift
│ └── MapAnnotationView.swift
├── Annotations/
│ ├── MKMapView+MapViewAnnotation.swift
│ └── MapViewAnnotation.swift
├── CoreLocation+Equatable.swift
├── MapView+Xcode.swift
└── MapView.swift
Condensed preview — 21 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (44K chars).
[
{
"path": ".gitignore",
"chars": 159,
"preview": ".DS_Store\n/.build\n/Packages\nxcuserdata/\nDerivedData/\n.swiftpm/configuration/registries.json\n.swiftpm/xcode/package.xcwor"
},
{
"path": "CONTRIBUTING.md",
"chars": 1526,
"preview": "# Contributing to SwiftUI MapView\n\nYou're welcome to contribute improvements and fixes to the project.\nThank you for you"
},
{
"path": "LICENSE",
"chars": 1067,
"preview": "MIT License\n\nCopyright (c) 2020 Sören Gade\n\nPermission is hereby granted, free of charge, to any person obtaining a copy"
},
{
"path": "MapViewExample/MapViewExample/Assets.xcassets/AccentColor.colorset/Contents.json",
"chars": 123,
"preview": "{\n \"colors\" : [\n {\n \"idiom\" : \"universal\"\n }\n ],\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }"
},
{
"path": "MapViewExample/MapViewExample/Assets.xcassets/AppIcon.appiconset/Contents.json",
"chars": 607,
"preview": "{\n \"images\" : [\n {\n \"idiom\" : \"universal\",\n \"platform\" : \"ios\",\n \"size\" : \"1024x1024\"\n },\n {\n "
},
{
"path": "MapViewExample/MapViewExample/Assets.xcassets/Contents.json",
"chars": 63,
"preview": "{\n \"info\" : {\n \"author\" : \"xcode\",\n \"version\" : 1\n }\n}\n"
},
{
"path": "MapViewExample/MapViewExample/CLLocationCoordinate2D+Examples.swift",
"chars": 421,
"preview": "//\n// CLLocationCoordinate2D+Examples.swift\n// MapViewExample\n//\n// Created by Sören Gade on 21.02.20.\n//\n\nimport Cor"
},
{
"path": "MapViewExample/MapViewExample/ContentView.swift",
"chars": 1444,
"preview": "//\n// ContentView.swift\n// MapViewExample\n//\n// Created by Sören Gade on 21.02.20.\n//\n\nimport SwiftUI\nimport SwiftUIM"
},
{
"path": "MapViewExample/MapViewExample/ExampleAnnotation.swift",
"chars": 924,
"preview": "//\n// ExampleAnnotation.swift\n// MapViewExample\n//\n// Created by Sören Gade on 21.02.20.\n//\n\nimport SwiftUIMapView\nim"
},
{
"path": "MapViewExample/MapViewExample/MapViewExampleApp.swift",
"chars": 245,
"preview": "//\n// MapViewExampleApp.swift\n// MapViewExample\n//\n// Created by Sören Gade on 16.12.25.\n//\n\nimport SwiftUI\n\n@main\nst"
},
{
"path": "MapViewExample/MapViewExample.xcodeproj/project.pbxproj",
"chars": 13664,
"preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 77;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
},
{
"path": "MapViewExample/MapViewExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
"chars": 135,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n version = \"1.0\">\n <FileRef\n location = \"self:\">\n </FileRef"
},
{
"path": "Package.swift",
"chars": 510,
"preview": "// swift-tools-version: 6.2\n\nimport PackageDescription\n\nlet package = Package(\n name: \"swiftui-mapview\",\n platform"
},
{
"path": "README.md",
"chars": 2612,
"preview": "# swiftui-mapview\n\n\n[. The extraction includes 21 files (38.7 KB), approximately 10.6k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.