logo-library

Platform Swift Swift Package Manager

SwiftLocation 是 Apple CoreLocation 框架的轻量级封装,支持新的 Swift 并发模型。

这意味着不再需要处理委托模式,也不再需要完成块
您可以直接使用新的 async/await 语法来管理位置请求、区域和 Beacon 监控。

例如,您想获取当前用户的位置吗?
只需 2 行代码即可搞定

try await location.requestPermission(.whenInUse) // obtain the permissions
let userLocation = try await location.requestLocation() // get the location

工作原理

SwiftLocation 非常易于使用。
只需创建您自己的 Location 实例并使用可用的方法之一。

重要提示

由于特定的硬件限制,某些 API 可能在某些受支持的平台上不可用。

6.0 版本的新功能

新的 6.0 里程碑是一个完全重写的版本,旨在最佳地支持 async/await。我们还专注于支持所有 CoreLocation 功能,而不会创建一个过于臃肿的软件包。
所有功能都由完整的单元测试套件支持。

这个新版本也仅通过 Swift Package Manager (5.5+) 分发,并且与所有 Apple 平台兼容:iOS 14+、macOS 11+、watchOS 7+、tvOS 14+。

版本 5.x 中的功能 - 地理编码、IP 解析、自动完成 - 将在后续开发过程中作为单独的可下载模块包含。

服务位置状态

使用 location.locationServicesEnabled 获取位置服务的当前状态。
为了监控更改,您可以使用 AsyncStream 的 `startMonitoringLocationServices()` 方法

