开源 Objective-C IOS 应用开发(十四)传感器--陀螺仪和gps

文章的目的为了记录使用Objective-C 进行IOS app 开发学习的经历。本职为嵌入式软件开发,公司安排开发app,临时学习,完成app的开发。开发流程和要点有些记忆模糊,赶紧记录,防止忘记。

相关链接:

开源 Objective-C IOS 应用开发(一)macOS 的使用

开源 Objective-C IOS 应用开发(二)Xcode安装

开源 Objective-C IOS 应用开发(三)第一个iPhone的APP

开源 Objective-C IOS 应用开发(四)Xcode工程文件结构

开源 Objective-C IOS 应用开发(五)iOS操作(action)和输出口(Outlet)

推荐链接:

开源 Arkts 鸿蒙应用 开发(一)工程文件分析-CSDN博客

开源 Arkts 鸿蒙应用 开发(二)封装库.har制作和应用-CSDN博客

开源 Arkts 鸿蒙应用 开发(三)Arkts的介绍-CSDN博客

开源 Arkts 鸿蒙应用 开发(四)布局和常用控件-CSDN博客

开源 Arkts 鸿蒙应用 开发(五)控件组成和复杂控件-CSDN博客

开源 Arkts 鸿蒙应用 开发(六)数据持久--文件和首选项存储-CSDN博客

开源 Arkts 鸿蒙应用 开发(七)数据持久--sqlite关系数据库-CSDN博客

开源 Arkts 鸿蒙应用 开发(八)多媒体--相册和相机-CSDN博客

开源 Arkts 鸿蒙应用 开发(九)通讯--tcp客户端-CSDN博客

开源 Arkts 鸿蒙应用 开发(十)通讯--Http-CSDN博客

开源 Arkts 鸿蒙应用 开发(十一)证书和包名修改-CSDN博客

开源 Arkts 鸿蒙应用 开发(十二)传感器的使用-CSDN博客

开源 Arkts 鸿蒙应用 开发(十三)音频--MP3播放_arkts avplayer播放音频 mp3-CSDN博客

开源 Arkts 鸿蒙应用 开发(十四)线程--任务池(taskpool)-CSDN博客

开源 Arkts 鸿蒙应用 开发(十五)自定义绘图控件--仪表盘-CSDN博客

开源 Arkts 鸿蒙应用 开发(十六)自定义绘图控件--波形图-CSDN博客

开源 Arkts 鸿蒙应用 开发(十七)通讯--http多文件下载-CSDN博客

开源 Arkts 鸿蒙应用 开发(十八)通讯--Ble低功耗蓝牙服务器-CSDN博客

推荐链接:

开源 java android app 开发(一)开发环境的搭建-CSDN博客

开源 java android app 开发(二)工程文件结构-CSDN博客

开源 java android app 开发(三)GUI界面布局和常用组件-CSDN博客

开源 java android app 开发(四)GUI界面重要组件-CSDN博客

开源 java android app 开发(五)文件和数据库存储-CSDN博客

开源 java android app 开发(六)多媒体使用-CSDN博客

开源 java android app 开发(七)通讯之Tcp和Http-CSDN博客

开源 java android app 开发(八)通讯之Mqtt和Ble-CSDN博客

开源 java android app 开发(九)后台之线程和服务-CSDN博客

开源 java android app 开发(十)广播机制-CSDN博客

开源 java android app 开发(十一)调试、发布-CSDN博客

开源 java android app 开发(十二)封库.aar-CSDN博客

本章内容主要演示iphone传感器的数据读取,读取陀螺仪和gps的数据。

目录:

1.手机演示

2.所有源码

3.源码分析

一、手机演示

二、所有源码

AppDelegate.h文件

复制代码
#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;

@end

AppDelegate.m文件

复制代码
#import "AppDelegate.h"
#import "ViewController.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // 创建窗口
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    
    // 创建ViewController
    ViewController *viewController = [[ViewController alloc] init];
    
    // 设置根视图控制器
    self.window.rootViewController = viewController;
    
    // 显示窗口
    [self.window makeKeyAndVisible];
    
    return YES;
}

