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

news2024/10/5 21:19:29

本篇文章将会介绍一下在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)

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

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

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

相关文章

项目经理进入职场都会经历的三个阶段

对于项目经理而言,进入职场是一个不断学习和成长的过程。在这个过程中,项目经理通常会经历三个主要阶段,每个阶段都有其独特的特点和挑战。 一、基础建设与学习阶段 对于新入行的项目经理来说,最初的阶段主要是基础技能的积累和…

AI绘画中的色彩空间转换技术

在数字艺术的广阔天地中,AI绘画作为一种新兴的创作方式,正以其独特的魅力吸引着越来越多的关注。它不仅仅是一种技术,更是一种全新的艺术表现形式。而在AI绘画的背后,色彩空间转换技术起着至关重要的作用。今天,我们就…

政安晨【零基础玩转各类开源AI项目】:解析开源项目:Champ 利用三维参数指导制作可控且一致的人体图像动画

目录 论文题目 Champ: 利用三维参数指导制作可控且一致的人体图像动画 安装 创建 conda 环境: 使用 pip 安装软件包 推理 1. 下载预训练模型 2. 准备准备引导动作数据 运行推理 训练模型 准备数据集 运行训练脚本 数据集 政安晨的个人主页:…

Web LLM 攻击技术

概述 在ChatGPT问世以来,我也尝试挖掘过ChatGPT的漏洞,不过仅仅发现过一些小问题:无法显示xml的bug和错误信息泄露,虽然也挖到过一些开源LLM的漏洞,比如前段时间发现的Jan的漏洞,但是不得不说传统漏洞越来…

抖音外卖区域代理需要多少钱?入局成本如何计算?

随着抖音外卖的日益火爆和抖音外卖平台全国代理的退场,想要申请抖音外卖平台区域代理的人数不断上涨。但是,创业毕竟不是儿戏,每一个决定都需要经过权衡利弊。而就做抖音外卖区域代理这一项目而言,抖音外卖平台区域代理需要多少钱…

洛杉矶裸机云多IP服务器网线路测评

在当今日益数字化的世界中,服务器的网络线路质量对于企业的运营效率和用户体验具有至关重要的作用。特别是对于那些寻求在洛杉矶部署裸机云多IP服务器的企业来说,了解服务器的网络线路质量显得尤为重要。本文将对洛杉矶裸机云多IP服务器的网络线路进行测…

Idea解决堆栈溢出

废话不说了,这问题搞了我两天,最近在用内网办公,没用公网,所以博客暂时没更新

QA | 关于智能座舱SusPIS-ATx系统常见问题答疑

前沿 在上一期《基于SusPIS-ATx的座舱仿真系统搭建与评估方法创意研讨会》中,我们围绕汽车智能座舱仿真测试相关评价规范和法规(如C-ICAP),引入了智能座舱测试行业难点及次生问题,介绍了基于SusPIS-ATx的智能座舱全域…

原花青素优化定向壳聚糖微通道的简单免疫调控结构设计

引用信息 文 章:A facile Immunoregulatory Constructional Design by Proanthocyanidin Optimizing Directional Chitosan Microchannel 期 刊:Small(影响因子:13.3) 发表时间:29/02/2024 作 …

多项目管理,如何平衡资源分配和优先级?

在多项目管理中,平衡资源分配和优先级是一项至关重要的任务,这不仅关乎项目的顺利进行,还直接影响到组织的整体效率和战略目标的实现。如果不能合理进行资源分配,容易引起资源的浪费和关键项目进度延期等问题,这不利于…

target resources requests storage size is smaller than the source

在进行dv克隆时,通过如下方式: kind: DataVolume metadata:annotations:cdi.kubevirt.io/storage.deleteAfterCompletion: "false"name: 7713bb8fdecd462fa0ca726e21cd9fa3-1namespace: default spec:pvc:accessModes:- ReadWriteManyresourc…

源代码加密:构筑软件安全的核心防线

在数字化时代,源代码作为软件的灵魂,承载着企业的核心竞争力和创新成果。源代码加密,作为一种精密的安全措施,旨在构建一道坚不可摧的防线,保护这些珍贵的数字资产免受未授权访问和泄露的威胁。 源代码加密的核心价值在…

霸王餐系统:解决新店销量,老店单量增长的秘诀

前言 在如今的外卖市场中,新店如何快速突破基础销量,老店又怎样持续增加单量,一直是商家们关注的焦点。霸王餐系统,便是一个行之有效的解决方案,它不仅以独特的业务模式吸引了消费者,更助力商家实现了销量…

工业信息化SCI期刊,中科院1区TOP,IF=12.3,收稿范围广泛

一、期刊名称 IEEE Transactions on Industrial Informatics 二、期刊简介概况 期刊类型:SCI 学科领域:工程工业 影响因子:12.3 中科院分区:1区TOP 三、期刊征稿范围 IEEE工业信息学汇刊是一本多学科期刊,发表技…

分布式版本控制工具软件——Git概述

目录 一、Git概述1.为什么要学习Git?(1)SCM概念(2)SCM实现 2.什么是版本控制?(1)版本控制软件的基础功能(2)集中式版本控制(3)分布式版…

【LeetCode热题100总结】239. 滑动窗口最大值

题目描述 给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。 返回 滑动窗口中的最大值 。 示例 1: 输入:nums [1,3,-1,-3,5,3,6,7]…

存储设备有哪些?属于私有云平台吗?怎么理解?

数字化的今天,数据已经成为了企业最重要最宝贵的资产了。为了保障数据的安全、可靠和高效利用,存储设备和云计算技术应运而生。今天我们大家就来聊聊存储设备有哪些?属于私有云平台吗?怎么理解? 存储设备有哪些&…

重塑认知科学中的“行为”理解,提升智能体决策能力

编者按:随着科技的不断进步,人工智能与认知科学的交叉研究已成为推动科学前沿的重要力量。其中,习惯性行为与目标导向行为的相互作用是心理学、认知神经科学和人工智能等领域都十分关注的研究课题,因为从简单的日常习惯到复杂的决…

linux 开放mysql端口

问题 在配置mysql后,需要放开3306端口,出现了FirewallD is not running错误 [roothadoop102 mysql]# firewall-cmd --zonepublic --add-port3306/tcp --permanent FirewallD is not running 1.启动firewalld systemctl start firewalld 2.查看firew…

算法 java 排序和查找

排序和查找 冒泡排序(稳定)选择排序(不稳定)插入排序(稳定)希尔排序(不稳定)归并排序(稳定)快速排序(不稳定)堆排序计数排序桶排序基数…