「OC」NSPredicate —— 使用谓词过滤元素

news2025/1/10 21:06:54

「OC」NSPredicate —— 使用谓词过滤元素

文章目录

  • 「OC」NSPredicate —— 使用谓词过滤元素
    • 前言
    • 介绍
    • 常见用法
      • **比较运算符**
      • **逻辑运算符**
      • **字符串比较运算符**
      • **聚合运算符**
      • **用于字典或者类当中**
      • **格式说明符(占位符)**
    • 实际运用
    • 总结
    • 参考文章

前言

在暑假的3Gshared和学生管理系统之中,无论是登陆注册界面还是学生信息的输入,都存在需要我们对输入内容进行限制,于是我们就需要找到一个方法来解决对输入内容的判断限制,就是NSPredicate——谓词来过滤输入的元素。由于在暑假的几个任务之中只是知道如何使用,并没有仔细了解,乘着暑假剩下的空闲时间进行学习总结。

介绍

NSPredicate类是用来定义逻辑条件约束的获取或内存中的过滤搜索,该对象可以准确的描述所需条件,对每个对象通过谓词进行筛选,判断是否与条件相匹配。使用NSPredicate可以有效地过滤和查询数据,提高数据处理的效率和灵活性。在Core Data中,NSPredicate常用于构建Fetch请求,从数据库中检索符合特定条件的数据。同时,在使用集合类(如NSArray、NSDictionary)时,NSPredicate也可以用来对数据进行过滤和排序。

首先我们需要了解构建谓词的常用运算符

请添加图片描述

此处为运算符的总结,看起来有点无从下手是吧,别急,后文在用到的时候还会再将功能贴出

了解完运算符,我们就可以了解如何使用NSPredicate,谓词表达式由表达式、运算符和值构成。

  1. predicateWithFormat:创建一个谓词。
+ (id)predicateWithFormat:(NSString *)format...;
  1. evaluateWithObject:接受对象,根据指定的对象计算自身的值。
-(BOOL)evaluateWithObject:(id)value;

谓词的一个常用功能就是对集合进行过滤,当程序使用谓词对集合进行过滤时,程序将会自动遍历集合元素,并根据集合元素来计算谓词的值,只有当根据某个集合元素计算谓词并返回YES时,该集合元素才会被保留下来。

//使用指定的谓词过滤NSArray集合,返回符合条件的元素组成的新集合
- (NSArray*)filteredArrayUsingPredicate:(NSPredicate *)predicate;

//使用指定的谓词过滤NSMutableArray,剔除集合中不符合条件的元素
- (void)filterUsingPredicate:(NSPredicate *)predicate;


常见用法

比较运算符

=、==:判断两个表达式是否相等,在谓词中===相同的意思都是判断,而没有赋值这一说

NSNumber *num = @123;
NSPredicate *pre = [NSPredicate predicateWithFormat:@"SELF == 123"];//此处 = 与 == 的功能是相同的
if ([pre evaluateWithObject:num]) {
    NSLog(@"1");
} else {
    NSLog(@"2");
}

>=,=>:判断左边表达式的值是否大于或等于右边表达式的值

<=,=<:判断左边表达式的值是否小于或等于右边表达式的值

`>`:判断左边表达式的值是否大于右边表达式的值

<:判断左边表达式的值是否小于右边表达式的值

!=、<>:判断两个表达式是否不相等

BETWEEN:BETWEEN表达式必须满足表达式 BETWEEN {下限,上限}的格式,要求该表达式必须大于或等于下限,并小于或等于上限

BETWEEN的用法:

NSNumber *num = @123;
NSPredicate *pre = [NSPredicate predicateWithFormat:@"SELF BETWEEN {40,123}"];
if ([pre evaluateWithObject:num]) {
    NSLog(@"1");
} else {
    NSLog(@"2");
}

逻辑运算符

AND、&&:逻辑与,要求两个表达式的值都为YES时,结果才为YES。

OR、||:逻辑或,要求其中一个表达式为YES时,结果就是YES