@end

ViewController.h文件

复制代码
#import <UIKit/UIKit.h>
#import <CoreMotion/CoreMotion.h>
#import <CoreLocation/CoreLocation.h>

@interface ViewController : UIViewController <CLLocationManagerDelegate>

@property (strong, nonatomic) UITextField *gyroTextField;
@property (strong, nonatomic) UITextField *gpsTextField;
@property (strong, nonatomic) UIButton *sensorButton;

// 运动管理器
@property (strong, nonatomic) CMMotionManager *motionManager;
// 位置管理器
@property (strong, nonatomic) CLLocationManager *locationManager;

@end

ViewController.m文件

复制代码
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupUI];
    [self setupSensors];
}

- (void)setupUI {
    self.view.backgroundColor = [UIColor whiteColor];
    
    // 获取屏幕尺寸
    CGRect screenBounds = [UIScreen mainScreen].bounds;
    CGFloat screenWidth = screenBounds.size.width;
    
    // 陀螺仪文本框
    self.gyroTextField = [[UITextField alloc] initWithFrame:CGRectMake(20, 100, screenWidth - 40, 40)];
    self.gyroTextField.placeholder = @"陀螺仪数据将显示在这里";
    self.gyroTextField.borderStyle = UITextBorderStyleRoundedRect;
    self.gyroTextField.enabled = NO;
    self.gyroTextField.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:self.gyroTextField];
    
    // GPS文本框
    self.gpsTextField = [[UITextField alloc] initWithFrame:CGRectMake(20, 160, screenWidth - 40, 40)];
    self.gpsTextField.placeholder = @"GPS数据将显示在这里";
    self.gpsTextField.borderStyle = UITextBorderStyleRoundedRect;
    self.gpsTextField.enabled = NO;
    self.gpsTextField.textAlignment = NSTextAlignmentCenter;
    [self.view addSubview:self.gpsTextField];
    
    // 传感器按钮
    self.sensorButton = [UIButton buttonWithType:UIButtonTypeSystem];
    self.sensorButton.frame = CGRectMake(20, 220, screenWidth - 40, 44);
    [self.sensorButton setTitle:@"开始读取传感器数据" forState:UIControlStateNormal];
    [self.sensorButton setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    self.sensorButton.backgroundColor = [UIColor systemBlueColor];
    self.sensorButton.layer.cornerRadius = 8;
    [self.sensorButton addTarget:self action:@selector(toggleSensorReading) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.sensorButton];
    
    // 添加标题标签
    UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 60, screenWidth - 40, 30)];
    titleLabel.text = @"传感器数据读取";
    titleLabel.textAlignment = NSTextAlignmentCenter;
    titleLabel.font = [UIFont boldSystemFontOfSize:18];
    [self.view addSubview:titleLabel];
}

- (void)setupSensors {
    // 初始化运动管理器
    self.motionManager = [[CMMotionManager alloc] init];
    
    // 初始化位置管理器
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest;
}

- (void)toggleSensorReading {
    if ([self.sensorButton.titleLabel.text isEqualToString:@"开始读取传感器数据"]) {
        [self startSensorReading];
        [self.sensorButton setTitle:@"停止读取传感器数据" forState:UIControlStateNormal];
    } else {
        [self stopSensorReading];
        [self.sensorButton setTitle:@"开始读取传感器数据" forState:UIControlStateNormal];
    }
}

