Objective-C 教程:从入门到实践
目录
- 引言:什么是 Objective-C?
- 环境搭建
- 基础语法
- 1 "Hello, World!"
- 2 面向对象核心概念
- 3 变量与数据类型
- 4 方法
- 5 属性
- 6 内存管理 (MRC vs. ARC)
- 7 协议 与代理
- 8 类别
- 9 块
- 实战项目:一个简单的待办事项 应用
- 学习资源与进阶
引言:什么是 Objective-C?
Objective-C 是一种通用的、面向对象的编程语言,它是 C 语言的超集,这意味着任何合法的 C 代码也是合法的 Objective-C 代码,它被广泛用于 Apple 的 macOS 和 iOS 操作系统的开发,是构建原生 Apple 应用程序的传统语言。

主要特点:
- C 语言基础:拥有 C 语言的全部特性,包括指针、手动内存管理(早期)等。
- Smalltalk 消息传递:其面向对象的特性深受 Smalltalk 影响,调用方法被称为“发送消息”,这使得它非常灵活和动态。
- 运行时系统:Objective-C 的许多强大功能(如动态类型、方法交换)都是在运行时决定的,而不是编译时。
- 与 Swift 共存:Apple 推荐使用 Swift 作为主要开发语言,但 Objective-C 仍然被广泛用于维护旧项目、与 C/C++ 库交互以及利用其成熟的生态。
环境搭建
学习 Objective-C 最主要的方式是使用 Apple 的官方集成开发环境。
- 工具:Xcode
- 下载:从 Mac App Store 免费下载,Xcode 不仅包含编译器,还包含了 Interface Builder(用于可视化界面设计)、模拟器、调试器等全套工具。
- 创建新项目:
- 打开 Xcode,选择 "Create a new Xcode project"。
- 选择 "macOS" -> "Command Line Tool" 或 "iOS" -> "App"。
- 语言选择 Objective-C。
基础语法
1 "Hello, World!"
创建一个 Command Line Tool 项目后,你会看到一个 main.m 文件。
// main.m
#import <Foundation/Foundation.h> // 导入 Foundation 框架,包含了基本的数据类型和工具
int main(int argc, const char * argv[]) {
@autoreleasepool { // 自动释放池,用于管理内存(ARC 环境下必需)
// NSLog 是 Foundation 框架提供的日志输出函数,类似于 C 的 printf
// 它会自动在输出后添加换行符和时间戳等信息
NSLog(@"Hello, World!");
}
return 0;
}
关键点:

#import:类似于 C 的#include,但会防止同一个文件被重复导入。<Foundation/Foundation.h>:是 Objective-C 的核心框架,包含了字符串、数组、字典等基本类。@autoreleasepool:在 ARC(自动引用计数)环境下,用于创建一个作用域,当作用域结束时,其中的自动释放对象会被释放。- 这是 Objective-C 的字符串字面量,属于
NSString对象。 NSLog:格式化输出字符串, 是一个格式说明符,用于打印对象。
2 面向对象核心概念
Objective-C 中的两个核心结构是 接口 和 实现。
- 接口:定义了类的公共行为(方法)和属性,通常以
.h(header) 文件结尾。 - 实现:定义了接口中声明的具体代码逻辑,通常以
.m(implementation) 文件结尾。
一个简单的 Car 类示例:
Car.h (接口文件)
#import <Foundation/Foundation.h> // @interface 声明一个类 // 继承自 NSObject,所有 Objective-C 类的根类 @interface Car : NSObject // 声明一个属性 // @property 自动生成 getter 和 setter 方法 // nonatomic: 非原子操作,性能更高 // strong: 强引用,表示对对象的所有权 @property (nonatomic, strong) NSString *brand; // 声明一个方法 // - 表示实例方法 (需要对象才能调用) // (void) 表示返回类型是 void // (NSString *) 表示返回类型是 NSString 对象 - (void)drive; - (NSString *)getBrand; @end
Car.m (实现文件)

