iOS生态系统
iOS生态系统层次架构
- 硬件层:
- 设备:iPhone、iPad、iPod Touch 等苹果设备。这些设备采用苹果设计的芯片,如 A 系列处理器,基于 ARM 架构。硬件设计与软件优化紧密结合,确保性能和能效的平衡。
- 核心操作系统层(Core OS Layer):
- 内核:iOS 基于 Darwin 内核,融合了来自 Mach 和 BSD 的技术。内核负责内存管理、进程调度、文件系统和网络堆栈等底层服务。
- 驱动程序:管理硬件设备的驱动程序,提供对硬件的抽象和控制。
- 安全性:提供关键的安全功能,如沙盒机制、代码签名和权限管理,确保系统的安全性和稳定性。
- 核心服务层(Core Services Layer):
- 基础框架(Foundation Framework):提供集合、字符串处理、日期和时间、文件管理等基础数据管理功能。
- 核心位置服务(Core Location):提供定位服务,支持 GPS 和 Wi-Fi 定位。
- 网络服务(CFNetwork):提供对网络协议的支持,如 HTTP、FTP 和 SSL。
- SQLite:嵌入式关系数据库,供应用程序存储结构化数据。
- 媒体层(Media Layer):
- 图形:
- Quartz Core(Core Graphics):2D 绘图引擎,支持矢量绘图和图像处理。
- OpenGL ES / Metal:提供高性能的 3D 图形渲染接口。
- 音频:
- Core Audio:提供低延迟、高品质的音频处理能力。
- OpenAL:用于 3D 音频渲染的跨平台音频 API。
- 视频:
- AVFoundation:提供音视频的捕捉、编辑和播放功能。
- 图形:
- 可触摸层(Cocoa Touch Layer):
- UIKit:提供构建用户界面的核心框架,包括按钮、表格、手势识别等。
- 多点触控支持:处理复杂的触摸事件和手势。
- 推送通知:支持远程和本地通知功能。
- 视图控制器:管理应用程序的视图层次和导航。
关于Dwarwin内核
Darwin 是苹果公司于 2000 年发布的开源操作系统,作为 macOS 和 iOS 的基础。其内核名为 XNU("X is Not Unix" 的递归缩写),是一个混合内核,结合了 Mach 微内核和 BSD 子系统的特性。
Mach 和 BSD 技术:
- Mach:由卡内基梅隆大学开发的微内核,旨在提供简洁的内核设计,支持多任务、虚拟内存和跨平台能力。在 XNU 中,Mach 负责进程间通信(IPC)、线程管理和虚拟内存管理。
- BSD:Berkeley Software Distribution,是 UNIX 的一个分支,提供了丰富的操作系统功能,如文件系统、网络协议栈和用户空间工具。在 XNU 中,BSD 子系统提供了 POSIX 接口、网络堆栈和文件系统支持。
Darwin 内核与 Linux 内核的关系: Darwin 和 Linux 都是类 UNIX 操作系统,但它们在设计和实现上有显著差异:
- 内核架构:Linux 采用单体内核架构,将所有核心功能集成在一个大内核中。而 XNU 是混合内核,结合了 Mach 微内核的模块化设计和 BSD 的传统内核特性。
- 起源和发展:Linux 由 Linus Torvalds 于 1991 年开始开发,完全从零编写,遵循 GPL 许可证。Darwin 则由苹果公司基于 Mach 和 BSD 技术开发,遵循 APSL(Apple Public Source License)。
- 硬件支持:Linux 支持多种硬件架构,具有广泛的硬件兼容性。Darwin 主要针对苹果自家硬件进行优化,硬件支持相对有限。
iOS 与 Android 的主要区别
硬件与操作系统:Android 操作系统运行在多种硬件设备上,由不同的制造商生产,导致硬件多样性和碎片化。iOS 仅运行在苹果自家设备上,硬件和软件高度集成,确保一致的用户体验。
- 系统开放性:Android 基于 Linux 内核,采用开放性设计,允许应用获取更多的系统权限和资源。iOS 基于 Darwin 内核, 采用封闭性设计,应用只能在受限的沙盒环境中运行,系统权限控制严格。
- 内存管理:Android 使用垃圾回收机制(GC)进行内存管理,而 iOS 采用自动引用计数(ARC)机制,开发者需要对对象的生命周期进行更精细的管理。
- 应用架构:Android 应用主要使用 Java 或 Kotlin 编写,UI 采用 XML 布局。iOS 应用主要使用 Objective-C 或 Swift 编写,UI 通过 Storyboard 或代码进行布局,提供 UIKit 等框架。
- 应用分发:Android 应用可以通过多个渠道分发,如 Google Play 和第三方应用商店。iOS 应用只能通过苹果的 App Store 分发,经过严格的审核流程。
开发环境与语言
-
Xcode:Xcode 是苹果官方的集成开发环境,提供了用于构建、调试和部署 iOS 应用的工具。它包含了构建 iOS 游戏所需的 SDK。
-
Objective-C 或 Swift:对于 iOS 的原生开发,Objective-C 和 Swift 是主要语言。虽然大部分游戏逻辑会使用 C# 和 Unity,但是在需要集成 iOS 原生功能(如崩溃监听、推送通知、支付等)时,必须使用 Objective-C 或 Swift 来与 Unity 进行交互。
CocoaPods / Carthage / SwiftPM(依赖管理)
- CocoaPods:Unity 导出的 iOS 项目通常会使用 CocoaPods 来集成第三方 iOS 库,比如崩溃监控、广告 SDK、分析等。
- Carthage / SwiftPM:有时也会使用这些工具来管理 iOS 原生库。
iOS开发相关语言环境
Objective-C 和 Swift 语言介绍
1. Objective-C 语言
Objective-C 是苹果在 1980 年代引入的一种面向对象的编程语言,基于 C 语言并扩展了 Smalltalk 风格的面向对象特性。它曾经是 iOS 和 macOS 开发的主力语言,直到 Swift 的出现。
-
类型:面向对象语言,基于 C 语言。
- Objective-C 是 C 的超集,意味着任何有效的 C 程序也是有效的 Objective-C 程序。它支持面向对象编程 (OOP) 的特性,例如类、继承、封装和多态。
- 消息发送机制:与许多面向对象语言不同,Objective-C 使用的是 消息传递 机制来调用方法,而不是直接的函数调用。这种机制在运行时进行动态绑定,这使得 Objective-C 具有非常强的灵活性和扩展性。
-
底层:Objective-C 运行时(Objective-C Runtime)负责动态方法解析、内存管理(ARC)、消息传递等核心功能。它为动态方法调用提供支持,这也是与其他语言不同的关键特点。
-
与 iOS Native 层的关系:
- Objective-C 是 iOS 的原生开发语言,Xcode 和 iOS SDK 提供了丰富的框架和 API,开发者通过 Objective-C 来调用底层系统功能,如推送通知、GPS、蓝牙等硬件接口。
- 调用底层 API:使用 Objective-C 编写的代码可以直接访问 iOS 系统底层的 Cocoa/Cocoa Touch 框架,例如 UIKit、Foundation、CoreData 等。
-
与 Swift 的互相调用:
- 与 Swift 的互操作性:从 Swift 2 开始,Apple 提供了良好的互操作性支持,可以让 Swift 与 Objective-C 代码无缝协作。可以在 Swift 中调用 Objective-C 的类、方法和属性,反之也可以在 Objective-C 中调用 Swift 类。
- 桥接文件(Bridging Header):如果项目中同时使用 Objective-C 和 Swift,开发者需要通过一个称为 Bridging Header 的桥接文件来实现两者之间的互操作。
2. Swift 语言
Swift 是苹果在 2014 年推出的现代化编程语言,旨在提供一种更安全、更高效、更简洁的开发体验。Swift 的出现逐步取代了 Objective-C,在 iOS 和 macOS 的应用开发中成为主流。
- 类型:编译型语言,现代化的面向对象和函数式编程语言。
- Swift 结合了面向对象编程(OOP)和函数式编程(FP)的特性。它不再使用动态消息传递,而是采用直接的函数调用和编译时类型检查,这提高了运行时效率和代码安全性。
- Swift 提供了更强的类型系统,编译器能够在编译时检测到更多的潜在问题,比如空指针引用和类型错误。
- 底层:Swift 语言编译后的代码运行在 LLVM(Low-Level Virtual Machine)框架之上,LLVM 是一个优化的编译工具链,帮助 Swift 生成高效的机器代码。
- Swift 在运行时依赖 Cocoa 和 Cocoa Touch 框架,与 Objective-C 一样可以直接访问这些底层的系统库。
- Swift 本身是基于 LLVM 和 Clang 编译器的,支持与 C 和 C++ 代码的互操作性。
- 与 iOS Native 层的关系:
- Swift 完全可以与 iOS 的原生 API(如 UIKit、Foundation)交互,并能高效地调用系统底层功能。
- Swift 提供了一些现代化的特性,如 自动内存管理(ARC)、类型安全、内存安全 等,这些特性使得开发者编写的代码更加简洁、安全和高效。
- 与 Objective-C 的互相调用:
- Swift 和 Objective-C 可以无缝互操作。你可以在 Swift 中调用 Objective-C 的类、方法和属性,反之亦然。
- Swift 和 Objective-C 之间的互相调用通过桥接文件(Bridging Header)和 Objective-C 兼容性 类来实现。
- Objective-C 兼容性:Swift 可以通过
@objc修饰符将 Swift 类和方法暴露给 Objective-C,这样 Objective-C 可以调用这些 Swift 代码。同样,Swift 类也可以通过@objc标记它们的方法,以便在动态运行时进行调用。
Objective-C 和 Swift 与 Native 层的关系及互相调用方案
1. 与 Native 层的关系
- Native 层 通常指的是 iOS 操作系统提供的原生 API 层,包括系统底层的硬件交互、UI 框架、网络库、数据库框架等。在 iOS 开发中,Objective-C 和 Swift 是主要的编程语言,它们与 Native 层直接交互,调用底层系统功能。
- iOS SDK:无论是使用 Objective-C 还是 Swift,开发者都会通过 iOS SDK 提供的框架和 API 来实现各种功能,例如访问设备硬件、处理网络请求、进行 UI 渲染等。这些 API 是通过 Objective-C 或 Swift 语言的语法来调用的。
2. 与 Unity 的交互方案
在 Unity 项目中,如果你需要调用 iOS 特定的功能(例如崩溃上报、推送通知等),你通常会通过 原生插件 的方式,将 Objective-C 或 Swift 编写的代码集成到 Unity 中。两者之间的互相调用流程如下:
- Unity 调用 Objective-C/Swift 方法:
- 通过 Unity 提供的
UnitySendMessage函数,Unity 可以向 Objective-C/Swift 代码发送消息,从而调用对应的 iOS 原生功能。例如,在 Unity 中调用一个原生支付功能,或者监听崩溃日志等。 - 通过 P/Invoke 或 Unity iOS Plugin 接口,Unity 可以直接与 Objective-C/Swift 代码进行交互。
- 通过 Unity 提供的
- Objective-C/Swift 调用 Unity:
- 反过来,Objective-C/Swift 代码也可以调用 Unity 的方法。例如,原生的推送通知到来时,可以通过 Objective-C/Swift 的代码通知 Unity 层,执行相应的游戏内操作。
- 在 Xcode 中,Unity 会生成一个包装器代码,允许 Objective-C/Swift 代码调用 Unity 的 API,执行例如加载场景、播放动画等操作。
3. 使用桥接(Bridging)技术
- 桥接文件(Bridging Header):如果你在项目中同时使用 Swift 和 Objective-C,必须创建一个桥接文件(
<ProjectName>-Bridging-Header.h),这个文件允许你在 Swift 中直接引用 Objective-C 代码。例如:
// Bridging Header 中引用 Objective-C 类
#import "MyObjectiveCClass.h"
- Objective-C 与 Swift 互操作:
- Swift 代码可以通过
@objc修饰符暴露给 Objective-C 使用,反之,Objective-C 代码可以通过桥接文件暴露给 Swift 使用。 - 在 Objective-C 中,通过
#import来引入 Swift 代码对应的头文件。
- Swift 代码可以通过
iOS平台库类型
静态库(Static Library)
- 文件扩展名:
.a - 特点: 在编译时被直接链接到可执行文件中,应用程序运行时不需要依赖外部的库文件。
构建方法:
- 创建静态库项目: 在 Xcode 中,选择 "Cocoa Touch Static Library" 模板创建项目。
- 编写代码: 添加需要封装的代码和头文件。
- 编译: 选择目标设备(模拟器或真机),编译生成对应架构的静态库。
- 合并架构: 使用
lipo工具将不同架构的静态库合并为一个通用的静态库。
动态库(Dynamic Library)
- 文件扩展名:
.dylib - 特点: 在应用程序运行时动态加载,多个应用可以共享同一个动态库。然而,出于安全和稳定性的考虑,iOS 对第三方动态库的使用有严格限制。
构建方法:
- 创建动态库项目: 在 Xcode 中,选择 "Cocoa Touch Framework" 模板创建项目。
- 配置项目: 在项目的 "Build Settings" 中,将 "Mach-O Type" 设置为 "Dynamic Library"。
- 编写代码: 添加需要封装的代码、头文件和资源文件。
- 编译: 选择目标设备,编译生成对应架构的动态库。
- 合并架构: 同样使用
lipo工具将不同架构的动态库合并。
框架(Framework)
- 文件扩展名:
.framework - 特点: Framework 是一种特殊的目录结构,包含了动态或静态库、头文件、资源文件(如图片、xib 文件等)以及相关的元数据。它提供了一种组织和分发代码的方式,便于模块化和代码重用。
构建方法:
- 创建框架项目: 在 Xcode 中,选择 "Cocoa Touch Framework" 模板创建项目。
- 编写代码: 添加需要封装的代码、头文件和资源文件。
- 配置项目: 根据需要设置 "Mach-O Type" 为 "Static Library" 或 "Dynamic Library"。
- 编译: 选择目标设备,编译生成对应架构的框架。
- 合并架构: 使用
lipo工具将不同架构的框架合并为一个通用的框架。
Objective-C与C++互相调用
在 iOS 开发中,Objective-C 和 C++ 可以通过 Objective-C++ 进行互相调用。Objective-C++ 是一种将 Objective-C 和 C++ 语法融合的语言,允许在同一源文件中同时使用这两种语言的特性。
- 文件扩展名: 将需要混合使用 Objective-C 和 C++ 代码的源文件扩展名命名为
.mm,表示该文件将作为 Objective-C++ 文件进行编译。 - 代码混合: 在
.mm文件中,可以直接使用 C++ 类和对象,以及调用 C++ 函数。同时,也可以在 C++ 代码中创建和使用 Objective-C 对象。
CppClass.hpp(C++ 头文件)
#ifndef CPPCLASS_HPP
#define CPPCLASS_HPP
#include <iostream>
class CppClass {
public:
void cppMethod() {
std::cout << "C++ Method Called" << std::endl;
}
};
#endif // CPPCLASS_HPP
ObjCClass.h(Objective-C 头文件)
#import <Foundation/Foundation.h>
@interface ObjCClass : NSObject
- (void)objcMethod;
@end
ObjCClass.m(Objective-C 实现文件)
#import "ObjCClass.h"
@implementation ObjCClass
- (void)objcMethod {
NSLog(@"Objective-C Method Called");
}
@end
Main.mm(Objective-C++ 文件)
#import <Foundation/Foundation.h>
#import "ObjCClass.h"
#import "CppClass.hpp"
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 创建并使用 Objective-C 对象
ObjCClass *objcObject = [[ObjCClass alloc] init];
[objcObject objcMethod];
// 创建并使用 C++ 对象
CppClass cppObject;
cppObject.cppMethod();
}
return 0;
}
Unity客户端iOS平台技术框架
iOS 应用的入口是 Objective-C/Swift 层的 UIApplication 类。Objective-C/Swift 层负责初始化并管理应用的生命周期。初始化完成后,Objective-C/Swift 层调用 Unity 引擎的 Native 层,之后由 Native 层调用 Mono 虚拟机执行 C# 代码。整个流程是从操作系统到 Objective-C/Swift 层,再到 Unity 引擎的 Native 层,最终到 Mono 虚拟机。
执行流程
入口和控制流程
- 操作系统启动应用:
- iOS 系统启动应用时,首先执行 Objective-C/Swift 层的入口 (
UIApplication类)。
- iOS 系统启动应用时,首先执行 Objective-C/Swift 层的入口 (
- Objective-C/Swift 层初始化:
UIApplicationDelegate的application:didFinishLaunchingWithOptions:方法被调用,初始化应用。
- 调用 Native 层:
- Objective-C/Swift 层通过 UnityAppController 调用 Unity 引擎的 Native 层,初始化引擎并启动主循环。
- Mono 虚拟机初始化:
- Unity 引擎的 Native 层初始化 Mono 虚拟机,加载并执行 C# 代码。
- 主循环更新:
- Native 层定期调用 Mono 虚拟机执行每一帧的更新 (
Update)。
- Native 层定期调用 Mono 虚拟机执行每一帧的更新 (
堆栈层级和调用顺序
- 操作系统 -> Objective-C/Swift 层
- Objective-C/Swift 层 -> Unity 引擎 Native 层
- Unity 引擎 Native 层 -> Mono 虚拟机
- Mono 虚拟机 -> 用户的 C# 代码
堆栈调用顺序:
OS -> Objective-C/Swift -> Unity Native -> Mono VM -> C# 用户代码
Unity iOS开发流程
Unity项目
导出为 iOS 工程文件
Xcode 工程,设置开发者证书、App ID、Provisioning Profile 等
构建应用并归档,生成可上传至 App Store 的 .ipa 文件
通过 Xcode 或 App Store Connect 上传你的应用到 App Store。
Unity 调用iOS native插件
在需要集成 iOS 原生功能(如崩溃监听、推送通知、支付等)时,必须使用 Objective-C 或 Swift 来进行开发; Unity 的插件系统允许你将 iOS原生代码嵌入到 Unity 项目中.
方案: 使用静态库(.a 文件)并通过 DllImport 调用
编写 Objective-C 代码并导出 C 接口:在 Xcode 中创建一个新的 Objective-C 类,实现所需的功能。为了使这些功能能够被 C# 调用,需要使用 extern "C" 来定义 C 风格的接口。例如:
// MyPlugin.m
#import <Foundation/Foundation.h>
// 导出 C 接口
extern "C" {
void MyPluginFunction(const char* message) {
NSString *nsMessage = [NSString stringWithUTF8String:message];
NSLog(@"Message from Unity: %@", nsMessage);
// 在此处实现其他功能
}
}
- 编译为静态库:将上述代码编译为静态库(.a 文件)。在 Xcode 中,创建一个新的静态库项目,添加您的代码,然后构建以生成 .a 文件。
- 将静态库和头文件添加到 Unity 项目:将生成的 .a 文件和相应的头文件(.h)添加到 Unity 项目的
Assets/Plugins/iOS目录中。 - 在 C# 中声明并调用原生函数:在 Unity 的 C# 脚本中,使用
DllImport属性声明外部函数,然后调用它们。例如:
using System.Runtime.InteropServices;
using UnityEngine;
public class MyPluginWrapper : MonoBehaviour
{
#if UNITY_IOS
[DllImport("__Internal")]
private static extern void MyPluginFunction(string message);
#endif
public void CallMyPluginFunction(string message)
{
#if UNITY_IOS
MyPluginFunction(message);
#endif
}
}
请注意,"__Internal" 是一个特殊的标识符,用于表示调用的是应用程序内部的函数。
Thanks
ChatGPT DeepSeek