Objective-C 教程:从入门到实践
目录
- 引言:什么是 Objective-C?
- 开发环境搭建
- Objective-C 核心基础
- 1 Hello, World!
- 2 面向对象思想回顾
- 3 语法特点:C 语言的超集
- 核心概念详解
- 1 接口与实现:
.h和.m文件 - 2 对象的创建与使用
- 3 消息传递**
- 4 属性**
- 5 方法**
- 6 协议**
- 7 分类**
- 8 块**
- 1 接口与实现:
- 内存管理
- 1 MRC (手动引用计数)
- 2 ARC (自动引用计数) - 现代 iOS 开发标准
- 常用框架与工具
- 1 Foundation 框架
- 2 Core Data
- 3 Xcode 调试技巧
- 学习路径与资源推荐
- 为什么还要学 Objective-C?
引言:什么是 Objective-C?
Objective-C(简称 ObjC 或 OC)是苹果公司 macOS 和 iOS 操作系统的主要编程语言,它是一门面向对象的语言,其语法独特,融合了 Smalltalk 的消息传递机制和 C 语言的底层能力。

主要特点:
- C 语言的超集:任何合法的 C 语言代码都可以直接在 Objective-C 中编译运行,这使得它非常强大,可以直接操作内存、指针等底层资源。
- 动态性:与 C++ 或 Java 不同,Objective-C 的很多操作(如方法调用、类型检查)是在运行时决定的,而不是编译时,这赋予了它极高的灵活性。
- 运行时系统:Objective-C 的强大功能很大程度上依赖于其底层的运行时系统,它负责处理对象、消息分发、方法转发等。
- 社区与生态:虽然现在 Swift 是苹果官方主推的语言,但海量的现有 iOS/macOS 应用、框架和开源库都是用 Objective-C 编写的,阅读和修改这些代码是必备技能。
开发环境搭建
开发 Objective-C 应用,你只需要安装苹果官方的集成开发环境。
- 硬件:一台 Mac 电脑(搭载 Intel 或 Apple Silicon 芯片)。
- 软件:从 Mac App Store 免费下载 Xcode,Xcode 不仅包含了编译器、调试器,还集成了 Interface Builder(用于可视化界面设计)、模拟器、性能分析工具等,是开发苹果应用的全能工具。
安装完成后,打开 Xcode,同意许可协议,它就会自动安装所有必要的命令行工具,包括 Clang 编译器和 Objective-C 运行时。
Objective-C 核心基础
1 Hello, World!
创建一个新的 Xcode 项目,选择 "macOS" -> "Command Line App",语言选择 "Objective-C"。

在 main.m 文件中,你会看到如下代码:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
}
return 0;
}
代码解析:
#import <Foundation/Foundation.h>:#import是#include的一个增强版,它会自动防止头文件被重复包含。Foundation.h是 Foundation 框架的核心头文件,包含了所有基本的数据类型、集合类、字符串等。@autoreleasepool { ... }:这是 Objective-C 的自动内存管理池,所有创建的对象都应该放在一个@autoreleasepool块中,以便系统能够及时回收不再使用的内存。NSLog(@"Hello, World!");:NSLog是 Foundation 框架提供的日志输出函数,类似于 C 语言的printf,它会自动在输出后加上时间戳和程序信息,方便调试。 这种形式的字符串是 Objective-C 的字符串字面量,它是一个NSString对象,而不是 C 风格的字符数组。
2 面向对象思想回顾
在深入代码前,请务必理解 OOP 的三大支柱:
- 封装:将数据(属性)和操作数据的方法捆绑在一起,形成一个对象,并对外部隐藏其内部实现细节。
- 继承:一个类可以继承另一个类的属性和方法,实现代码复用和层次化设计。
- 多态:不同的对象可以对同一消息做出不同的响应,在 Objective-C 中,这主要通过协议和动态消息传递实现。
3 语法特点:C 语言的超集
Objective-C 保留了 C 语言的所有特性,你可以这样写:

int a = 10;
float b = 3.14;
char c = 'A';
int array[5] = {1, 2, 3, 4, 5};
它引入了自己的一套语法来处理面向对象,这些语法都以 符号开头,@interface, @implementation, @property 等。
核心概念详解
这是 Objective-C 学习的重中之重。
1 接口与实现:.h 和 .m 文件
在 Objective-C 中,一个类的定义通常分为两个文件:
.h文件 (Header/Interface File):类的接口文件,它声明了这个类“有什么”(属性)和“能做什么”(方法),它就像一份公共契约,告诉其他代码这个类的功能。.m文件 (Implementation File):类的实现文件,它详细定义了在.h文件中声明的方法的具体实现逻辑。
示例:Person.h
#import <Foundation/Foundation.h> // @interface 声明一个类,继承自 NSObject // NSObject 是所有 Objective-C 类的根类 @interface Person : NSObject // @property 声明一个属性 // @property (nonatomic, copy) NSString *name; // nonatomic: 非原子性,性能更高 // copy: 对属性赋值时,会进行 copy 操作,确保对象不被意外修改 @property (nonatomic, copy) NSString *name; @property (nonatomic, assign) NSInteger age; // assign: 用于基本数据类型 // - 表示实例方法(需要对象才能调用) // (void) 表示返回类型是 void - (void)sayHello; // + 表示类方法(通过类名直接调用,不需要对象) + (instancetype)personWithName:(NSString *)name age:(NSInteger)age; @end
示例:Person.m
#import "Person.h"
@implementation Person
// 实现 sayHello 方法
- (void)sayHello {
// 使用 self 来引用当前对象
NSLog(@"Hello, my name is %@ and I'm %ld years old.", self.name, (long)self.age);
}
// 实现 personWithName 类方法
+ (instancetype)personWithName:(NSString *)name age:(NSInteger)age {
// alloc: 分配内存空间
// init: 初始化对象
Person *p = [[self alloc] init];
p.name = name;
p.age = age;
return p;
}
@end
2 对象的创建与使用
创建对象需要两步:分配内存 和 初始化。
// 1. 导入头文件 #import "Person.h" // ... // 2. 创建对象 Person *person1 = [[Person alloc] init]; // 3. 使用点语法或 setter 方法设置属性 person1.name = @"Alice"; person1.age = 30; // 4. 调用方法 [person1 sayHello]; // 输出: Hello, my name is Alice and I'm 30 years old. // 5. 使用类方法创建对象 Person *person2 = [Person personWithName:@"Bob" age:25]; [person2 sayHello]; // 输出: Hello, my name is Bob and I'm 25 years old.
3 消息传递**
这是 Objective-C 的核心思想。调用一个方法,在 Objective-C 中被称为“向对象发送一条消息”。
语法格式:[接收者 消息]
[person1 sayHello]:向person1这个对象发送sayHello消息。[Person personWithName:@"Bob" age:25]:向Person这个类发送personWithName:age:消息。
消息的接收者甚至可以响应一个它没有声明的方法(这被称为“消息转发”),这是其动态性的体现。
4 属性
@property 是 Objective-C 2.0 引入的语法糖,极大地简化了代码。
- 生成成员变量:默认情况下,
@property会自动在.m文件的实现块中生成一个带下划线_的私有成员变量(如_name)。 - 生成 getter/setter 方法:它会自动为你生成访问和修改属性的方法(即 getter 和 setter)。
- 属性修饰符:
- 内存管理修饰符:
strong: 默认,对对象进行强引用,只要还有一个强引用指向它,对象就不会被销毁。weak: 弱引用,不持有对象,对象被销毁后,指针会自动置为nil,用于避免循环引用。copy: 对赋值对象进行copy操作,常用于NSString,NSArray等不可变对象,防止其内容被意外修改。assign: 用于基本数据类型(NSInteger,CGRect等),是简单的值传递,不涉及内存管理。retain:strong的旧版写法,功能相同。
- 原子性修饰符:
atomic(默认): 线程安全,但性能开销大,在 iOS 开发中几乎不用。nonatomic: 非线程安全,性能高,是 iOS 开发的标准选择。
- 内存管理修饰符:
5 方法
- 实例方法 ():作用于对象实例,必须先创建对象,然后用对象来调用。
- (void)walk; - (NSString *)getFullName;
- 类方法 ():作用于类本身,可以直接用类名调用,无需创建对象,常用于创建“工厂方法”或执行与类相关的操作。
+ (instancetype)defaultManager; + (void)initialize;
- 方法名:Objective-C 的方法名由多个部分组成,每个冒号 都代表一个参数,这种命名方式非常具有描述性。
// 这是一个方法名,它描述了整个操作 - (void)setAge:(NSInteger)newAge; - (void)insertObject:(id)anObject atIndex:(NSUInteger)index;
6 协议
协议类似于 Java 中的接口或 C++ 中的纯虚类,它定义了一组方法,但不提供实现,任何类都可以采纳协议,并承诺实现这些方法。
协议定义 (.h 文件)
#import <Foundation/Foundation.h> // @protocol 定义协议名 // @optional 表示方法可选,采纳协议的类可以选择性实现 // @required 表示方法必须实现(默认) @protocol GreetingProtocol <NSObject> @required - (void)sayGreeting; @optional - (void)sayGoodbye; @end
采纳协议
#import "GreetingProtocol.h"
@interface Dog : NSObject <GreetingProtocol>
@end
@implementation Dog
- (void)sayGreeting {
NSLog(@"Woof! Hello!");
}
// sayGoodbye 是可选的,所以可以不实现
@end
协议是实现多态的关键,你可以定义一个方法,其参数类型是 id<GreetingProtocol>,然后传入任何采纳了该协议的对象。
7 分类
分类允许你为已存在的类添加方法,而无需修改其原始代码或创建子类,这对于扩展框架类(如 NSString)或给自定义类添加新功能非常有用。
语法:原类名 + 分类名
示例:为 NSString 添加一个分类
- 创建新文件,选择 "Objective-C File",File Type 选择 "Category",输入 Category Name 为 "Utils"。
- 这会生成两个文件:
NSString+Utils.h和NSString+Utils.m。
NSString+Utils.h
#import <Foundation/Foundation.h> // 为 NSString 添加一个名为 Utils 的分类 @interface NSString (Utils) - (BOOL)isNumeric; @end
NSString+Utils.m
#import "NSString+Utils.h"
@implementation NSString (Utils)
- (BOOL)isNumeric {
NSScanner *scanner = [NSScanner scannerWithString:self];
float floatValue;
return [scanner scanFloat:&floatValue] && [scanner isAtEnd];
}
@end
使用
NSString *numStr = @"123";
if ([numStr isNumeric]) {
NSLog(@"'%@' is a number.", numStr);
}
8 块
块是 C 语言、Objective-C 和 Swift 中的闭包,它封装了一段代码和这段代码执行所需的状态(局部变量),它非常灵活,常用于异步操作、回调函数和集合遍历。
基本语法
^{
// 封装的代码
NSLog("This is a block.");
};
// 带参数和返回值的块
^(int a, int b) -> int {
return a + b;
};
作为变量
// 定义一个块变量
void (^simpleBlock)(void) = ^{
NSLog(@"Block as a variable.");
};
// 调用
simpleBlock();
在集合遍历中的使用
NSArray *names = @[@"Alice", @"Bob", @"Charlie"];
[names enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"Index %lu: %@", (unsigned long)idx, obj);
// 如果找到 "Bob",就停止遍历
if ([obj isEqualToString:@"Bob"]) {
*stop = YES;
}
}];
内存管理
内存管理是 Objective-C 开发的核心难点之一,但现代的 ARC 已经极大地简化了它。
1 MRC (Manual Reference Counting) - 了解即可
在 ARC 出现之前,开发者需要手动管理内存,核心规则是:
alloc,new,copy,mutableCopy会创建一个新对象,其引用计数为 1。retain会使引用计数加 1。release会使引用计数减 1。- 当引用计数为 0 时,对象会被自动销毁。
dealloc方法在对象被销毁前调用,用于释放资源。
口诀:谁创建,谁释放;谁retain,谁release。
示例
// 错误示范:内存泄漏 NSString *str = [[NSString alloc] initWithFormat:@"Hello"]; // str 的引用计数为 1,但没有调用 release,它永远不会被释放 // 正确示范 NSString *str = [[NSString alloc] initWithFormat:@"Hello"]; [str release]; // 使用完后立即释放 // 使用 autorelease 延迟释放 NSString *str = [[[NSString alloc] initWithFormat:@"Hello"] autorelease]; // str 会在当前的 @autoreleasepool 结束时被释放
2 ARC (Automatic Reference Counting) - 现代 iOS 开发标准
Xcode 4.2 之后引入,编译器在编译时自动在代码中插入 retain, release, autorelease 调用,开发者无需手动管理。
核心规则:
- 不再使用
retain,release,autorelease,dealloc(除了释放实例变量)。 - 属性修饰符是关键:
strong,weak,copy,assign的作用由编译器保证。strong:相当于 MRC 中的retain。weak:相当于 MRC 中的assign,但用于对象,对象销毁时,weak 指针会自动置为nil,有效避免了“野指针”问题。
- 循环引用:如果两个对象互相用
strong引用对方,它们的引用计数永远无法归零,导致内存泄漏。解决方案是其中一端使用weak。
ARC 下的 dealloc
你仍然可以重写 dealloc 方法,但不能调用 [super dealloc],主要用于释放非 Objective-C 对象的资源,Core Foundation 对象。
@implementation MyView
- (void)dealloc {
// 释放非 ARC 管理的资源
CFRelease(_someCFObject);
// 不要调用 [super dealloc];
}
@end
常用框架与工具
1 Foundation 框架
这是 Objective-C 的基石,提供了所有非图形化的基础类。
NSString/NSMutableString:不可变/可变字符串。NSArray/NSMutableArray:不可变/可变对象数组。NSDictionary/NSMutableDictionary:不可变/可变键值对字典。NSSet/NSMutableSet:不可变/可变集合,保证元素唯一性。NSNumber:将基本数据类型包装成对象。NSData/NSMutableData:二进制数据。NSDate/NSCalendar/NSDateFormatter:日期和时间处理。
2 Core Data
苹果官方的持久化框架,用于管理对象图,它不是一个数据库,而是一个对象图管理和持久化框架,它将对象模型映射到 SQLite 数据库文件中,让你可以用面向对象的方式操作数据。
3 Xcode 调试技巧
- 断点:在代码行号左侧单击即可设置,程序运行到此处会暂停。
- LLDB 控制台:断点暂停后,可以在控制台下命令,如
po (print object)打印对象信息,p (print)打印变量值。 - 视图调试器:可以可视化地查看 App 的视图层级,方便定位 UI 问题。
学习路径与资源推荐
-
官方文档:
- The Objective-C Programming Language:苹果官方教程,最权威。
- Xcode Help:学习使用 Xcode。
-
经典书籍:
- 《Objective-C 编程》(又称“大黄书”):Objective-C 的“圣经”,内容详尽,适合系统学习。
- 《Cocoa 编程》(又称“红宝书”):在掌握 Objective-C 后,学习 Cocoa 框架的必读之作。
-
在线资源:
- Ray Wenderlich:网站上有大量高质量的 iOS/macOS 开发教程,很多教程虽然使用 Swift,但其设计思想和架构模式同样适用于 Objective-C。
- Stanford CS193P:斯坦福大学的 iOS 开发公开课,有历年视频和讲义,是入门的经典课程。
- Stack Overflow:遇到具体问题时,这里是最好的求助社区。
为什么还要学 Objective-C?
尽管 Swift 是苹果的未来,但在当前和可预见的未来,学习 Objective-C 仍然至关重要:
- 维护现有代码:绝大多数成熟的 App、第三方库和开源项目都是用 Objective-C 写的,如果你想阅读、修改或贡献这些代码,就必须懂 Objective-C。
- 理解底层机制:Objective-C 的“裸露”特性(如运行时、消息传递)能让你更深刻地理解 iOS/macOS 系统的工作原理,学习 Swift 时,这些底层机制被隐藏了,而 Objective-C 让它们无处可藏。
- 特定领域的应用:一些底层性能要求极高的库或与 C 代码库交互紧密的场景,仍然会优先选择 Objective-C。
- 职业发展:在很多公司,尤其是那些有历史包袱的大型 App 团队,能够熟练阅读和修改 Objective-C 代码是一项重要的加分项。
学习建议:如果你是新手,可以直接从 Swift 开始,因为它更现代、更安全、更易学,当你对 iOS 开发有了基本了解后,再回头来学习 Objective-C,这时你会发现很多概念是相通的,学习起来会事半功倍,并能更好地理解整个苹果开发生态。
