33、深入探索 NSPredicate 与不同语言过渡到 Objective - C 的要点

深入探索 NSPredicate 与不同语言过渡到 Objective - C 的要点

1. NSPredicate 基础与数组交集操作

NSPredicate 是一个强大的工具,可用于过滤对象。例如,我们可以通过以下代码来过滤数组:

NSArray *names = ...; // 假设这里有一个 names 数组
NSPredicate *predicate = ...; // 定义一个谓词
NSArray *results = [names filteredArrayUsingPredicate: predicate];

下面通过一个具体的例子来展示如何求两个数组的交集:

NSArray *names1 = [NSArray arrayWithObjects:
 @"Herbie", @"Badger", @"Judge", @"Elvis", nil];
NSArray *names2 = [NSArray arrayWithObjects:
 @"Judge", @"Paper Car", @"Badger", @"Phoenix", nil];
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"SELF IN %@", names1];
NSArray *results = [names2 filteredArrayUsingPredicate: predicate];
NSLog (@"%@", results);

输出结果为:

(
  Judge,
  Badger
)

其工作原理是,谓词包含了第一个数组的内容,类似于 SELF IN {"Herbie", "Badger", "Judge", "Elvis"} 。第二个数组会根据这个谓词进行过滤,只有同时存在于两个数组中的字符串才会出现在结果数组中。

2. 字符串操作相关的谓词

除了基本的数组过滤,NSPredicate 还提供了一些字符串特定的操作符,如下表所示:
| 操作符 | 含义 |
| ---- | ---- |
| BEGINSWITH | 检查一个字符串是否以另一个字符串开头 |
| ENDSWITH | 检查一个字符串是否以另一个字符串结尾 |
| CONTAINS | 检查一个字符串是否包含另一个字符串 |

例如:
- "name BEGINSWITH 'Bad'" 可以匹配 “Badger”。
- "name ENDSWITH 'vis'" 可以匹配 “Elvis”。
- "name CONTAINS udg" 可以匹配 “Judge”。

不过,这些匹配是区分大小写和重音符号的。例如, "name BEGINSWITH 'HERB'" 不会匹配 “Herbie”, "name BEGINSWITH 'Hérb'" 也不会匹配。为了放宽匹配规则,可以使用 [c] (不区分大小写)、 [d] (不区分重音符号)或 [cd] (两者都不区分)。例如, "name BEGINSWITH[cd] 'HERB'" 可以匹配 “Herbie”。

3. LIKE 操作符与正则表达式

有时候,上述的字符串匹配操作不够强大,这时可以使用 LIKE 操作符。在 LIKE 操作符中, ? 匹配一个字符, * 匹配任意数量的字符。例如:
- "name LIKE '*er*'" 可以匹配任何中间包含 “er” 的名字,等同于 CONTAINS
- "name LIKE '???er*'" 可以匹配 “Paper Car”,但不能匹配 “Badger”。

此外,如果需要更强大的字符串匹配能力,可以使用 MATCHES 操作符,它接受一个正则表达式。不过,正则表达式虽然强大,但计算成本较高。如果谓词中有更简单的操作,如基本的字符串操作符和比较操作符,建议先执行这些操作,再使用 MATCHES ,这样可以提高性能。

4. 从其他语言过渡到 Objective - C

许多程序员从其他语言转向 Objective - C 和 Cocoa 时会遇到困难,因为它的行为与其他流行语言不同。以下是从不同语言过渡到 Objective - C 的要点:

4.1 从 C 语言过渡

Objective - C 是在 C 语言的基础上增加了一些面向对象的特性。Objective - C 程序员可以使用 C 语言的标准库,如 malloc() free() 处理动态内存, fopen() fgets() 处理文件。

当调用使用回调的 ANSI C 库时,不能直接让其调用 Objective - C 方法,因为回调要求的 C 函数签名与实现 Objective - C 方法的函数签名不同。不过,大多数回调库允许提供用户数据或指针。可以使用 Objective - C 对象的地址作为上下文指针,在回调函数中,将上下文指针转换为对象类型并发送消息。

以下是一个示例:

// 创建一个 TreeWalker 对象
TreeWalker *walker = [[TreeWalker alloc] init];
// 创建 XML 解析器
XMLParser parser;
parser = XMLParserLoadFile ("/tmp/badgers.xml");
// 设置解析器的回调函数,并使用 TreeWalker 对象作为上下文
XMLSetParserCallback (parser, elementCallback, walker);

回调函数如下:

void elementCallback (XMLParser *parser, XMLElement *element, userData *context)
{
  TreeWalker *walker = (TreeWalker *) context;
  [walker handleNewElement: element inParser: parser];
}
4.2 从 C++ 语言过渡

C++ 有很多 Objective - C 缺乏的特性,如多重继承、命名空间、操作符重载、模板、类变量、抽象类和标准模板库等。不过,Objective - C 有一些特性和技术可以替代或模拟这些特性。