#import "Car.h" // 导入自己的头文件
// @implementation 实现一个类
@implementation Car
// @synthesize 让编译器自动生成 brand 属性的 getter/setter 方法
// (在较新版本的 Xcode 中,可以省略 @synthesize,编译器会自动完成)
@synthesize brand;
// 实现 drive 方法
- (void)drive {
NSLog(@"The %@ car is driving.", self.brand);
}
// 实现 getBrand 方法
- (NSString *)getBrand {
return self.brand;
}
@end
3 变量与数据类型
- 基本数据类型:和 C 语言一样,
int,float,double,char,BOOL(YES/NO)。 - 对象类型:使用指针来表示,
NSString *,NSArray *,Car *。 id类型:一个万能的对象类型,可以指向任何 Objective-C 对象,非常灵活,但会失去编译时类型检查。
NSString *name = @"John"; // 字符串对象 int age = 30; BOOL isStudent = NO; id someObject = @"I can be anything"; // 合法 someObject = @123; // 也合法
4 方法
Objective-C 的方法声明和调用非常独特。
方法签名格式:
-/+ (返回类型) 方法名: (参数类型)参数名1 参数名2: (参数类型)参数名2 ...
- (实例方法) / (类方法,类似静态方法)
- 是参数的分割符,参数名也参与方法签名。
示例:
声明
- (void)setModel:(NSString *)model andYear:(int)year; + (instancetype)carWithBrand:(NSString *)brand; // 工厂类方法
调用
Car *myCar = [[Car alloc] init]; // 创建对象 [myCar setModel:@"Model S" andYear:2025]; // 调用实例方法 Car *tesla = [Car carWithBrand:@"Tesla"]; // 调用类方法
5 属性
@property 是一个编译器指令,可以自动为实例变量生成 getter 和 setter 方法。
属性修饰符:
- 原子性:
atomic(默认): 线程安全,但性能开销大。nonatomic: 非线程安全,性能高,在 iOS 开发中几乎总是使用nonatomic。
- 引用/所有权:
strong: 强引用,持有对象,对象会一直存在,直到没有强引用指向它,用于对象类型。weak: 弱引用,不持有对象,对象被销毁时,指针会自动置为nil,用于避免循环引用(如 delegate)。assign: 用于基本数据类型 (int,BOOL等),或用于解决循环引用的特殊情况。copy: 创建一个副本,用于可变对象(如NSMutableString),防止外部修改影响内部。
示例:
@property (nonatomic, strong) NSMutableString *name; // 使用 strong @property (nonatomic, weak) id delegate; // 使用 weak @property (nonatomic, assign) NSInteger age; // 使用 assign
6 内存管理
这是 Objective-C 中一个至关重要的主题。
- MRC (Manual Reference Counting):手动管理,程序员需要手动调用
retain,release,autorelease来增加和减少引用计数,当计数为 0 时,对象被销毁。(现已不推荐,但了解历史很重要) - ARC (Automatic Reference Counting):自动引用计数,Xcode 编译器会在编译时自动插入
retain,release等代码,极大地简化了内存管理。(现代 Objective-C 开发的标准)
ARC 规则:
- 你仍然需要理解
strong,weak,assign的区别。 - 不能调用
retain,release,autorelease,dealloc等方法(除了在dealloc中释放非对象资源)。 @autoreleasepool块仍然需要用于管理大量临时创建的对象。
dealloc 方法:
当一个对象即将被销毁时,系统会调用其 dealloc 方法,你需要手动释放那些不属于 ARC 管理的资源(你通过 malloc 分配的 C 语言内存)。
@implementation MyClass {
void *someCFObject; // 假设这是一个 Core Foundation 对象
}
- (void)dealloc {
CFRelease(someCFObject); // 手动释放
[super dealloc]; // MRC 需要调用,ARC 会自动处理,不应手动调用
}
@end
7 协议 与代理
协议定义了一组方法,但不提供实现,任何类都可以遵循一个协议,并实现其方法,这是实现委托模式的基础。
协议示例 (CarProtocol.h)**
#import <Foundation/Foundation.h> // @protocol 定义一个协议 // @optional 表示遵循协议的类可以选择性实现的方法 // @required (默认) 表示必须实现的方法 @protocol CarProtocol <NSObject> @required - (void)carDidStartEngine:(Car *)car; @optional - (void)carDidStopEngine:(Car *)car; @end
在类中使用协议
// 在 .h 文件中
#import "CarProtocol.h"
@interface Car : NSObject
@property (nonatomic, weak) id<CarProtocol> delegate; // delegate 必须遵循 CarProtocol
- (void)startEngine;
@end
// 在 .m 文件中
@implementation Car
- (void)startEngine {
NSLog(@"Engine started.");
// 检查 delegate 是否存在并是否响应这个方法
if ([self.delegate respondsToSelector:@selector(carDidStartEngine:)]) {
[self.delegate carDidStartEngine:self];
}
}
@end
8 类别
允许你在不修改原类源代码的情况下,为已存在的类添加新方法,非常实用。
示例:为 NSString 添加一个 MD5 哈希方法
// NSString+MD5.h
#import <Foundation/Foundation.h>
@interface NSString (MD5)
- (NSString *)md5Hash;
@end
// NSString+MD5.m
#import "NSString+MD5.h"
#import <CommonCrypto/CommonDigest.h> // Apple 的加密框架
@implementation NSString (MD5)
- (NSString *)md5Hash {
const char *str = [self UTF8String];
unsigned char result[CC_MD5_DIGEST_LENGTH];
CC_MD5(str, (CC_LONG)strlen(str), result);
NSMutableString *ret = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
[ret appendFormat:@"%02x", result[i]];
}
return ret;
}
@end
使用方式:
NSString *myString = @"hello"; NSString *hash = [myString md5Hash]; NSLog(@"%@", hash); // 输出 5d41402abc4b2a76b9719d911017c592
9 块
Block 是 C 语言、Objective-C 和 Swift 中的一个强大特性,它是一种匿名函数,可以捕获其所在作用域的变量。
语法:^ (插入符号) 是 Block 的标志。
// 定义一个 Block 变量
int (^myBlock)(int, int) = ^(int a, int b) {
return a + b;
};
// 调用 Block
int result = myBlock(5, 3);
NSLog(@"Result: %d", result); // 输出 Result: 8
// 常用于作为方法的参数,例如数组的排序
NSArray *strings = @"hello world from objective-c".componentsSeparatedByString:@" ";
NSLog(@"Sorted: %@", [strings sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [obj1 compare:obj2]; // 按字母顺序排序
}]);
实战项目:一个简单的待办事项 应用
这个项目将涵盖创建 UI、处理用户输入、数据存储和委托模式。
目标:一个可以添加、显示待办事项的应用。
步骤:
- 创建项目:在 Xcode 中创建一个新的 Single View App 项目,语言选择 Objective-C。
- 设计界面:
- 打开
Main.storyboard。 - 添加一个
UITableView用于显示待办事项列表。 - 添加一个
UITextField用于输入新事项。 - 添加一个
UIButton用于添加事项。 - 使用 Auto Layout 约束好它们的位置。
- 打开
- 创建数据模型:
- 新建一个
TodoItem类,只有一个title属性。
- 新建一个
- 连接 UI 与代码:
- 打开
ViewController.h,为UITableView,UITextField,UIButton创建@property(并连接到 Storyboard 中的控件)。 - 遵循
UITableViewDataSource和UITableViewDelegate协议。
- 打开
- 实现数据源方法:
- 在
ViewController.m中实现tableView:numberOfRowsInSection:和tableView:cellForRowAtIndexPath:方法来显示列表。
- 在
- 处理添加逻辑:
- 为 "Add" 按钮创建一个
IBAction。 - 在方法中,获取
UITextField的文本,创建一个新的TodoItem对象,并添加到一个数组中。 - 刷新
UITableView([self.tableView reloadData];)。
- 为 "Add" 按钮创建一个
- 持久化存储 (使用
NSUserDefaults):- 在
viewDidLoad中,从UserDefaults读取已保存的待办事项列表。 - 在添加新事项或应用将要退出时,将列表保存到
UserDefaults。
- 在
这是一个简化的流程,但足以让你了解如何将所学知识组合起来构建一个完整的应用。
学习资源与进阶
- 官方文档:
- 书籍:
- 《Objective-C 编程》:Aaron Hillegass 著,Big Nerd Ranch 系列书籍,讲解清晰,实例丰富。
- 《Cocoa 编程》:Aaron Hillegass 著,在掌握 Objective-C 后阅读,深入讲解 macOS/iOS 的框架。
- 在线教程:
- Ray Wenderlich:网站上有大量高质量的 Objective-C 和 Swift 教程。
- 斯坦福大学公开课:CS193P (iOS) 和 CS193M (macOS) 的早期课程是基于 Objective-C 的,是绝佳的学习材料。
- 进阶主题:
- Core Data:Apple 的官方数据持久化框架。
- Core Animation:用于创建流畅的动画效果。
- 网络编程:使用
NSURLSession进行网络请求。 - 与 C++ 交互:了解如何混合使用 Objective-C 和 C++(称为 "Objective-C++")。
希望这份教程能帮助你顺利入门 Objective-C!虽然 Swift 是现在的趋势,但掌握 Objective-C 能让你更好地理解 Apple 生态的底层,并能维护庞大的现有代码库。
