SwiftUI获取用户的位置信息(CLLocationManager,CLLocationManagerDelegate)

本篇文章将会介绍一下在SwiftUI中如何通过CorLocation框架获取用户的位置信息,因为获取位置信息属于用户的隐私信息,所以需要在Info.plist文件里面加上访问位置权限的说明。
在这里插入图片描述
关于位置信息,可以请求两种级别的许可:alwayswhen in use。根据我们应用需求进行选择。我们需要在Info.plist文件上上添加这个条目,同时必须提供一个描述,向用户解释为什么你的应用程序需要位置信息(该文本将出现在询问用户权限的对话框中),比如说:“XXX App需要访问您的位置以提供基于位置的服务。”

本文采用when in use这种方式:
![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/bb719f87fd4e48dd9f578e6e7abdee60.png = 600x)

下面创建一个处理位置信息的类LocationManager

import Foundation
import CoreLocationfinal class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {// 记录位置信息@Published var currentLocation: CLLocationCoordinate2D?// 初始化CLLocationManager实例private var locManager = CLLocationManager()func checkLocationAuthorization() {// 设置代理locManager.delegate = self// 获取用户授权状态let authorizationStatus = locManager.authorizationStatusDispatchQueue.global().async { [weak self] in// 判断用户设备的系统位置权限是否开启,而非App的。该判断需要异步进行,否则会卡主线程。if CLLocationManager.locationServicesEnabled() {// 如果设备系统位置权限开启了,回主线程继续操作DispatchQueue.main.async {if authorizationStatus == .authorizedAlways || authorizationStatus == .authorizedWhenInUse {// 如果用户授权了,开启位置更新。self?.locManager.startUpdatingLocation()} else if authorizationStatus == .notDetermined {// 如果用户未曾选择过,那么弹出授权框。self?.locManager.requestWhenInUseAuthorization()} else {// 用户拒绝了,停止位置更新。self?.locManager.stopUpdatingLocation()}}} else {// 如果设备系统位置权限未开启,回主线程继续操作DispatchQueue.main.async {if authorizationStatus == .notDetermined {// 如果用户未曾选择过,那么弹出授权框。self?.locManager.requestWhenInUseAuthorization()} else {// 因系统位置权限未开启,停止位置更新。self?.locManager.stopUpdatingLocation()}}}}}// MARK: - CLLocationManagerDelegate// 每当位置更新时都会被调用,这里更新currentLocation变量。func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {if let newLocation = manager.location, !(newLocation.coordinate.longitude == 0.0 && newLocation.coordinate.latitude == 0.0) {currentLocation = newLocation.coordinate}}// 当位置管理器无法获取位置或发生错误时调用。func locationManager(_ manager: CLLocationManager, didFailWithError error: any Error) {currentLocation = nillocManager.delegate = nillocManager.stopUpdatingLocation()}// 当用户的位置权限状态发生变化时调用,例如用户从拒绝状态改为允许状态。用于根据当前的授权状态调整应用的行为,如在用户授权后开始位置更新。func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {if manager.authorizationStatus == .denied {locManager.stopUpdatingLocation()} else if manager.authorizationStatus == .authorizedAlways || manager.authorizationStatus == .authorizedWhenInUse {locManager.startUpdatingLocation()}}
}

完整代码如上,下面逐步看一下:

首先LocationManager类继承了NSObject类,并实现了CLLocationManagerDelegateObservableObject协议。
实现CLLocationManagerDelegate协议是为了处理位置信息以及授权等变更的情况;
实现ObservableObject协议,并定义了一个@Published变量,供UI显示位置信息使用。

在该类中定义两个属性,说明见注释。

  // 记录位置信息,变化时通知用到该变量的UI进行刷新。@Published var currentLocation: CLLocationCoordinate2D?// 初始化CLLocationManager实例private var locManager = CLLocationManager()

目前该类还提供了一个对外的方法checkLocationAuthorization(),该方法内设置了delegate,判断系统位置权限情况以及用户针对App的授权情况,根据不同的情况采取对应的处理方式,具体见注释。

特别说明一下CLLocationManager.locationServicesEnabled()方法获取系统位置授权情况,需要在异步进行,否则卡UI。

CLLocationManagerDelegate中,我们实现了三个基本的方法,分别处理位置信息变更,位置信息获取失败,以及用户授权状态的改变。

上面都搞定后,弄个界面显示一下位置信息:

struct LocationViewDemo: View {@StateObject private var locationManager = LocationManager()var body: some View {VStack(spacing: 30) {if let currentLocation = locationManager.currentLocation {VStack(spacing: 20) {Text("Latitude: \(currentLocation.latitude)")Text("Longitude: \(currentLocation.longitude)")}}Button("Get location") {locationManager.checkLocationAuthorization()}.buttonStyle(.borderedProminent)}.padding()}
}

App首次运行起来后:
请添加图片描述
点击后:
请添加图片描述
授权后,位置信息就显示出来了。
请添加图片描述

弹出授权框,我们可以调用下面两个方法,不同的方法对应Info.plist文件中不同配置,匹配不上就无法弹框了。

requestAlwaysAuthorization()
requestWhenInUseAuthorization()

关于manager,还有一个请求一次位置信息的方法:

locManager.requestLocation()

CLLocationManagerDelegate代码方法的说明:

// 每当位置更新时都会被调用,这里更新currentLocation变量。
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
// 当位置管理器无法获取位置或发生错误时调用。
func locationManager(_ manager: CLLocationManager, didFailWithError error: any Error)
/// 当用户的位置权限状态发生变化时调用,例如用户从拒绝状态改为允许状态。
/// 用于根据当前的授权状态调整应用的行为,如在用户授权后开始位置更新。
func locationManagerDidChangeAuthorization(_ manager: CLLocationManager)
/// 位置更新暂停时被调用
func locationManagerDidPauseLocationUpdates(_ manager: CLLocationManager)
/// 位置更新恢复时被调用
func locationManagerDidResumeLocationUpdates(_ manager: CLLocationManager)
/// 用户进入一个地理区域时被调用
func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion)
/// 用户离开一个地理区域时被调用
func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion)

最后,希望能够帮助到有需要的朋友,如果觉得有帮助,还望点个赞,添加个关注,笔者也会不断地努力,写出更多更好用的文章。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/23933.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

视频剪辑去水印软件推荐 视频剪辑去水印方法

不会去水印,很难做好视频剪辑。选对软件、掌握去水印的方法,是每个剪辑师必须经历的过程。真正擅长视频剪辑去水印的软件,一定具备多种去水印功能。剪辑师可以根据素材的具体情况,选择最恰当的去水印方法。有关视频剪辑去水印软件…

JimuReport 积木报表 v1.7.5 版本发布,免费的低代码报表

项目介绍 一款免费的数据可视化报表工具,含报表和大屏设计,像搭建积木一样在线设计报表!功能涵盖,数据报表、打印设计、图表报表、大屏设计等! Web 版报表设计器,类似于excel操作风格,通过拖拽完…

工具JS:纯前端判断运行环境是公司内网还是公网环境