NOT、 !:逻辑非,对原有的表达式取反

AND、&&

NSArray *testArray = @[@1, @2, @3, @4, @5, @6];
 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF > 2 && SELF < 5"];//此处AND 和 &&效果相同
 NSArray *filterArray = [testArray filteredArrayUsingPredicate:predicate];
 NSLog(@"filterArray:%@", filterArray);

NOT、 !:此处用了IN,不了解的读者可以先往后看

NSArray *filterArray = @[@"ab", @"abc"];
 NSArray *array = @[@"a", @"ab", @"abc", @"abcd"];
 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NOT (SELF IN %@)", filterArray];
 NSLog(@"%@", [array filteredArrayUsingPredicate:predicate]);//取了array之中与filterArray的非交集

字符串比较运算符

  • BEGINSWITH:检查某个字符串是否以指定的字符串开头
  • ENDSWITH:检查某个字符串是否以指定的字符串结尾
  • CONTAINS:检查某个字符串是否包含指定的字符串
  • LIKE:检查某个字符串是否匹配指定的字符串模板。其之后可以跟?代表一个字符和代表任意多个字符两个通配符。比如"name LIKE ‘ac’",这表示name的值中包含ac则返回YES;"name LIKE '?ac’",表示name的第2、3个字符为ac时返回YES。?代表的是一个未知符号,*可以代表模糊搜索不指定个数,可以看看下文的例子
  • MATCHES:检查某个字符串是否匹配指定的正则表达式。值得一提的是正则表达式的执行效率是最低的,但其功能是最强大的,也是我们最常用的。