- (void)startSensorReading {
    // 开始陀螺仪数据读取
    if (self.motionManager.isGyroAvailable) {
        self.motionManager.gyroUpdateInterval = 0.1; // 更新频率10Hz
        
        [self.motionManager startGyroUpdatesToQueue:[NSOperationQueue mainQueue] withHandler:^(CMGyroData * _Nullable gyroData, NSError * _Nullable error) {
            if (error) {
                self.gyroTextField.text = [NSString stringWithFormat:@"陀螺仪错误: %@", error.localizedDescription];
                return;
            }
            
            if (gyroData) {
                NSString *gyroText = [NSString stringWithFormat:@"X: %.4f, Y: %.4f, Z: %.4f",
                                    gyroData.rotationRate.x,
                                    gyroData.rotationRate.y,
                                    gyroData.rotationRate.z];
                self.gyroTextField.text = gyroText;
            }
        }];
    } else {
        self.gyroTextField.text = @"陀螺仪不可用";
    }
    
    // 请求位置权限并开始GPS更新
    if ([CLLocationManager locationServicesEnabled]) {
        CLAuthorizationStatus status = [CLLocationManager authorizationStatus];
        
        if (status == kCLAuthorizationStatusNotDetermined) {
            [self.locationManager requestWhenInUseAuthorization];
        } else if (status == kCLAuthorizationStatusAuthorizedWhenInUse ||
                   status == kCLAuthorizationStatusAuthorizedAlways) {
            [self.locationManager startUpdatingLocation];
        } else {
            self.gpsTextField.text = @"位置服务未授权";
        }
    } else {
        self.gpsTextField.text = @"位置服务不可用";
    }
}

- (void)stopSensorReading {
    // 停止陀螺仪更新
    if (self.motionManager.isGyroActive) {
        [self.motionManager stopGyroUpdates];
    }
    
    // 停止位置更新
    [self.locationManager stopUpdatingLocation];
    
    self.gyroTextField.text = @"已停止";
    self.gpsTextField.text = @"已停止";
}

#pragma mark - CLLocationManagerDelegate

- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    CLLocation *currentLocation = [locations lastObject];
    
    NSString *gpsText = [NSString stringWithFormat:@"经度: %.6f, 纬度: %.6f",
                        currentLocation.coordinate.longitude,
                        currentLocation.coordinate.latitude];
    self.gpsTextField.text = gpsText;
}

- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    self.gpsTextField.text = [NSString stringWithFormat:@"GPS错误: %@", error.localizedDescription];
}

- (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager {
    CLAuthorizationStatus status = manager.authorizationStatus;
    
    if (status == kCLAuthorizationStatusAuthorizedWhenInUse ||
        status == kCLAuthorizationStatusAuthorizedAlways) {
        [self.locationManager startUpdatingLocation];
    } else if (status == kCLAuthorizationStatusDenied) {
        self.gpsTextField.text = @"位置服务被拒绝";
    }
}

- (void)dealloc {
    [self stopSensorReading];
}

@end

info.plist文件

复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>UIApplicationSceneManifest</key>
	<dict>
		<key>UIApplicationSupportsMultipleScenes</key>
		<false/>
		<key>UISceneConfigurations</key>
		<dict>
			<key>UIWindowSceneSessionRoleApplication</key>
			<array>
				<dict>
					<key>UISceneConfigurationName</key>
					<string>Default Configuration</string>
					<key>UISceneDelegateClassName</key>
					<string>SceneDelegate</string>
					<key>UISceneStoryboardFile</key>
					<string>Main</string>
				</dict>
			</array>
		</dict>
	</dict>
    <key>NSLocationWhenInUseUsageDescription</key>
    <string>需要您的位置权限来显示GPS数据</string>
</dict>
</plist>

三、源码分析

AppDelegate.h

复制代码
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
  • 功能:声明AppDelegate类,继承UIResponder,遵循UIApplicationDelegate协议

  • 关键属性UIWindow *window - 应用的主窗口

AppDelegate.m

application:didFinishLaunchingWithOptions:

复制代码
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // 创建窗口 - 使用屏幕边界初始化窗口
    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];

    // 创建ViewController - 初始化主视图控制器
    ViewController *viewController = [[ViewController alloc] init];

    // 设置根视图控制器 - 将ViewController设置为窗口的根控制器
    self.window.rootViewController = viewController;

    // 显示窗口 - 使窗口可见并设置为关键窗口
    [self.window makeKeyAndVisible];

    return YES;
}