工具JS:纯前端判断运行环境是公司内网还是公网环境 判断内网方式一般就2种: 后端出接口,判断请求头内ip地址,是否公司内网的ip即可前端项目内处理,利用iframe、script、img等标签支持跨域(本文介绍&#…

手机如何开启开发者选项? (小米为例)

目录 问题小米开启开发者选项 待续、更新中 问题 小米开启开发者选项 设置 我的设备 手机全部参数信息 点击 miui版本 10次 提示开启开发者选项 设置中搜索:开发者 进入 开启USB调试和USB安装即可使用计算机hbuilder进行安装软件,进行调试 待续、更新中 1 顿号、: 先使用ctrl…

【日记】遇到了一个很奇怪的大爷(845 字)

正文 花了昨天和今天两天时间,把数据转移完了。这块 2T 的硬盘可以光荣退休了。目前是没什么存储焦虑了。 农发行净开发一些垃圾系统。今天没什么业务,但跟 ActiveX 斗智斗勇了一整天,最后实在搞不过 IE 浏览器。我也懒得管了,又不…

禁用layui树形表格的多选框checkbox

1. 背景 在使用树形表格渲染数据时,需要对数据进行批量操作。相对于选中数据后,再做错误提示。直接把数据的多选框禁用掉更加直观。 2. 实现 DisabledTableCheckBox: () > {// 获取所有行 var tableElem $(".layui-table-fixed-l");var …

Promise请求接口并处理返回结果,使用fetch函数

function request(url) {return new Promise((resolve, reject) > {fetch(url).then(response > {if (response.ok) {return response.json();} else {throw new Error(请求失败);}}).then(data > {resolve(data);}).catch(error > {reject(error);});}); }// 使用…

一脉阳光上市圆梦:销售成本高昂,两大创始人的行贿往事与屡屡被罚

《港湾商业观察》施子夫 2024年6月7日,江西一脉阳光集团股份有限公司(以下简称,一脉阳光)将正式在港交所主板挂牌上市(以下简称,一脉阳光;股票代码02522.HK),公司预计发…

解释单例模式、工厂模式和观察者模式的原理和应用场景

单例模式(Singleton Pattern) 原理 单例模式确保一个类仅有一个实例,并提供一个全局访问点来访问这个唯一实例。这个模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访…

7.0 android中Service的基础知识

service的定义: Service 是一个在后台执行长时间运行操作而不提供用户界面的组件。 允许在用户没有与应用交互时操作,或者执行一些用户交互之外的操作,如音乐播放、文件上传、文件下载等。 Service的使用不影响用户的交互,且由其…

adb dump当前可见的窗口

1、窗口信息 adb shell dumpsys window windows > w.txt2、dump当前可见的窗口activity windows系统 adb shell dumpsys activity | findStr mFocusmac系统 adb shell dumpsys activity | grep mFocus3、dump当前处于栈顶的activity windows系统 adb shell dumpsys activi…

Vue3【七】setup的语法糖setup简写方法

Vue3【七】setup的语法糖setup简写方法 Vue3【七】setup的语法糖setup简写方法 使用script标签式写法称为setup语法糖 组件名称默认位文件名 export 的内容可以省略 案例截图 案例目录 案例代码 Person.vue <template><div class"person"><h1>我…

这才是计科之 Onix XV6 源码分析(1、XV6-x86的启动)

这才是计科之 Onix & XV6 源码分析&#xff08;1、XV6-x86的启动&#xff09; 前言 Onix是一款相对于XV6来说功能更为健全的单核OS&#xff0c;由于功能更加完善&#xff0c;Onix也更加复杂。代码阅读起来会比较绕。 XV6是一款简单易读的多核操作系统&#xff0c;但其功…

【JMeter接口测试工具】第一节.JMeter简介和安装【入门篇】

文章目录 前言一、JMeter简介 1.1 JMeter基本介绍 1.2 JMeter优缺点二、JMeter安装 2.1 JMeter安装步骤 2.2 JMeter环境配置三、项目介绍 3.1 项目简介 3.2 API接口清单总结 前言 一、JMeter简介 1.1 JMeter基本介绍 JMeter 是 Apache 组织使用…

js模块(module)和导入,导出(import,export)

什么是模块&#xff08;module&#xff09; 一个模块&#xff08;module&#xff09;就是一个文件。一个脚本就是一个模块。就这么简单。 模块可以相互加载&#xff0c;并可以使用特殊的指令 export 和 import 来交换功能&#xff0c;从另一个模块调用一个模块的函数或者变量…

mysql(54) : dbcp多实例使用

mysql版本: 8.0.11 java版本: 8 maven版本: 3.6.3 mave依赖 <dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.18</version></dependency><dependency><groupId&…

使用C#反射中的MAKEGENERICTYPE函数,来为泛型方法和泛型类指定(泛型的)类型

MakeGenericType 是一个在 C# 中用于创建开放类型的实例的方法。开放类型是一种未绑定类型参数的泛型类型。当你有一个泛型类型定义&#xff0c;并且想要用特定的类型实例化它时&#xff0c;你可以使用 MakeGenericType 方法。 public Type MakeGenericType (params Type[] ty…

Windows API 开发桌面应用程序,在窗口按下鼠标左键不放可以拖图,并且拖图期间鼠标图标变成手掌

在Windows API中&#xff0c;要实现鼠标左键按下并拖动以移动窗口中的某个图形&#xff0c;并且同时改变鼠标图标为“手掌”形状&#xff08;这通常指的是“拖动”或“移动”的图标&#xff09;&#xff0c;你需要执行几个步骤。 以下是一个基本的步骤指南&#xff0c;用于在W…

java---程序逻辑控制(详解)

目录 一、概述二、顺序结构三、分支结构3.1 if语句3.1.1 语法格式13.1.2 语法格式23.1.3 语法格式3 3.2 练习3.2.1 判断一个数字是奇数还是偶数3.2.2 判断一个数字是正数&#xff0c;负数&#xff0c;还是零3.2.3 判断一个年份是否为闰年 3.3.switch语句 四、循环结构4.1 while…

部署Jar包教程

文章目录 引言I 编写脚本1.1 启动1.2 关闭1.3 SSH上传jar包II 打包2.1 build中的plugins中标签的含义2.2 jar中没有主清单属性引言 I 编写脚本 1.1 启动 chmod a+x start.sh #!/bin/bash nohup java -Xms1024m -Xmx1024m -Xmn256m -XX:MaxDirectMemorySize=5G -jar SOAP-0.…