for await event in await location.startMonitoringLocationServices() {
 print("Location Services are \(event.isLocationEnabled ? "enabled" : "disabled")"
 // break to interrupt the stream
}

您可以随时使用 break 停止流;它将在使用的 `Location` 实例上自动调用 `stopMonitoringLocationServices()`。

授权状态

您可以使用 location.authorizationStatus 属性获取授权状态的当前状态。
如果您需要监控此值的更改,您可以使用 startMonitoringAuthorization() 方法提供的 AsyncStream

for await event in await location.startMonitoringAuthorization() {
  print("Authorization status did change: \(event.authorizationStatus)")
  // break to interrupt the stream
}

精确度授权级别

location.accuracyAuthorization 提供应用程序提供的当前精度级别的单次值。
当您需要监控更改时,您可以使用 startMonitoringAccuracyAuthorization() 提供的 AsyncStream

for await event in await location.startMonitoringAccuracyAuthorization() {
  print("Accuracy authorization did change: \(event.accuracyAuthorization.description)")
  // break to interrupt the stream
}

请求位置权限

位置权限请求也通过 async await 管理。一旦您正确配置了 Info.plist 文件,您就可以使用 requestPermission() 方法

// return obtained CLAuthorizationStatus level
let obtaninedStatus = try await location.requestPermission(.whenInUse)

提供有关您如何使用位置服务的描述

首次进行授权请求时,系统会显示一个警报,询问用户是否授予或拒绝该请求。警报包含一个使用描述字符串,用于解释您为何需要访问位置数据。

您在应用程序的 Info.plist 文件中提供此字符串,并使用它来告知用户您的应用程序如何使用位置数据。

Core Location 支持每个访问级别的不同使用字符串。您必须包含“使用时”访问的使用描述字符串。如果您的应用程序支持“始终”访问,请提供额外的字符串来解释您为何需要更高的权限。下表列出了要包含在 Info.plist 中的键以及何时包含它们。

使用键 何时需要
NSLocationWhenInUseUsageDescription 应用程序请求“使用时”或“始终”授权时。
NSLocationAlwaysAndWhenInUseUsageDescription 应用程序请求“始终”授权时。
NSLocationTemporaryUsageDescriptionDictionary 当您想要临时扩展您的授权级别的精度时使用

请求临时精确度权限

如果应用程序并非所有功能都需要精确位置,但仅在特定功能(例如,在结账、预订服务等期间)需要精确位置,则应用程序可以仅针对该会话使用 requestTemporaryPrecisionAuthorization(purpose:) 方法请求临时精度级别

// return CLAccuracyAuthorization value
let status = try await location.requestTemporaryPrecisionAuthorization(purpose: "booking")

持续位置监控

如果您需要持续监控来自用户设备的新位置,您可以使用 startMonitoringLocations() 提供的 AsyncStream

for await event in try await location.startMonitoringLocations() {
    switch event {
    case .didPaused:
	// location updates paused
    case .didResume:
    // location updates resumed
    case let .didUpdateLocations(locations):
    // new locations received   
    case let .didFailed(error):
    // an error has occurred   
    }
    // break to stop the stream
}

请求一次性用户位置

有时您可能需要将用户位置作为单个值获取。async 的 requestLocation(accuracy:timeout:) 方法旨在在有效的时间间隔内返回可选的过滤位置

// Simple implementation to get the last user location
let location = try await location.requestLocation()

// Optionally you can return a value only if satisfy one or more constraints
let location = try await location.requestLocation(accuracy: [
    .horizontal(100) // has an horizontal accuracy of 100 meters or lower
], timeout: 8) // wait for response for a max of 8 seconds

过滤器包括水平/垂直、速度、航向精度,并提供设置自定义过滤器函数作为回调的机会。

访问监控

访问监控允许您观察用户去过的地方。
访问对象由系统创建并由 CLLocationManager 传递。访问对象包括访问发生的位置以及关于到达和离开时间的相关信息。

要监控访问,您可以使用 AsyncStreamstartMonitoringVisits() 方法

for await event in await location.startMonitoringVisits() {
    switch event {
    case let .didVisit(place):
    // a new CLVisit object has been received.   
    case let .didFailWithError(error):
    // an error has occurred
    }
}

重要位置变更监控

AsyncStreamstartMonitoringSignificantLocationChanges() 方法启动基于重要位置变更的更新生成。

for await event in await self.location.startMonitoringSignificantLocationChanges() {
    switch event {
    case .didPaused:
    // stream paused
    case .didResume:
    // stream resumed
    case .didUpdateLocations(locations):
    // new locations received
    case let .didFailWithError(error):
    // an error has occured
    }
	// break to stop the stream
}

设备朝向监控

要获取有关当前设备朝向的更新,请使用 startUpdatingHeading() 方法提供的 AsyncStream

for await event in await self.location.startUpdatingHeading() {
	// a new heading value has been generated
}

Beacon 测距

Beacon 测距由 AsyncStreamstartRangingBeacons() 方法提供

let constraint: CLBeaconIdentityConstraint = ...
for await event in await location.startRangingBeacons(satisfying: constraint) {
	// a new event has been generated
}

测试套件和模拟 CLLocationManager

SwiftLocation 分发时附带了一个广泛的单元测试套件,您可以在 SwiftLocationTests 文件夹中找到它。
在套件内部,您还将找到 MockedLocationManager.swift 文件,这是一个 CLLocationManager 模拟类,您可以使用它为您的应用程序提供测试套件。通过配置和扩展此文件,您将能够在您的宿主应用程序中直接模拟位置请求和监控的结果。

通过 SPM 安装

SwiftLocation 通过 Swift Package Manager 提供。
将其作为依赖项添加到 Swift Package 中,并将其添加到您的 Package.swift

dependencies: [
  .package(url: "https://github.com/malcommac/SwiftLocation.git", from: "6.0.0")
]

支持此项目 ❤️

如果您喜欢这个库并希望鼓励进一步开发,请考虑通过 Github Sponsorship 成为我工作的赞助商

许可证

此软件包由 Daniele Margutti 创建和维护。

它使用 MIT 许可证 分发。

贡献

阅读 CONTRIBUTING 文件以获取更多信息。