作用:应用启动入口点,完成窗口和界面初始化

ViewController.h

复制代码
@interface ViewController : UIViewController <CLLocationManagerDelegate>
// UI控件属性
@property (strong, nonatomic) UITextField *gyroTextField;
@property (strong, nonatomic) UITextField *gpsTextField;
@property (strong, nonatomic) UIButton *sensorButton;

// 传感器管理器
@property (strong, nonatomic) CMMotionManager *motionManager;
@property (strong, nonatomic) CLLocationManager *locationManager;
@end

功能:声明视图控制器类,遵循CLLocationManagerDelegate协议,定义所有UI和传感器相关属性

ViewController.m

viewDidLoad

复制代码
- (void)viewDidLoad {
    [super viewDidLoad];
    [self setupUI];      // 初始化用户界面
    [self setupSensors]; // 初始化传感器
}

作用:视图控制器加载完成后调用,进行界面和传感器的初始化

setupUI

复制代码
- (void)setupUI {
    // 设置背景色
    self.view.backgroundColor = [UIColor whiteColor];

    // 获取屏幕尺寸
    CGRect screenBounds = [UIScreen mainScreen].bounds;
    CGFloat screenWidth = screenBounds.size.width;

    // 创建并配置陀螺仪文本框
    self.gyroTextField = [[UITextField alloc] initWithFrame:CGRectMake(20, 100, screenWidth - 40, 40)];
    // ... 文本框属性设置
    [self.view addSubview:self.gyroTextField];

    // 创建并配置GPS文本框
    self.gpsTextField = [[UITextField alloc] initWithFrame:CGRectMake(20, 160, screenWidth - 40, 40)];
    // ... 文本框属性设置
    [self.view addSubview:self.gpsTextField];

    // 创建并配置传感器按钮
    self.sensorButton = [UIButton buttonWithType:UIButtonTypeSystem];
    self.sensorButton.frame = CGRectMake(20, 220, screenWidth - 40, 44);
    // ... 按钮属性设置
    [self.sensorButton addTarget:self action:@selector(toggleSensorReading) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.sensorButton];

    // 创建并配置标题标签
    UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(20, 60, screenWidth - 40, 30)];
    // ... 标签属性设置
    [self.view addSubview:titleLabel];
}

作用:创建所有UI控件并设置它们的布局和属性

setupSensors

复制代码
- (void)setupSensors {
    // 初始化运动管理器 - 用于访问陀螺仪等运动数据
    self.motionManager = [[CMMotionManager alloc] init];

    // 初始化位置管理器 - 用于访问GPS位置数据
    self.locationManager = [[CLLocationManager alloc] init];
    self.locationManager.delegate = self;           // 设置代理
    self.locationManager.desiredAccuracy = kCLLocationAccuracyBest; // 设置定位精度
}

作用:初始化传感器管理器对象

toggleSensorReading

复制代码
- (void)toggleSensorReading {
    if ([self.sensorButton.titleLabel.text isEqualToString:@"开始读取传感器数据"]) {
        [self startSensorReading];  // 开始读取
        [self.sensorButton setTitle:@"停止读取传感器数据" forState:UIControlStateNormal];
    } else {
        [self stopSensorReading];   // 停止读取
        [self.sensorButton setTitle:@"开始读取传感器数据" forState:UIControlStateNormal];
    }
}

作用:按钮点击事件处理,切换传感器读取状态

startSensorReading

