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 CoreLocation

final class LocationManager: NSObject, CLLocationManagerDelegate, ObservableObject {

  // 记录位置信息
  @Published var currentLocation: CLLocationCoordinate2D?

  // 初始化CLLocationManager实例
  private var locManager = CLLocationManager()

  func checkLocationAuthorization() {
    // 设置代理
    locManager.delegate = self

    // 获取用户授权状态
    let authorizationStatus = locManager.authorizationStatus


    DispatchQueue.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 = nil
    locManager.delegate = nil
    locManager.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)

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

图的创建和BFS,DFS遍历

图的创建 图是一种用于表示对象及其关系的抽象数据结构,由节点(也称为顶点)和连接节点的边组成。图可以分为有向图(Directed Graph)和无向图(Undirected Graph),以及加权图&…

Redis的事务与关系型数据库事务有何不同?

引言:关于 Redis 的事务很多人可能都是一知半解,大多数人只了解数据库的事务,并且是单体事务,对于 Redis 事务和常见关系型数据库的事务的区别还没有去了解过,本文就来详细进行介绍。 题目 Redis的事务与关系型数据库…

git【工具软件】分布式版本控制工具软件

一、Git 的介绍 git软件的作用:管理软件开发项目中的源代码文件。 常用功能: 仓库管理、文件管理、分支管理、标签管理、远程操作 功能指令: add,commit,log,branch,tag,remote…

UE5 Mod Support 思路——纯蓝图

原创作者:Chatouille 核心功能 “Get Blueprint Assets”节点,用于加载未来的mod。用基础类BP_Base扩展即可。打包成补丁,放到Content\Paks目录下,即可让游戏访问到内容。 与文中所写不同的地方 5.1或者5.2开始,打…

mysql optimizer_switch : 查询优化器优化策略深入解析

码到三十五 : 个人主页 在 MySQL 数据库中,查询优化器是一个至关重要的组件,它负责确定执行 SQL 查询的最有效方法。为了提供DBA和开发者更多的灵活性和控制权,MySQL 引入了 optimizer_switch 系统变量。这个强大的工具允许用户开…

自动驾驶仿真(高速道路)LaneKeeping

前言 A high-level decision agent trained by deep reinforcement learning (DRL) performs quantitative interpretation of behavioral planning performed in an autonomous driving (AD) highway simulation. The framework relies on the calculation of SHAP values an…

Go微服务: 基于使用场景理解分布式之二阶段提交

概述 二阶段提交(Two-Phase Commit,2PC)是一种分布式事务协议,用于在分布式系统中确保多个参与者的操作具有原子性即所有参与者要么全部提交事务,要么全部回滚事务,以维持数据的一致性它分为两个阶段进行&…

3038. 相同分数的最大操作数目 I

题目 给你一个整数数组 nums,如果 nums 至少包含 2 个元素,你可以执行以下操作: 选择 nums 中的前两个元素并将它们删除。一次操作的分数是被删除元素的和。 在确保所有操作分数相同的前提下,请你求出最多能进行多少次操作。 …

数字IC后端物理验证PV | TSMC 12nm Calibre Base Layer DRC案例解析

基于TSMC 12nm ARM A55 upf flow后端设计实现训练营将于6月中旬正式开班!小班教学!目前还有3个名额,招满为止!有需要可以私信小编 ic-backend2018报名。吾爱IC社区所有训练营课程均为直播课! 这个课程支持升级成双核A…

李廉洋:6.7黄金亚盘洗盘暴跌,美盘最新分析策略。

黄金消息面分析:美联储降息可能是经济出现麻烦的信号。自去年10月以来,美国股市一直在上涨,原因是尽管利率持续走高,但美国经济和企业盈利仍保持强劲。如果市场对2024年下半年降息的信心增强,那么硬着陆的可能性就会增…

python-df的合并与Matplotlib绘图

1 数据连接 concat merge join (append 作为了解) append 竖直方向追加, 在最新的pandas版本中已经被删除掉了, 这里推荐使用concat 1.1 pd.concat 两张表, 通过行名、列名对齐进行连接 import pandas as pd df1 …

MS1112驱动开发

作者简介: 一个平凡而乐于分享的小比特,中南民族大学通信工程专业研究生在读,研究方向无线联邦学习 擅长领域:驱动开发,嵌入式软件开发,BSP开发 作者主页:一个平凡而乐于分享的小比特的个人主页…

【电路笔记】-分贝

分贝 分贝是以 10 为底的对数比,用于表示电路中功率、电压或电流的增加或减少。 1、概述 一般来说,分贝是响度的度量。 在设计或使用放大器和滤波器电路时,计算中使用的一些数字可能非常大或非常小。 例如,如果我们将两个放大器级级联在一起,功率或电压增益分别为 20 和…

嵌入式Linux系统编程 — 2.1 标准I/O库简介

目录 1 标准I/O库简介 1.1 标准I/O库简介 1.2 标准 I/O 和文件 I/O 的区别 2 FILE 指针 3 标准I/O库的主要函数简介 4 标准输入、标准输出和标准错误 4.1 标准输入、标准输出和标准错误概念 4.2 示例程序 5 打开文件fopen() 5.1 fopen()函数简介 5.2 新建文件的权限…

全程自动化操作 自动生成图文发布,矩阵批量软件系统 日产1-3万篇

一、简介 图文发布对于现代网站运营至关重要,然而手动创建和发布图文内容效率低下且易出错。全自动化图文生成发布流程可以解决这个问题。本文将详细说明如何以编程方式实现这一流程。 二、模块设计 该流程主要包含三个模块:图像生成,文本生成…

前端解析文件流格式数据异常时并给提示

把后端返回的文件流格式转换成正常数据格式 断点调试返回值 network查看返回值 一、blob类型 let stringData:any await this.blobToString(res); blobToString(blob) { return new Promise((resolve, reject) > { const reader new FileReader(); reader.onloadend (…

通过U盘将第三方软件安装到各大品牌电视的方法

在本教程中,小武给大家整理了通过U盘的方式安装第三方软件到电视盒子上,可直接使用通用U盘的方式来进行安装。 如果您相应电视品牌按通用方式无法完成需求,下面为您也贴心整理了20款主流智能电视和电视盒子的U盘安装指南。这些步骤适用于小米…

Vxe UI vxe-form 实现折叠表单,当表单很多时实现自动收起与展开

Vxe UI vue vxe-form 实现折叠表单&#xff0c;当表单很多时实现自动收起与展开 代码 folding 用于将当前表单项设置为默认隐藏 collapse-node 设置折叠按钮&#xff0c;加上之后会自动在该表单项的右侧显示一个折叠按钮 <template><div><vxe-formtitle-colo…

c++ EECS280

Introduction Euchre (pronounced “YOO-kur”) is a card game popular in Michigan. The learning goals of this project include Abstract Data Types in C, Derived Classes, Inheritance, and Polymorphism. You’ll gain practice with C-style Object Oriented Progr…

操盘手专栏 | 0-1搞懂TikTok广告优化该怎么玩!

如果你正想要或计划投放TikTok广告来提高杠杆效益&#xff0c;是否有面临下面的难题&#xff1a; 难找到系统的TikTok投放知识&#xff1f; 不懂得如何制定广告计划&#xff1f; 投放效果怎样才算有效优化&#xff1f; ...... 为此&#xff0c;超店有数邀请到了拥有8年营销…