Objective-C 基础语法详细解析
Objective-C(简称 OC)是苹果生态(iOS、macOS、watchOS、tvOS)的核心开发语言,基于 C 语言扩展而来,既保留了 C 语言的底层能力,又引入了面向对象编程(OOP)特性,同时兼容 C 语言语法。以下从文件结构、数据类型、核心语法、面向对象特性到特有机制,全面梳理 OC 基础语法体系。
一、OC 工程核心:文件结构与编译逻辑
OC 代码通过 头文件(.h) 和 实现文件(.m) 配合实现功能,二者分工明确,是 OC 项目的基础组成单元。
文件类型 | 后缀 | 核心作用 | 包含内容 | 引用方式 |
---|---|---|---|---|
头文件 | .h |
对外暴露接口("说明书") | 类声明、方法声明、属性声明、宏定义、枚举、协议定义 | #import "文件名.h" 或 #import <框架名/文件名.h> |
实现文件 | .m |
实现内部逻辑("具体功能") | 类的方法实现、私有变量定义、私有方法实现 | 仅需在内部 #import 对应头文件 |
关键规则:
-
#import
与#include
的区别 :#import
会自动防止头文件重复引入,无需手动加#ifndef
保护,是 OC 中推荐的引用方式;#include
是 C 语言语法,可能导致重复引入。 -
框架头文件引用 :系统框架(如 Foundation、UIKit)的头文件用尖括号
<>
,自定义头文件用双引号""
,例如:objc#import <Foundation/Foundation.h> // 系统框架头文件 #import "Person.h" // 自定义头文件
二、数据类型体系:从基础到对象
OC 的数据类型分为 基本数据类型 (兼容 C 语言)和 对象数据类型(OC 专属),二者在内存存储、访问方式上有本质区别。
1. 基本数据类型(栈内存存储,效率高)
完全兼容 C 语言,同时新增 OC 专属布尔类型,适用于存储简单数值和状态。
类型类别 | 具体类型 | 字节数(64位系统) | 取值范围/说明 | 示例代码 |
---|---|---|---|---|
整型 | int |
4字节 | -2³¹ ~ 2³¹-1 | int score = 95; |
long |
8字节 | -2⁶³ ~ 2⁶³-1 | long userId = 1234567890123; |
|
NSInteger |
自适应(4/8字节) | 兼容 32/64 位系统,OC 推荐使用 | NSInteger age = 25; |
|
浮点型 | float |
4字节 | 单精度,精度约 6-7 位小数 | float weight = 62.5f; (必须加 f 标识) |
double |
8字节 | 双精度,精度约 15-17 位小数 | double height = 1.83; |
|
CGFloat |
自适应(4/8字节) | 图形框架(Core Graphics)专用,OC 绘图推荐 | CGFloat radius = 10.5; |
|
字符型 | char |
1字节 | ASCII 字符(0-127) | char gender = 'M'; |
布尔型 | BOOL |
1字节 | OC 专属,本质是 typedef signed char BOOL ,取值 YES (1)或 NO (0) |
BOOL isStudent = YES; |
注意:OC 中 不推荐 使用 C 语言的
_Bool
或 C++ 的bool
,统一用BOOL
+YES
/NO
。
2. 对象数据类型(堆内存存储,引用访问)
OC 的核心数据类型,本质是"类的实例",必须通过 指针(*
) 访问,常用系统对象类型如下:
对象类型 | 用途 | 示例代码 | 关键特性 |
---|---|---|---|
NSString |
字符串处理 | NSString *name = @"张三"; |
不可变字符串,需用 @ 标识字面量,支持拼接、截取等操作 |
NSMutableString |
可变字符串 | NSMutableString *desc = [NSMutableString stringWithString:@"Hello"]; |
可动态添加、修改字符串内容 |
NSArray |
不可变数组 | NSArray *hobbies = @[@"篮球", @"编程"]; |
存储对象集合,不可修改长度,元素需为 OC 对象 |
NSMutableArray |
可变数组 | NSMutableArray *list = [NSMutableArray array]; [list addObject:@"苹果"]; |
可动态添加、删除元素 |
NSDictionary |
不可变字典 | NSDictionary *user = @{@"name": @"李四", @"age": @22}; |
键值对集合,键必须是不可变对象(如 NSString ) |
NSNumber |
基本类型包装 | NSNumber *count = @10; NSNumber *price = @39.9; |
将基本类型(int、float 等)包装为对象,用于集合存储 |
关键规则:
- 指针必须加
*
:对象变量本质是指向堆内存的指针,声明时必须加*
,例如NSString *str
而非NSString str
; - 字面量加
@
:OC 对象的字面量(字符串、数组、字典)需用@
与 C 语言区分,例如@"字符串"
(OC) vs"字符串"
(C); - 空指针
nil
:对象未初始化时,需赋值为nil
(OC 专属空指针),避免野指针,例如NSString *emptyStr = nil;
。
三、面向对象核心:类与对象
OC 是纯面向对象语言,一切功能围绕"类"(模板)和"对象"(实例)展开,通过 @interface
(声明)和 @implementation
(实现)完成类的定义。
1. 类的声明(.h 文件)
用 @interface
关键字定义类的"对外接口",包括类名、父类、公共属性、公共方法,是其他类调用该类的"入口"。
示例:Person.h(声明 Person 类)
objc
#import <Foundation/Foundation.h> // 引入基础框架,NSObject 所在头文件
// 声明 Person 类,继承自 NSObject(OC 所有类的根类)
@interface Person : NSObject
#pragma mark - 公共属性(用 @property 声明,编译器自动生成 getter/setter)
// 属性格式:@property (修饰符) 类型 *属性名;(基本类型无需 *)
@property (nonatomic, copy) NSString *name; // 姓名:copy 修饰不可变字符串,防止外部修改
@property (nonatomic, assign) NSInteger age; // 年龄:assign 修饰基本类型
@property (nonatomic, assign, getter=isStudent) BOOL student; // 是否学生:重命名 getter 为 isStudent
#pragma mark - 公共方法声明
// 实例方法:- 开头,需通过对象调用,格式:- (返回值类型) 方法名:参数1 参数名2:参数2...;
- (void)sayHello; // 无参数,无返回值
- (void)eat:(NSString *)food; // 1个参数(food:食物名称)
- (NSString *)introduceWithHobby:(NSString *)hobby; // 带返回值(自我介绍字符串)
// 类方法:+ 开头,直接通过类调用,常用于工厂方法(创建对象)
+ (Person *)personWithName:(NSString *)name age:(NSInteger)age;
@end
核心细节:@property
修饰符
修饰符控制属性的内存管理、线程安全、读写权限,是 OC 属性的核心配置,常用组合如下:
修饰符类别 | 可选值 | 作用 | 适用场景 |
---|---|---|---|
内存管理 | strong |
强引用:对象引用计数 +1,只要有强引用,对象不释放 | 大多数对象属性(如 NSString *name ) |
weak |
弱引用:不增加引用计数,对象释放后自动置为 nil |
避免循环引用(如代理属性 @property (nonatomic, weak) id<Delegate> delegate ) |
|
copy |
拷贝:赋值时拷贝一份新对象,原对象修改不影响当前属性 | 不可变对象(NSString 、NSArray 、NSDictionary ) |
|
assign |
赋值:直接赋值,不管理内存 | 基本类型(NSInteger 、BOOL 、CGFloat ) |
|
线程安全 | nonatomic |
非线程安全:不保证多线程下读写安全,效率高 | 移动端开发(绝大多数场景,UI 线程单线程访问) |
atomic |
线程安全:保证多线程下读写安全,效率低 | 多线程频繁读写的属性(极少用) | |
读写权限 | readwrite |
可读写:自动生成 getter + setter(默认) | 需外部修改的属性(如 name 、age ) |
readonly |
只读:仅生成 getter,无 setter | 不允许外部修改的属性(如 userId ) |
2. 类的实现(.m 文件)
用 @implementation
关键字实现类的"内部逻辑",包括方法的具体代码、私有变量、私有方法,仅在当前 .m
文件可见。
示例:Person.m(实现 Person 类)
objc
#import "Person.h" // 引入当前类的头文件
// 实现 Person 类
@implementation Person
#pragma mark - 私有变量(仅 .m 内部可见,外部无法访问)
NSString *_privateID; // 私有 ID,存储内部标识
#pragma mark - 公共方法实现
- (void)sayHello {
// self.属性名:调用属性的 getter 方法,获取属性值
NSLog(@"大家好!我是%@", self.name);
}
- (void)eat:(NSString *)food {
NSLog(@"%@正在吃%@", self.name, food);
}
- (NSString *)introduceWithHobby:(NSString *)hobby {
// 字符串拼接:用 [NSString stringWithFormat:],占位符 %@ 对应对象
return [NSString stringWithFormat:@"我叫%@,今年%ld岁,喜欢%@",
self.name, (long)self.age, hobby]; // NSInteger 转 long 避免警告
}
// 类方法实现:工厂方法,简化对象创建
+ (Person *)personWithName:(NSString *)name age:(NSInteger)age {
// 1. alloc:为对象分配堆内存(引用计数 = 1)
// 2. init:初始化对象属性和状态
Person *person = [[Person alloc] init];
// 调用 setter 方法赋值
person.name = name;
person.age = age;
return person;
}
#pragma mark - 私有方法(仅 .m 内部可见,外部无法调用)
- (void)privateMethod {
NSLog(@"这是 Person 类的私有方法,外部无法访问");
}
@end
核心细节:
- 对象创建流程 :OC 创建对象必须经过
alloc
(分配内存)和init
(初始化)两步,缺一不可,简写为[[类名 alloc] init]
; self
关键字 :实例方法中self
代表"当前对象",类方法中self
代表"当前类",用于访问当前对象的属性/方法,例如[self sayHello]
(调用当前对象的sayHello
方法);NSLog
打印 :OC 标准打印函数,格式为NSLog(@"格式化字符串", 参数1, 参数2...)
,常用占位符:%@
:打印 OC 对象(调用对象的description
方法);%ld
:打印NSInteger
或long
类型;%f
:打印float
或double
类型;%d
:打印int
类型。
3. 对象的使用(消息传递机制)
OC 调用方法的本质是"向对象发送消息",而非传统的"函数调用",语法格式为 [接收者 消息]
(接收者可以是对象或类,消息即方法名+参数)。
示例:main.m(程序入口,使用 Person 对象)
objc
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool { // 自动释放池:管理 OC 对象内存,避免泄漏
// 方式1:通过 alloc + init 创建对象
Person *person1 = [[Person alloc] init];
// 调用 setter 方法赋值(两种等价写法)
person1.name = @"李四"; // 简化写法(推荐)
[person1 setAge:22]; // 原始消息写法
person1.student = YES;
// 调用实例方法
[person1 sayHello]; // 输出:大家好!我是李四
[person1 eat:@"苹果"]; // 输出:李四正在吃苹果
NSString *intro1 = [person1 introduceWithHobby:@"游泳"];
NSLog(@"%@", intro1); // 输出:我叫李四,今年22岁,喜欢游泳
// 方式2:通过类方法(工厂方法)创建对象(简化流程)
Person *person2 = [Person personWithName:@"王五" age:25];
[person2 sayHello]; // 输出:大家好!我是王五
// 调用 getter 方法获取属性值(两种等价写法)
NSString *name1 = person1.name; // 简化写法(推荐)
NSString *name2 = [person2 name]; // 原始消息写法
NSLog(@"person1 姓名:%@,person2 姓名:%@", name1, name2);
}
return 0;
}
关键特性:
- 自动释放池(
@autoreleasepool
) :OC 内存管理的核心机制之一,池中标记为"自动释放"的对象,会在池结束时自动释放(调用release
),避免内存泄漏;移动端开发中,UIKit 会自动创建释放池,仅需在main
函数或异步线程中手动添加; - 空指针安全 :若接收者是
nil
(空指针),发送消息不会崩溃,返回值为nil
(对象类型)或0
(基本类型),例如Person *nilPerson = nil; [nilPerson sayHello];
(无崩溃,无输出)。
四、OC 特有语法:协议、分类、Block
除基础面向对象特性外,OC 提供协议、分类、Block 三种特有机制,用于解耦、代码复用和异步回调。
1. 协议(Protocol):类似"接口"
定义一套"必须/可选实现的方法",类通过 <协议名>
遵守协议,实现协议中的方法,常用于代理模式(解耦)。
示例 1:定义协议(MyProtocol.h)
objc
#import <Foundation/Foundation.h>
// 声明协议,继承自 NSObject 协议(OC 所有协议的根协议)
@protocol MyProtocol <NSObject>
// 必须实现的方法(@required,默认,不写也为必须)
- (void)mustDoTask;
// 可选实现的方法(@optional,可实现也可不实现)
@optional
- (void)optionalTask;
@end
示例 2:类遵守协议(Person.h 中声明)
objc
// Person 类遵守 MyProtocol 协议
@interface Person : NSObject <MyProtocol>
// ... 原有属性和方法
@end
示例 3:实现协议方法(Person.m 中)
objc
@implementation Person
// ... 原有方法实现
// 必须实现协议的 mustDoTask 方法(不实现会报警告)
- (void)mustDoTask {
NSLog(@"%@ 完成了必须执行的任务", self.name);
}
// 可选实现 optionalTask 方法(可省略)
- (void)optionalTask {
NSLog(@"%@ 完成了可选任务", self.name);
}
@end
应用场景:代理模式
例如 iOS 中 UITableView
的 UITableViewDelegate
协议,控制器通过实现协议方法控制表格的点击、高度等,本质是"协议定义规则,类实现规则",实现代码解耦。
2. 分类(Category):扩展类功能(续)
在不修改原类代码的前提下,为类 新增方法 (不能直接新增属性,需通过关联对象间接实现),常用于拆分庞大类的代码、扩展系统类功能(如为 NSString
新增字符串处理方法)。
示例 1:为系统类 NSString
扩展分类(新增字符串处理方法)
首先创建分类文件(NSString+Extension.h
和 NSString+Extension.m
):
头文件(NSString+Extension.h)
声明分类的公共方法,格式为 @interface 原类名 (分类名)
:
objc
#import <Foundation/Foundation.h>
// 为 NSString 类添加名为 Extension 的分类
@interface NSString (Extension)
// 新增方法:判断字符串是否为纯数字
- (BOOL)isPureNumber;
// 新增方法:截取字符串前 N 个字符
- (NSString *)substringWithLength:(NSInteger)length;
@end
实现文件(NSString+Extension.m)
实现分类的方法,格式为 @implementation 原类名 (分类名)
:
objc
#import "NSString+Extension.h"
@implementation NSString (Extension)
// 实现"判断纯数字"方法
- (BOOL)isPureNumber {
// 正则表达式匹配纯数字
NSString *regex = @"^[0-9]*$";
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
return [predicate evaluateWithObject:self];
}
// 实现"截取前 N 个字符"方法(处理越界情况)
- (NSString *)substringWithLength:(NSInteger)length {
// 若长度超过字符串本身,直接返回原字符串
if (length >= self.length) {
return self;
}
// 调用系统方法截取,避免越界
return [self substringToIndex:length];
}
@end
示例 2:使用分类方法
引入分类头文件后,所有 NSString
对象均可直接调用分类新增的方法:
objc
#import <Foundation/Foundation.h>
#import "NSString+Extension.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSString *str1 = @"123456";
NSString *str2 = @"abc123";
// 调用分类方法判断纯数字
NSLog(@"str1 是否纯数字:%@", [str1 isPureNumber] ? @"YES" : @"NO"); // 输出 YES
NSLog(@"str2 是否纯数字:%@", [str2 isPureNumber] ? @"YES" : @"NO"); // 输出 NO
// 调用分类方法截取前 3 个字符
NSString *subStr1 = [str1 substringWithLength:3];
NSLog(@"str1 前3个字符:%@", subStr1); // 输出 123
}
return 0;
}
分类的关键规则:
- 不能直接新增属性 :分类的
@interface
中声明的属性,编译器不会自动生成getter/setter
和成员变量,需通过objc_setAssociatedObject
和objc_getAssociatedObject
关联对象实现(见下文补充); - 方法优先级:若分类方法与原类方法同名,分类方法会覆盖原类方法(编译警告,不推荐);若多个分类方法同名,最后编译的分类方法生效;
- 系统类扩展 :可直接为
NSString
、NSArray
等系统类添加分类,无需修改系统源码,是 OC 灵活扩展的核心特性。
补充:分类中"间接新增属性"(关联对象)
通过 Runtime 库的关联对象机制,可在分类中为类添加"伪属性",示例如下(为 Person
类分类新增 address
属性):
Person+Address.h
objc
#import "Person.h"
@interface Person (Address)
// 声明关联属性
@property (nonatomic, copy) NSString *address;
@end
Person+Address.m
objc
#import "Person+Address.h"
#import <objc/runtime.h> // 引入 Runtime 库
// 定义关联对象的 key(唯一标识)
static const void *PersonAddressKey = &PersonAddressKey;
@implementation Person (Address)
// 实现 address 的 getter 方法
- (NSString *)address {
// 通过 key 获取关联对象
return objc_getAssociatedObject(self, PersonAddressKey);
}
// 实现 address 的 setter 方法
- (void)setAddress:(NSString *)address {
// 设置关联对象:参数依次为"宿主对象""key""关联值""内存管理策略"
objc_setAssociatedObject(self, PersonAddressKey, address, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
@end
使用时与普通属性一致:
objc
Person *person = [[Person alloc] init];
person.address = @"北京市朝阳区"; // 调用分类的 setter
NSLog(@"地址:%@", person.address); // 调用分类的 getter,输出 北京市朝阳区
3. Block:匿名函数/闭包
Block 是 OC 中的"匿名函数",可捕获外部变量,常用于 异步回调 (如网络请求回调、动画完成回调)、简化代码逻辑(如集合遍历、排序),语法类似 Swift 的闭包或 JavaScript 的箭头函数。
1. Block 的基本语法
Block 的声明格式为:返回值类型 (^Block名称)(参数列表) = ^(参数列表) { 代码块 };
- 若无返回值,返回值类型为
void
; - 若无参数,参数列表可省略(仅保留
()
); - 捕获外部变量时,默认是"值捕获"(不可修改),需加
__block
修饰才能修改。
示例 1:无参数、无返回值的 Block
objc
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 声明并定义 Block(无参数、无返回值)
void (^PrintHelloBlock)(void) = ^(void) {
NSLog(@"Hello, Block!");
};
// 调用 Block(类似函数调用)
PrintHelloBlock(); // 输出 Hello, Block!
}
return 0;
}
示例 2:带参数、带返回值的 Block(计算两数之和)
objc
// 声明并定义 Block(参数:两个 int,返回值:int)
int (^AddBlock)(int, int) = ^(int a, int b) {
return a + b;
};
// 调用 Block 并接收返回值
int result = AddBlock(3, 5);
NSLog(@"3 + 5 = %d", result); // 输出 3 + 5 = 8
示例 3:捕获外部变量(__block
修饰可修改变量)
objc
__block int count = 0; // __block 修饰:允许 Block 内部修改外部变量
// Block 内部修改外部变量
void (^IncrementBlock)(void) = ^ {
count++; // 若不加 __block,编译报错
NSLog(@"当前 count:%d", count);
};
IncrementBlock(); // 输出 当前 count:1
IncrementBlock(); // 输出 当前 count:2
2. Block 的应用场景:异步回调
最典型的场景是"网络请求回调"------网络请求是异步操作,请求完成后通过 Block 通知调用者结果(类似 Android 的 Callback)。
示例:模拟网络请求工具类(NetworkTool.h
/NetworkTool.m
)
objc
// NetworkTool.h
#import <Foundation/Foundation.h>
// 定义回调 Block 类型(简化声明,用 typedef 重命名)
typedef void (^RequestSuccessBlock)(NSString *responseData); // 成功回调:返回响应数据
typedef void (^RequestFailureBlock)(NSError *error); // 失败回调:返回错误信息
@interface NetworkTool : NSObject
// 声明网络请求方法(参数含成功/失败 Block)
+ (void)sendRequestWithURL:(NSString *)url
success:(RequestSuccessBlock)success
failure:(RequestFailureBlock)failure;
@end
objc
// NetworkTool.m
#import "NetworkTool.h"
@implementation NetworkTool
+ (void)sendRequestWithURL:(NSString *)url
success:(RequestSuccessBlock)success
failure:(RequestFailureBlock)failure {
// 模拟异步网络请求(用 GCD 延迟 2 秒执行)
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_global_queue(0, 0), ^{
// 模拟请求结果:若 URL 包含"success",则成功;否则失败
if ([url containsString:@"success"]) {
// 调用成功 Block,传递响应数据
if (success) { // 先判断 Block 是否为空,避免崩溃
success(@"请求成功!响应数据:{\"code\":200,\"data\":\"OK\"}");
}
} else {
// 调用失败 Block,传递错误信息
if (failure) {
NSError *error = [NSError errorWithDomain:@"NetworkError"
code:404
userInfo:@{NSLocalizedDescriptionKey:@"请求失败,URL 错误"}];
failure(error);
}
}
});
}
@end
使用网络工具类(通过 Block 接收回调):
objc
#import <Foundation/Foundation.h>
#import "NetworkTool.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"开始发送请求...");
// 调用网络请求方法,传入成功/失败 Block
[NetworkTool sendRequestWithURL:@"https://example.com/success"
success:^(NSString *responseData) {
// 成功回调:在主线程更新 UI(示例中仅打印)
NSLog(@"请求成功:%@", responseData);
}
failure:^(NSError *error) {
// 失败回调:处理错误
NSLog(@"请求失败:%@", error.localizedDescription);
}];
// 阻塞主线程,等待异步回调(实际开发中无需此操作,UI 线程会自动循环)
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3]];
}
return 0;
}
Block 的关键注意事项:
-
避免循环引用 :若 Block 捕获了"强引用对象"(如
self
),且对象又强引用 Block(如 Block 是对象的属性),会导致循环引用(内存泄漏)。解决方案是使用__weak
弱引用 :objc// 正确写法:用 __weak 修饰 self,避免循环引用 __weak typeof(self) weakSelf = self; self.requestBlock = ^{ // Block 内部使用 weakSelf,避免强引用 [weakSelf updateUIWithData:@"数据"]; };
-
Block 为空判断 :调用 Block 前必须判断是否为空(
if (block) { block(); }
),否则 Block 为nil
时调用会崩溃; -
内存管理 :Block 默认存储在"栈"中,若需在超出作用域后使用(如异步回调),会自动拷贝到"堆"中(ARC 下自动管理,MRC 下需手动调用
copy
)。
五、内存管理:ARC 与引用计数
OC 的内存管理核心是 引用计数(Reference Counting),即通过计数跟踪对象的引用次数:对象被引用时计数 +1,引用释放时计数 -1,计数为 0 时对象销毁(释放堆内存)。
目前 OC 开发默认使用 ARC(Automatic Reference Counting,自动引用计数) ,编译器自动插入 retain
(计数 +1)、release
(计数 -1)、autorelease
(延迟释放)代码,无需手动管理内存;早期的 MRC(Manual Reference Counting)已极少使用。
1. ARC 下的引用类型
ARC 中通过 strong
(强引用)和 weak
(弱引用)控制对象生命周期:
-
strong
强引用 :默认引用类型,持有对象,使对象引用计数 +1,只要有强引用存在,对象不会被销毁;objc// strong 引用:person 强引用对象,计数 = 1 Person *person = [[Person alloc] init];
-
weak
弱引用 :不持有对象,不改变引用计数,对象被销毁后,weak
引用会自动置为nil
(避免野指针),常用于避免循环引用(如代理属性、Block 捕获self
):objc// weak 引用:weakPerson 不持有对象,计数仍为 1 __weak Person *weakPerson = person;
2. 自动释放池(@autoreleasepool
)
@autoreleasepool
是 ARC 中管理"延迟释放对象"的机制:
-
调用
[object autorelease]
(ARC 下编译器自动调用)的对象,会被加入当前自动释放池; -
自动释放池结束时(
@autoreleasepool
代码块执行完毕),池中所有对象会被统一调用release
,计数 -1; -
移动端开发中,UIKit 会在每一次事件循环(如点击、滑动)中自动创建和销毁自动释放池,无需手动添加;仅在批量创建大量临时对象(如循环创建 1000 个
NSString
)时,手动添加释放池可避免内存峰值过高:objc// 批量创建临时对象,手动添加释放池优化内存 for (int i = 0; i < 1000; i++) { @autoreleasepool { NSString *tempStr = [NSString stringWithFormat:@"临时字符串_%d", i]; // 使用 tempStr...(使用完毕后,释放池结束时自动释放) } }
六、OC 与 Swift 的关系
OC 是苹果早期生态的核心语言,而 Swift 是苹果 2014 年推出的现代语言,二者的关系是 兼容共存:
- 混编支持 :OC 项目可直接引入 Swift 代码(需创建桥接文件
项目名-Bridging-Header.h
),Swift 项目也可通过@objc
暴露接口给 OC 调用; - 底层共享:OC 和 Swift 均基于苹果的 Runtime 运行时系统,可通过 Runtime 机制互相调用类和方法;
- 生态迁移:苹果官方推荐新项目使用 Swift,但 OC 仍被大量老项目(如 iOS 系统框架、第三方库)使用,短期内不会被淘汰。
总结
Objective-C 语法的核心特点是"C 语言基础 + 面向对象扩展 + 特有机制":
- 文件结构上通过
.h
(声明)和.m
(实现)分离接口与逻辑; - 数据类型分为基础类型(兼容 C)和对象类型(OC 专属,需指针访问);
- 面向对象通过类(
@interface
/@implementation
)、属性(@property
)、消息传递([接收者 消息]
)实现; - 特有机制(协议、分类、Block)解决解耦、代码复用、异步回调问题;
- 内存管理依赖 ARC 和引用计数,自动释放池辅助优化内存。
OC 是苹果生态开发的基础,理解其语法体系不仅能应对老项目维护,也能更深入理解 Swift 与苹果底层框架的设计逻辑。