复制代码
- (void)startSensorReading {
    // 陀螺仪部分
    if (self.motionManager.isGyroAvailable) {
        self.motionManager.gyroUpdateInterval = 0.1; // 设置更新频率为10Hz

        // 开始陀螺仪更新,使用主队列接收数据
        [self.motionManager startGyroUpdatesToQueue:[NSOperationQueue mainQueue] 
          withHandler:^(CMGyroData *gyroData, NSError *error) {
            // 处理陀螺仪数据或错误
        }];
    }

    // GPS部分
    if ([CLLocationManager locationServicesEnabled]) {
        CLAuthorizationStatus status = [CLLocationManager authorizationStatus];

        // 根据权限状态处理
        if (status == kCLAuthorizationStatusNotDetermined) {
            [self.locationManager requestWhenInUseAuthorization]; // 请求权限
        } else if (有权限) {
            [self.locationManager startUpdatingLocation]; // 开始定位
        }
    }
}

作用:启动所有传感器数据读取

stopSensorReading

复制代码
- (void)stopSensorReading {
    // 停止陀螺仪更新
    if (self.motionManager.isGyroActive) {
        [self.motionManager stopGyroUpdates];
    }

    // 停止位置更新
    [self.locationManager stopUpdatingLocation];

    // 更新UI显示
    self.gyroTextField.text = @"已停止";
    self.gpsTextField.text = @"已停止";
}

作用:停止所有传感器数据读取

CLLocationManagerDelegate 方法

locationManager:didUpdateLocations:

复制代码
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *> *)locations {
    CLLocation *currentLocation = [locations lastObject]; // 获取最新位置
    // 格式化并显示经纬度信息
    NSString *gpsText = [NSString stringWithFormat:@"经度: %.6f, 纬度: %.6f",
                        currentLocation.coordinate.longitude,
                        currentLocation.coordinate.latitude];
    self.gpsTextField.text = gpsText;
}

作用:位置更新时调用,显示新的GPS坐标

locationManager:didFailWithError:

复制代码
- (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error {
    self.gpsTextField.text = [NSString stringWithFormat:@"GPS错误: %@", error.localizedDescription];
}

作用:定位失败时调用,显示错误信息

locationManagerDidChangeAuthorization:

复制代码
- (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager {
    CLAuthorizationStatus status = manager.authorizationStatus;

    // 权限状态变化时处理
    if (有权限) {
        [self.locationManager startUpdatingLocation]; // 开始定位
    } else if (被拒绝) {
        self.gpsTextField.text = @"位置服务被拒绝"; // 显示拒绝信息
    }
}

作用:位置权限状态变化时调用

dealloc

复制代码
- (void)dealloc {
    [self stopSensorReading]; // 停止所有传感器读取
}

作用:对象销毁时调用,清理资源

代码执行流程:

  1. 启动application:didFinishLaunchingWithOptions:

  2. 界面加载viewDidLoadsetupUI + setupSensors

  3. 用户交互toggleSensorReadingstartSensorReading/stopSensorReading

  4. 数据更新 → 陀螺仪handler / 位置代理方法更新UI

  5. 权限处理locationManagerDidChangeAuthorization: 处理权限状态变化

相关推荐
二流小码农3 小时前
鸿蒙开发:支持自定义组件的跑马灯
android·ios·harmonyos
HelloGitHub5 小时前
节省 60% Token 的新数据格式「GitHub 热点速览」
开源·github
2501_915106325 小时前
iOS 抓包全流程指南,HTTPS 抓包、TCP 数据流分析与多工具协同的方法论
android·tcp/ip·ios·小程序·https·uni-app·iphone
xixixi7777712 小时前
了解一下Sentry(一个开源的实时错误监控平台)
前端·安全·开源·安全威胁分析·监控·sentry
q***710113 小时前
开源模型应用落地-工具使用篇-Spring AI-Function Call(八)
人工智能·spring·开源
极限实验室13 小时前
Coco AI 参选 Gitee 2025 最受欢迎开源软件!您的每一票,都是对中国开源的硬核支持
人工智能·开源
3***499613 小时前
Swift Experience
开发语言·ios·swift
AscendKing15 小时前
开源项目分享 图像深度学习Demo项目
开源·好好学电脑·hhxdn.com
七宝大爷16 小时前
定义 LLM 格局:开源与闭源两大阵营的较量
开源·闭源·gpu集群