例如,可以使用类别(categories)和协议(protocols)来实现类似多重继承或抽象基类的功能。但如果使用多重继承是为了引入额外的实例变量,可以使用组合(composition)和存根方法(stub methods),也可以通过重写 forwardInvocation: 方法来模拟多重继承。

C++ 和 Objective - C 在方法调度机制上也有很大差异。C++ 使用基于虚函数表(vtable)的机制来确定调用的代码,这种方式速度快且安全,但缺乏灵活性。而 Objective - C 使用运行时函数在类结构中查找要调用的代码,速度较慢,但更灵活。

在 Objective - C 中,对象只需要有方法实现就可以被调用,这使得任意对象都可以成为其他对象的数据源或委托。不过,这种灵活性也使得 Objective - C 的类型安全性不如 C++。

Objective - C 没有类变量,可以使用文件作用域的全局变量和访问器来模拟。例如:

@interface Blarg : NSObject
{
}
+ (int) classVar;
+ (void) setClassVar: (int) cv;
@end

#import "Blarg.h"
static int g_cvar;
@implementation Blarg
+ (int) classVar
{
  return (g_cvar);
}
+ (void) setClassVar: (int) cv
{
  g_cvar = cv;
}
@end
5. Objective - C++

Xcode 中的 Clang 编译器支持一种混合语言 Objective - C++,它允许自由混合 C++ 和 Objective - C 代码,但有一些小的限制。通过使用 .mm 文件扩展名,编译器会将代码视为 Objective - C++。

常见的开发场景是将应用的核心逻辑放在可移植的 C++ 库中,将用户界面用平台的原生工具包编写。Objective - C++ 为这种开发方式提供了很大的便利,既可以获得 C++ 的性能和类型安全性,又可以使用 Objective - C 的动态特性和 Cocoa 工具包。

需要注意的是,Objective - C 和 C++ 的对象层次结构不能混合,不能让 C++ 类继承自 NSView,也不能让 Objective - C 类继承自 std::string

综上所述,无论是使用 NSPredicate 进行对象过滤,还是从其他语言过渡到 Objective - C,都需要理解其特性和机制,根据具体需求选择合适的方法和技术。

深入探索 NSPredicate 与不同语言过渡到 Objective - C 的要点

6. 不同语言过渡的总结与对比

从前面的内容可以看出,从 C 和 C++ 过渡到 Objective - C 各有特点,下面通过表格进行总结对比:
| 对比项 | 从 C 过渡 | 从 C++ 过渡 |
| ---- | ---- | ---- |
| 语言基础 | 在 C 基础上增加面向对象特性,可使用 C 标准库 | 缺乏 C++ 部分特性,但有替代方案 |
| 回调机制 | 不能直接用 Objective - C 方法作回调,可利用对象地址作上下文指针 | 无此方面问题,但方法调度机制不同 |
| 多重继承 | 不涉及此问题 | 可用类别、协议、组合、重写方法模拟 |
| 类型安全性 | 与 C 类似,需注意指针操作等 | 相比 C++ 类型安全性较低 |
| 类变量 | 不涉及,C 一般用全局变量 | 用文件作用域全局变量和访问器模拟 |

通过这个表格,我们可以更清晰地看到不同语言过渡到 Objective - C 时的差异,有助于开发者根据自己的编程背景更好地适应 Objective - C。

7. NSPredicate 操作的流程梳理

为了更好地理解 NSPredicate 的使用,下面用 mermaid 流程图展示其基本操作流程:

graph TD
    A[定义数组] --> B[定义谓词]
    B --> C[使用谓词过滤数组]
    C --> D[获取过滤结果]
    D --> E{结果判断}
    E -- 有结果 --> F[处理结果]
    E -- 无结果 --> G[结束操作]

这个流程图展示了使用 NSPredicate 过滤数组的基本步骤:
1. 首先定义要过滤的数组。
2. 接着定义一个合适的谓词,根据不同的需求选择不同的操作符,如 BEGINSWITH LIKE 等。
3. 使用定义好的谓词对数组进行过滤。
4. 获取过滤后的结果。
5. 判断结果是否存在,如果有结果则进行相应的处理,如果没有结果则结束操作。

8. 关于 Objective - C 特性的深入理解

Objective - C 有一些独特的特性,在实际使用中需要深入理解。

8.1 消息发送与 nil 对象

在 Objective - C 中,可以向 nil 对象发送消息,这是一个很特别的特性。消息发送给 nil 对象时,操作会被忽略,返回值根据方法的返回类型有所不同:
- 如果方法返回指针类型(如对象指针),返回值为 nil,可以安全地链式调用。
- 如果方法返回与指针大小相同或更小的 int 类型,返回值为 0。
- 如果方法返回 float 或结构体类型,结果未定义。

这种特性可以避免每次发送消息前都检查对象是否为 NULL,但也可能掩盖错误,导致难以追踪的 bug。例如:

SomeClass *obj = nil;
id result = [obj someMethod]; // result 为 nil
8.2 类的继承与方法重写