下面我们将每个比较运算符都进行举例(对于比较运算符来说,是不用区分大小写的,即 BEGINSWITH 和 beginwith 相同

注:字符串比较都是区分大小写和重音符号的。如:café和cafe是不一样的,Cafe和cafe也是不一样的。如果希望字符串比较运算不区分大小写和重音符号,请在这些运算符后使用[c],[d]选项。其中[c]是不区分大小写,[d]是不区分重音符号,其写在字符串比较运算符之后,比如:name LIKE[cd] ‘cafe’,那么不论name是cafe、Cafe还是café上面的表达式都会返回YES。

BEGINSWITH:

NSMutableArray *array = [NSMutableArray arrayWithObjects:@"Nick", @"Ben", @"Adam", @"Melissa",@"alice",@"你好",@"啊",nil];//定义数组
    NSArray *tempArray = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF BEGINSWITH 'a'"]];//过滤以a开头的元素, 如果为BEGINSWITH[c]则代表忽略大小写
    NSLog(@"tempArray:%@", tempArray);

ENDSWITH

NSMutableArray *array = [NSMutableArray arrayWithObjects:@"Nick", @"Ben", @"Adam", @"Melissa",@"alice",@"你好",@"啊",nil];//定义数组
NSArray *tempArray1 =  [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF ENDSWITH[c] 'a'"]]; //以a结尾的元素
NSLog(@"tempArray1:%@", tempArray1);

CONTAINS

NSMutableArray *array = [NSMutableArray arrayWithObjects:@"Nick", @"Ben", @"Adam", @"Melissa",@"alice",@"你好",@"啊",nil];//定义数组
 NSArray *tempArray2 = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF contains[c] 'e'"]]; //包含有e的元素
NSLog(@"tempArray1:%@", tempArray2);

LIKE

过滤中间有e 的元素

NSArray *tempArray3 =   [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF like[cd] '*e*' "]];

过滤以N开头的元素

NSArray *tempArray5 =   [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF like[cd] 'N*' "]];

MATCHES

检验手机号码的程序

- (BOOL)checkPhoneNumber:(NSString *)phoneNumber
{
    NSString *regex = @"^[1][3-8]\\d{9}$";
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    return [pred evaluateWithObject:phoneNumber];
}

关于正则表达式的使用,有兴趣的读者可以看一下以下文章:

正则表达式在IOS中的应用及IOS中三种正则表达式的使用与比较

聚合运算符

  • ANY、SOME:集合中任意一个元素满足条件,就返回YES。
  • ALL:集合中所有元素都满足条件,才返回YES。
  • NONE:集合中没有任何元素满足条件就返回YES。如:NONE person.age < 18,表示person集合中所有元素的age>=18时,才返回YES。
  • IN:只有当左边表达式或值出现在右边的集合中才会返回YES。

IN:(聚合运算符之中的举例默认都为IN示例之中的array1和array2)

NSArray *array1 = [NSArray arrayWithObjects:@1,@2,@3,@4,@5,@6,@7,@8, nil];
NSArray *array2 = [NSArray arrayWithObjects:@4,@6, nil];
NSArray *temp = [array1 filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF in%@",array2]]; //表示获取 array2 和 array1中的交集

ANYSOME

检查 array1 中是否有任意一个元素出现在 array2 中:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY SELF in %@", array2];
BOOL hasCommonElement = [predicate evaluateWithObject:array1];
if (hasCommonElement) {
    NSLog(@"array1 中至少有一个元素出现在 array2 中");
} else {
    NSLog(@"array1 和 array2 没有交集");
}

在实际使用中,ANYSOME 是等价的,通常只使用 ANY

ALL

检查 array1 中的所有元素是否都出现在 array2 中:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ALL SELF in %@", array2];
BOOL allInArray2 = [predicate evaluateWithObject:array1];
if (allInArray2) {
    NSLog(@"array1 中的所有元素都出现在 array2 中");
} else {
    NSLog(@"array1 中至少有一个元素不在 array2 中");
}

NONE

检查 array1 中是否没有任何元素出现在 array2 中:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"NONE SELF in %@", array2];
BOOL noneInArray2 = [predicate evaluateWithObject:array1];
if (noneInArray2) {
    NSLog(@"array1 中没有任何元素出现在 array2 中");
} else {
    NSLog(@"array1 和 array2 有交集");
}

用于字典或者类当中

我们还可以使用谓词去筛选字典元素或者是类之中的属性。

NSArray *employees = @[
    @{@"name": @"啊", @"age": @25, @"department": @"HR"},
    @{@"name": @"哦", @"age": @35, @"department": @"IT"},
    @{@"name": @"额", @"age": @40, @"department": @"IT"}
];

// 创建 NSPredicate 对象
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age > 30 AND department == 'IT'"];

// 应用 NSPredicate 过滤数组
NSArray *filteredEmployees = [employees filteredArrayUsingPredicate:predicate];

// 处理过滤后的结果
for (NSDictionary *employee in filteredEmployees) {
    NSLog(@"Name: %@, Age: %@, Department: %@", employee[@"name"], employee[@"age"], employee[@"department"]);
}

在类之中使用,我们先创建一个Person类,里面包含name和age两个属性,我们重写description方法,以及写了一个初始化方法

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property NSString *name;
@property NSInteger age;

+ (id)personWithName:(NSString *)name andAge:(NSInteger)age;

@end

#import "Person.h"

@implementation Person

+ (id)personWithName:(NSString *)name andAge:(NSInteger)age{
    Person *person = [[Person alloc] init];
    person.name = name;
    person.age = age;
    return person;
}

- (NSString *)description{
    NSString *s =[NSString stringWithFormat:@"name = %@,age = %ld",_name,_age];
    return s;
}

@end

接下来创建一个由Person类组成的数组,进行创建谓词进行过滤

#import <Foundation/Foundation.h>
#import "Person.h"

//谓词,指定过滤器的条件,将符合条件的对象保留下来
//一般用谓词过滤数组中指定的元素
int main(int argc, const char * argv[]) {
    @autoreleasepool {
       
        NSArray *persons = [NSArray arrayWithObjects:
                            [Person personWithName:@"啊" andAge:20],
                            [Person personWithName:@"1" andAge:30],
                            [Person personWithName:@"2" andAge:40],
                            [Person personWithName:@"3" andAge:50],
                            [Person personWithName:@"4" andAge:60],
                            [Person personWithName:@"5" andAge:70],
                            [Person personWithName:@"6" andAge:20],
                            [Person personWithName:@"7" andAge:40],
                            [Person personWithName:@"8" andAge:60],
                            [Person personWithName:@"9" andAge:40],
                            [Person personWithName:@"0" andAge:80],
                            [Person personWithName:@"10" andAge:90],
                            [Person personWithName:@"1" andAge:20]];
        
        //年龄小于30
        //定义谓词对象,谓词对象中包含了过滤条件
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < %d",30];
        //使用谓词条件过滤数组中的元素,过滤之后返回查询的结果
        NSArray *array = [persons filteredArrayUsingPredicate:predicate];
        NSLog(@"filterArray = %@",array);
      
      
}

成功运行我们打印出一下结果

请添加图片描述

格式说明符(占位符)

谓词的表达式中,如果要动态修改条件,可以使用占位符来实现对谓词的拼接

在使用时,如果需要拼接属性名,其占位符为%K(注意大写)而不是%@,如:

NSString * key = @"age";
int age = 30;
//拼接示例:
[NSPredicate predicateWithFormat:@"%K < %d", key, age];

除此之外,在程序之中我们过滤条件一般来说也是根据需求进行动态变化的,所以

除此之外,还可以在谓词表达式中使用动态改变的属性值,就像环境变量一样

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < $AGE"];

上述表达式中,开头,随着程序改变$AGE这个谓词表达式的比较条件就可以,使用predicateWithSubstitutionVariables:动态改变。

接下来我们就可以学习一下,如何对这个较为重要的运算符进行使用

//用$AGE进行占位,可以动态修改$对应的值,这里的AGE可以是任意字符串
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age < $AGE"];

//修改AGE的值(AGE对应上面的$后的字符串),生成新的NSPredicate对象
NSPredicate *newPredicate = [predicate predicateWithSubstitutionVariables:@{@"AGE":@18}];

//使用newPredicate过滤数组
NSArray *array = [persons filteredArrayUsingPredicate: newPredicate];

实际运用

关于谓词的实际运用,我现在只是简单的对谓词进行了初步的使用,即使用正则表达式,即使用关键字MATCHES,进行格式的规范,当出现不符合格式的内容则弹出警告框,具体的限制代码如下

- (BOOL)validateName:(NSString *)name {
    NSString *pattern = @"^[\\p{Han}]{1,5}$";//限制只能为汉字
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", pattern];
    return [predicate evaluateWithObject:name];
}

- (BOOL)validateClass:(NSString *)className {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", @"^[\u4e00-\u9fa5]{2,3}[0-9]{4}$"];//限制只能为汉字2-3个加上4位数字
    return [predicate evaluateWithObject:className];
}

- (BOOL)validateGrade:(NSString *)grade {
    // 正则表达式,匹配只包含数字的字符串
    NSString *regex = @"^[0-9]+$";
    NSPredicate *regexPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
    
    BOOL isNumber = [regexPredicate evaluateWithObject:grade];
    
    if (isNumber) {
        // 如果是数字,检查其整数值是否小于200
        NSInteger value = [grade integerValue];
        return value < 200;
    }
    
    return NO;
}

总结

本篇文章作为在学生管理系统之中用谓词实现正则表达式限制文本框输入的延伸,其实一开始觉得这个正则表达式限制是一个比较小的点,深入了解才知道谓词这个我感觉比较重要的知识点,也没想到内容会有这么多,也希望以后可以使用谓词在其它方面可以帮助到我。在暑假剩下的时间还是得好好加油了!!!

参考文章

iOS中谓词(NSPredicate)的基本入门使用教程

iOS NDPredicate与数组过滤

【OC梳理】NSPredicate

OC学习篇之—谓词(NSPredicate)

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

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

相关文章

05创建型设计模式——原型模式

一、原型模式简介 原型模式&#xff08;Prototype Pattern&#xff09;模式是一种对象创建型模式&#xff0c;它采取复制原型对象的方法来创建对象的实例。使用原型模式创建的实例&#xff0c;具有与原型一样的数据。 1&#xff09;由原型对象自身创建目标对象。换句话说&…

python基础语法 010 类和对象-3 方法

1.3 方法 属性表示是一个类当中的成员或类的特征&#xff0c;而方法是&#xff1f;&#xff1f; 方法&#xff1a;表示类、对象的行为&#xff0c;方法本质上是函数&#xff0c;是一个特殊的函数 属性名称一般为名词&#xff0c;方法名称一般为动词 1.3.1 方法 VS 属性 1、…

24/8/17算法笔记 DDPG算法

深度确定性策略梯度&#xff08;DDPG&#xff09;算法是一种用于解决连续动作空间强化学习问题的算法。它结合了确定性策略梯度&#xff08;DPG&#xff09;和深度学习技术的优点&#xff0c;通过Actor-Critic框架进行策略和价值函数的近似表示。DDPG算法的关键组成部分包括经验…

【RAG综述】北京大学检索增强技术综述

RAG for AIGC ​ 图 1 描述了一个典型的 RAG 过程。给定一个输入查询&#xff0c;检索器识别相关的数据源&#xff0c;检索到的信息与生成器交互以改进生成过程。根据检索结果如何增强生成&#xff0c;有几种基础范式&#xff08;简称基础&#xff09;&#xff1a;它们可以作为…

STM32的蜂鸣器

蜂鸣器分为有源蜂鸣器和无源蜂鸣器。 有源蜂鸣器&#xff1a;内部有震荡源&#xff0c;只要通电即可自动发出固定频率的声音。&#xff08;频率固定无 法控制音色&#xff09; 。 无源蜂鸣器&#xff1a;内部无震荡源&#xff0c;需要外部脉冲信号驱动发声&#xff0c;声音频…

《机器学习》 线性回归 一元、多元 推导 No.3

一、什么是线性回归 线性回归是一种用于预测连续数值的机器学习算法。它基于输入特征与目标变量之间的线性关系建立了一个线性模型。线性回归的目标是找到最佳拟合直线&#xff0c;以最小化预测值与实际值之间的误差。这个线性模型可以用来进行预测和推断。 线性回归的模型可以…

SpringBoot Profile多环境配置及配置优先级

【SpringBoot学习笔记 三】Profile多环境配置及配置优先级_profiles队列中的优先值-CSDN博客 Profile激活方式 但是我们发现一个问题&#xff0c;就是每次切换环境还需要去配置里指定&#xff0c;然后通过修改dev为test或prod来切换项目环境 , 这样做的话每次切换环境都要重新改…

前端面试——如何判断对象和数组

给你一个值&#xff0c;如何判断其是对象还是数组&#xff1f;&#xff1f;&#xff1f; 我们先给出数据 var lists [1,2,3,4,5]var objs {length:5 } 我们分别尝试如下五种方法 console.log((✘)使用length,lists.length,objs.length); console.log((✔)使用isArray,Arr…

【已成功EI检索】第三届机电一体化技术与航空航天工程国际学术会议(ICMTAE 2023)

重要信息 大会官网&#xff1a;www.icmtae.org 大会时间&#xff1a;2023年9月15-17日 大会地点&#xff1a;中国-江西南昌理工学院&#xff08;南昌市青山湖区经济技术开发区英雄大道901号&#xff09; 接受/拒稿通知&#xff1a;投稿后1周内 收录检索&#xff1a;EI 和 …

Vulkan 学习(4)---- Vulkan 逻辑设备

目录 Vulkan Logical Device OverView逻辑设备创建VkDeviceQueueCreateInfoDeviceExtension获取DeviceQueue参考代码 Vulkan Logical Device OverView 在 Vulkan 中&#xff0c;逻辑设备(Logical Device)是与物理设备(Physical Device)交互的接口,它抽象了对特定GPU(物理设备)…

CDD数据库文件制作(八)——服务配置(0x85)

目录 1.子功能创建2.会话切换配置/安全等级配置2.1.根据诊断调查表进行信息提取2.2.会话转换配置/安全等级配置3.寻址方式信息提取/禁止肯定响应位(SPRMIB)信息3.1.寻址方式/禁止肯定响应位(SPRMIB)配置4.否定响应码信息提取4.1.否定响应码配置按照诊断调查表中对0x85服务的…

PX30 Android8.1适配AIC8800 wifi

wifi驱动生成ko文件 生成后 通过wpa_supplicant加载参数 external/wpa_supplicant_8/wpa_supplicant/main.c int main(int argc, char *argv[]) {int ret -1;char module_type[20]{0};wpa_printf(MSG_INFO,"argc %d\n",argc);if(argc 2) {if (wifi_type[0] 0) …

【MySQL】数据库基础(表的操作)

目录 一、创建表 二、查看表结构 三、修改表 3.1 添加新列 3.2 修改列属性 3.3 删除列属性 3.4 修改表名 3.5 向表中插入 3.6 修改列名 四、删除表 一、创建表 语法&#xff1a; CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) …

docker容器安全加固参考建议——筑梦之路

这里主要是rootless的方案。 在以 root 用户身份运行 Docker 会带来一些潜在的危害和安全风险&#xff0c;这些风险包括&#xff1a; 容器逃逸&#xff1a;如果一个容器以 root 权限运行&#xff0c;并且它包含了漏洞或者被攻击者滥用&#xff0c;那么攻击者可能会成功逃出容器…

车载camera avm框图

一、关键词介绍: POC: power on coax LVDS: Low-Voltage Differential Signaling GMSL:Gigabit Multimedia Serial Link AVM: Around View Monitor Serdes:DeSerializer、Serializer DVP:Interface with ISP and Sensor: DVP(Digital Video Port) 二、车载camera avm…

书籍推荐:大数据之路 阿里巴巴大数据实践

书籍推荐&#xff1a;大数据之路 阿里巴巴大数据实践 这本书侧重于理论知识&#xff0c;并结合了阿里大数据发展的过程&#xff0c;将知识总结起来。总的来所&#xff0c;书中的有些章节个人感觉非常不错&#xff0c;比如&#xff1a;数据仓库建模&#xff1b;但是大部分章节都…

性能优化理论篇 | 如何保证数据安全落盘,5分钟彻底弄懂 一次write中的各种缓冲区 !

性能优化系列目录&#xff1a; 性能优化理论篇 | 彻底弄懂系统平均负载 性能优化理论篇 | swap area是个什么东西 性能优化理论篇 | Cache VS Buffer&#xff0c;傻傻分不清 &#xff1f; 在很多IO场景中&#xff0c;我们经常需要确保数据已经安全的写到磁盘上&#xff0c;以便…

xss之DOM破坏

文章目录 DOM破坏漏洞的复现https://xss.pwnfunction.com/基于bp学院DOM破坏漏洞复现思路分析实现 常见的xss触发的标签没有过滤的情况存在过滤的情况 DOM破坏 DOM破坏就是⼀种将 HTML 代码注⼊⻚⾯中以操纵 DOM 并最终更改⻚⾯上 JavaScript ⾏为的技术。 在⽆法直接 XSS的情…

Linux·权限与工具-make

1. Makefile/makefile工具 首先展示一下&#xff0c;makefile工具如何使用。我们先写一个C语言程序 然后我们建立一个Makefile/makefile文件&#xff0c;m大小写均可。我们在文件中写入这样两行 wq保存退出后&#xff0c;我们使用 make 命令 可以看到生成了可执行程序&#xff…

无人机模拟训练室技术详解

无人机模拟训练室作为现代无人机技术培训的重要组成部分&#xff0c;集成了高精度模拟技术、先进的数据处理能力及高度交互的操作界面&#xff0c;为无人机操作员提供了一个安全、高效、接近实战的训练环境。以下是对无人机模拟训练室技术的详细解析&#xff0c;涵盖系统基础概…