Objective - C 中,创建新类时通常会继承自 NSObject 或现有 Cocoa 类,与 C++ 多个独立根的对象层次结构不同。而且在 Objective - C 中,重写方法不需要重新声明或标记为虚拟,任何方法都可以在子类或类别中重写。这有两种不同的观点:
- 一种认为重新声明可以让读者了解类对父类的修改。
- 另一种认为这只是实现细节,类的使用者无需关注,且避免了新方法重写时所有依赖类的重新编译。

9. 实战案例分析

下面通过一个简单的实战案例来综合运用前面提到的知识。假设我们有一个存储联系人姓名的数组,需要过滤出以 “John” 开头的姓名,并且不区分大小写。

// 定义联系人姓名数组
NSArray *contacts = [NSArray arrayWithObjects: @"John Smith", @"Jane Doe", @"Johnny Walker", @"Sam Johnson", nil];
// 定义谓词
NSPredicate *predicate = [NSPredicate predicateWithFormat: @"SELF BEGINSWITH[cd] 'John'"];
// 过滤数组
NSArray *filteredContacts = [contacts filteredArrayUsingPredicate: predicate];
// 输出过滤结果
NSLog (@"%@", filteredContacts);

在这个案例中,我们首先定义了一个联系人姓名数组,然后使用 BEGINSWITH[cd] 谓词来过滤出以 “John” 开头且不区分大小写的姓名,最后输出过滤结果。

10. 总结与展望

通过对 NSPredicate 的学习,我们了解到它是一个强大的对象过滤工具,利用不同的操作符可以实现各种复杂的过滤需求。在从其他语言过渡到 Objective - C 时,需要理解其独特的特性和机制,如回调处理、多重继承模拟、方法调度等。

对于开发者来说,掌握 Objective - C 的这些知识可以更好地进行 iOS 和 OS X 编程。同时,Objective - C++ 的出现为开发提供了更多的选择,可以结合 C++ 的性能和 Objective - C 的动态特性。未来,随着技术的发展,我们可以期待 Objective - C 在更多领域发挥作用,并且与其他语言的融合会更加深入。

在实际开发中,开发者应不断实践,根据具体项目需求灵活运用这些知识和技术,提高开发效率和代码质量。

内容概要:本文围绕新一代传感器产品在汽车电子电气架构中的关键作用展开分析,重点探讨了智能汽车向高阶智能化演进背景下,传统传感器无法满足感知需求的问题。文章系统阐述了自动驾驶、智能座舱、电动化网联化三大趋势对传感器技术提出的更高要求,并深入剖析了激光雷达、4D毫米波雷达和3D-ToF摄像头三类核心新型传感器的技术原理、性能优势现存短板。激光雷达凭借高精度三维点云成为高阶智驾的“眼睛”,4D毫米波雷达通过增加高度维度提升环境感知能力,3D-ToF摄像头则在智能座舱中实现人体姿态识别交互功能。文章还指出传感器正从单一数据采集向智能决策升级,强调车规级可靠性、多模态融合成本控制是未来发展方向。; 适合人群:从事汽车电子、智能驾驶、传感器研发等相关领域的工程师和技术管理人员,具备一定专业背景的研发人员;; 使用场景及目标:①理解新一代传感器在智能汽车系统中的定位技术差异;②掌握激光雷达、4D毫米波雷达、3D-ToF摄像头的核心参数、应用场景及选型依据;③为智能驾驶感知层设计、多传感器融合方案提供理论支持技术参考; 阅读建议:建议结合实际项目需求对比各类传感器性能指标,关注其在复杂工况下的鲁棒性表现,并重视传感器整车系统的集成适配问题,同时跟踪芯片化、固态化等技术演进趋势。
内容概要:本文系统阐述了汽车电子软件测试的整体框架,重点围绕软件及系统集成测试、软件系统(需求)测试、验收测试、测试报告编写以及整体测试状态汇总五大核心环节展开。详细说明了软件集成测试系统集成测试在组件聚合、软硬协同、接口验证等方面的实施策略技术差异,明确了软件测试偏重逻辑正确性(白盒)、系统测试关注端到端行为表现(黑盒)的定位区分,并强调验收测试正从工程交付关口转变为用户价值验证的核心环节。同时,文章指出测试报告需建立需求用例间的可追溯链,整体测试状态汇总则是呈现软件质量全景的“仪表盘”,对于多域协同的复杂汽车系统至关重要。; 适合人群:从事汽车电子、嵌入式系统开发测试的工程师,尤其是工作1-3年、希望深入理解软件测试体系流程的中初级技术人员;也适用于项目管理人员和技术负责人; 使用场景及目标:①理解汽车软件测试各阶段的边界、职责协作关系;②掌握集成测试中软/硬件接口验证的方法论;③构建从技术测试到用户价值验证的全局视角,提升测试策略设计能力; 阅读建议:此资源以工程实践为基础,结合ASPICE等标准演进,不仅讲解测试技术细节,更强调测试管理用户思维的融合,建议结合实际项目流程对照学习,并关注各测试层级之间的衔接追溯机制。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值