Objective-C 基础教程
目录
- 引言:什么是 Objective-C?
- 开发环境搭建
- 第一个程序:Hello, World!
- 基础语法
- 导入头文件
#importvs#include- 日志输出
- 注释
- 数据类型
- 基本数据类型
- 对象类型 (
id) NSString(字符串)NSArray(数组),NSDictionary(字典),NSNumber(数字)
- 核心概念:面向对象编程
- 类与对象
- 接口与实现
- 实例变量
- 属性
- 方法
- 实例方法
- 类方法
- 消息发送
- 内存管理
- 手动引用计数
- 自动引用计数 - 现代 Objective-C 的标准
- 协议
- 块
- 总结与学习资源
引言:什么是 Objective-C?
Objective-C(简称 OC)是 Apple 公司的主要编程语言,用于开发 macOS、iOS、iPadOS 和 watchOS 等平台的应用程序。

它是一门“混血”语言:
- C 语言基础:Objective-C 是 C 语言的超集,这意味着任何合法的 C 语言代码,都可以直接在 Objective-C 中编译和运行,它拥有 C 语言的全部特性,如指针、结构体、函数等。
- Smalltalk 消息传递:在 C 语言的基础上,Objective-C 添加了面向对象的特性,其核心是“消息传递”(Message Passing),而不是传统的“函数调用”(Function Call),这是它与 C++、Java 等语言最大的不同。
为什么学习它?
- 开发 Apple 生态应用:如果你想开发原生的 iPhone、iPad、Mac 应用,Objective-C 是必经之路(尽管现在 Swift 更流行,但大量现有项目仍使用 OC)。
- 理解底层:学习 OC 能让你更深入地理解 Apple 框架(如 Foundation, UIKit)的工作原理。
- 独特的编程思想:OC 的动态特性和消息传递机制,会给你带来全新的编程视角。
开发环境搭建
现代 Objective-C 开发主要使用 Xcode,这是 Apple 官方提供的集成开发环境。
- 下载 Xcode:访问 Mac App Store,搜索并免费下载 Xcode。
- 安装:Xcode 是一个庞大的应用,安装过程可能需要一些时间和空间。
- 创建新项目:
- 打开 Xcode,选择 "Create a new Xcode project"。
- 选择 "macOS" -> "Command Line Tool"。
- 在 "Language" 选项中,选择 Objective-C。
- 给项目命名,选择一个位置,然后点击 "Create"。
Xcode 会自动为你生成一个基础的 OC 项目结构。

第一个程序:Hello, World!
Xcode 生成的项目中,通常会有一个 main.m 文件。m 是 Objective-C 源文件的标准后缀。
打开 main.m,你会看到类似这样的代码:
#import <Foundation/Foundation.h>
// int main(int argc, const char * argv[]) {
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"Hello, World!");
}
return 0;
}
代码解释:
#import <Foundation/Foundation.h>:导入 Foundation 框架,这个框架包含了 OC 的基本类,如NSString,NSArray,NSObject等,没有它,我们甚至无法使用NSLog。int main(...):程序的入口点,和 C 语言一样。@autoreleasepool { ... }:这是一个自动释放池,用于管理内存,我们会在后面的内存管理部分详细解释,只需知道所有需要自动管理的对象都应该放在这里。NSLog(@"Hello, World!");:在控制台打印日志。 这种形式表示一个 OC 字符串对象。NSLog会自动在输出的末尾添加时间戳和程序信息。
运行程序:点击 Xcode 左上角的播放按钮(▶️),或者按 Cmd + R,在底部的控制台窗口,你将看到输出:

2025-10-27 10:30:00.123 MyProject[12345:67890] Hello, World!
基础语法
导入头文件
#import <Framework/Header.h>:导入系统框架的头文件。<>表示在系统路径下查找。#import "Local/Header.h":导入你自己项目中的头文件。 表示在项目相对路径下查找。
#import vs #include
#import 是 Apple 对 C 语言 #include 的增强,它的作用和 #include 一样,都是导入文件,但 #import 会确保同一个文件只被导入一次,从而避免了重复包含导致的编译错误,在 OC 中,始终使用 #import。
日志输出
除了 NSLog,你还会看到 printf(来自 C 语言)。
NSLog(@"This is an Objective-C log."); // 输出: 2025-10-27 ... This is an Objective-C log.
printf("This is a C-style log.\n"); // 输出: This is a C-style log.
区别:NSLog 更适合 OC,因为它能更好地处理对象,并附带调试信息。printf 速度稍快,但主要用于 C 风格的输出。
注释
- 单行注释:
// This is a comment - 多行注释:
/* This is a multi-line comment */
数据类型
基本数据类型
这些和 C 语言完全一样。
int: 整数float: 单精度浮点数double: 双精度浮点数char: 字符BOOL: 布尔值 (YES/NO, true/false)
int age = 30; float price = 99.9f; BOOL isStudent = YES;
对象类型 (id)
id 是一个特殊的类型,它可以指向任何 Objective-C 对象,它是一个动态类型,编译时不会检查对象具体是什么类型,只有在运行时才会确定。
id myObject = someObject; // myObject 可以是 NSString, NSArray, 或者任何其他 OC 对象
NSString (字符串)
字符串是 OC 中最常用的对象类型之一,它使用 符号作为前缀。
// 创建字符串 NSString *greeting = @"Hello"; // 注意:* 表示 greeting 是一个指向 NSString 对象的指针 // 字符串拼接 NSString *name = @"Alice"; NSString *fullGreeting = [greeting stringByAppendingFormat:@", %@", name]; NSLog(@"%@", fullGreeting); // 输出: Hello, Alice // 使用格式化创建字符串 NSString *anotherGreeting = [NSString stringWithFormat:@"The user is: %@", name]; NSLog(@"%@", anotherGreeting); // 输出: The user is: Alice
NSArray, NSDictionary, NSNumber
这些是 Foundation 框架中常用的集合类。
-
NSArray(有序数组):存放一组对象。// 创建不可变数组 NSArray *fruits = @[@"Apple", @"Banana", @"Orange"]; NSLog(@"First fruit: %@", fruits[0]); // 通过下标访问 // 获取数组元素个数 NSLog(@"Fruit count: %lu", (unsigned long)fruits.count);
-
NSDictionary(键值对字典):通过唯一的键来存储值。// 创建不可变字典 NSDictionary *person = @{ @"name": @"Bob", @"age": @30, // NSNumber @"city": @"New York" }; NSLog(@"Name: %@", person[@"name"]); // 通过键访问 -
NSNumber(数字包装器):因为集合类(如 NSArray)只能存放对象,不能存放基本数据类型(如int,float),所以需要用NSNumber将它们包装起来。NSNumber *myAge = @30; // 将 int 30 包装成 NSNumber 对象 NSNumber *myPrice = @19.99; // 将 double 19.99 包装成 NSNumber 对象
核心概念:面向对象编程
类与对象
- 类:创建对象的蓝图或模板,它定义了对象所具有的属性和方法。
- 对象:类的实例,是一个具体的实体,拥有类定义的属性和方法。
接口与实现
在 OC 中,一个类的定义通常分为两个文件:
.h文件 (头文件 / Interface / 公共接口):声明类的公共部分,它告诉外界“这个类有什么”和“它能做什么”。.m文件 (实现文件 / Implementation):实现类的具体逻辑,它告诉外界“这个类具体是怎么做的”。
示例:创建一个 Person 类
Person.h (接口)
#import <Foundation/Foundation.h> // @interface ... @end 是类的声明块 // Person: NSObject 表示 Person 类继承自 NSObject // NSObject 是几乎所有 OC 类的根类,提供了最基本的功能 @interface Person : NSObject // 声明一个属性 // @property 编译器指令,自动生成属性的 getter 和 setter 方法 // NSString *name: 属性类型和名称 // nonatomic: 非原子性,性能更好,是现代 iOS/macOS 开发的默认选择 @property (nonatomic, copy) NSString *name; // 声明一个方法 // - (void)sayHello; 表示这是一个实例方法 // (void) 是返回类型,sayHello 是方法名 // 没有参数的方法 - (void)sayHello; // 带参数的方法 // (void)greet:(NSString *)greeting withName:(NSString *)name; // 冒号后面跟着参数的类型和名称 - (void)greet:(NSString *)greeting withName:(NSString *)name; @end
Person.m (实现)
#import "Person.h" // 导入自己的头文件
// @implementation ... @end 是类的实现块
@implementation Person
// 实现 sayHello 方法
- (void)sayHello {
NSLog(@"Hello, my name is %@.", self.name); // self 指向当前对象本身,类似于 Java/C# 中的 this
}
// 实现 greet:withName: 方法
- (void)greet:(NSString *)greeting withName:(NSString *)name {
NSLog(@"%@, %@!", greeting, name);
}
@end
实例变量
在 .h 文件中,使用 @property 声明的属性,编译器会自动在 .m 文件中生成一个对应的私有实例变量(ivar),变量名通常为 _name,你通常不需要直接访问 _name,而是通过 self.name(即属性的 getter/setter)来访问。
属性
@property 是一个强大的编译器指令,它为你自动生成:
- 一个私有的实例变量(如
_name)。 - 一个 getter 方法(
- (NSString *)name)。 - 一个 setter 方法(
- (void)setName:(NSString *)name)。
属性的特性(括号里的内容):
nonatomic: 非原子性,性能高。strong: 强引用,表示该属性对它所指向的对象拥有所有权,当对象被赋值给这个属性时,引用计数会 +1,用于对象类型。weak: 弱引用,表示该属性对它所指向的对象没有所有权,当对象被赋值给这个属性时,引用计数不变,如果对象被销毁,这个属性会自动被置为nil,常用于 delegate 模式,以避免循环引用。copy: 复制,当对象被赋值给这个属性时,会调用该对象的copy方法创建一个副本,属性指向这个副本,用于可变对象(如NSMutableString),以防止外部修改影响属性内部值。assign: 简单赋值,用于基本数据类型(如int,float,BOOL)和weak引用的对象。
方法
-
实例方法:以 (减号) 开头,作用于单个对象实例,必须先创建对象才能调用。
Person *p = [[Person alloc] init]; [p sayHello];
-
类方法:以 (加号) 开头,作用于类本身,不需要创建实例就可以调用。
// NSString 的类方法,创建一个空字符串 NSString *emptyString = [NSString string];
消息发送
OC 调用方法的方式称为“消息发送”。
语法:[接收者 消息]
[p sayHello];:向对象p发送sayHello消息。[p greet:@"Hi" withName:@"Charlie"];:向对象p发送一个带参数的greet:withName:消息,注意,方法名是greet:withName:,而不是greet。
点语法
点语法是消息发送的一种简化形式,主要用于属性的 getter 和 setter。
-
获取属性值(调用 getter):
NSString *name = p.name; // 等价于 [p name]
-
设置属性值(调用 setter):
p.name = @"David"; // 等价于 [p setName:@"David"]
点语法不能用于普通的方法调用!p.sayHello() 是错误的,必须写成 [p sayHello]。
内存管理
现代 Objective-C 默认使用 自动引用计数。
核心思想:每个对象都有一个“引用计数”(Retain Count),当引用计数为 0 时,对象就会被系统自动销毁。
alloc,new,copy,mutableCopy:这些方法创建的对象,引用计数初始为 1。strong属性赋值、对象被添加进NSArray/NSDictionary:对象的引用计数 +1(称为 "retain")。strong属性被赋予新值、对象从NSArray/NSDictionary中移除:旧对象的引用计数 -1(称为 "release")。
你不需要手动 retain 和 release,编译器和运行时会自动帮你管理,你只需要遵守以下规则:
- 谁创建,谁释放:如果你通过
alloc,new,copy或mutableCopy创建了一个对象,你就拥有它,并且有责任在不再需要时释放它(在现代 ARC 下,这通常是隐式的)。 - 谁 retain,谁 release:如果你通过
strong属性或其它方式 retain 了一个对象,当不再需要时,它的引用计数会自动减少。
循环引用
这是 ARC 下最常见的内存泄漏问题,当两个或多个对象互相强引用时,它们的引用计数永远不会变为 0,导致无法被释放。
解决方案:将一方的引用改为 weak。
// A.h @property (nonatomic, strong) B *b; // B.h @property (nonatomic, strong) A *a; // 循环引用!
修正后:
// A.h @property (nonatomic, strong) B *b; // B.h @property (nonatomic, weak) A *a; // B 对 A 的引用是弱引用,打破循环
协议
协议类似于 Java 中的接口或 C++ 中的纯虚类,它定义了一组方法,但不实现这些方法,任何类都可以遵循协议,并实现协议中定义的方法。
用途:实现委托模式。
示例:一个下载器,可以通知它的代理(delegate)下载进度。
DownloadProtocol.h (协议定义)
#import <Foundation/Foundation.h> // @protocol ... @end 定义协议 // @optional 表示该协议中的方法是可选的,遵循协议的类可以选择性实现 // @required 表示该协议中的方法是必须实现的(默认) @protocol DownloadProtocol <NSObject> @optional - (void)downloadDidFinish:(NSString *)filePath; - (void)downloadDidFailWithError:(NSError *)error; @end
Downloader.h (使用协议的类)
#import <Foundation/Foundation.h> #import "DownloadProtocol.h" @interface Downloader : NSObject @property (nonatomic, weak) id<DownloadProtocol> delegate; // delegate 必须遵循 DownloadProtocol - (void)startDownload; @end
Downloader.m (实现)
#import "Downloader.h"
@implementation Downloader
- (void)startDownload {
NSLog(@"Download started...");
// 模拟下载完成
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
// 检查 delegate 是否响应这个方法,避免崩溃
if ([self.delegate respondsToSelector:@selector(downloadDidFinish:)]) {
[self.delegate downloadDidFinish:@"/path/to/file.zip"];
}
});
}
@end
块
块是 C 语言、C++、Objective-C 和 Swift 中的一个语言特性,它允许你创建一段可以在之后执行的代码,类似于匿名函数或 lambda 表达式。
语法:^ { /* code here */ }
示例:
int (^myBlock)(int, int) = ^(int a, int b) {
return a + b;
};
int result = myBlock(5, 3);
NSLog(@"Result: %d", result); // 输出: Result: 8
块在异步编程中非常常见,例如网络请求完成后执行的回调代码。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// 在后台线程执行耗时操作
NSURL *url = [NSURL URLWithString:@"http://example.com/data.json"];
NSData *data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
// 回到主线程,更新 UI
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"Received JSON: %@", jsonString);
});
});
总结与学习资源
- Objective-C 是 C 语言的超集,添加了 Smalltalk 风格的面向对象特性。
- 核心是消息传递 (
[receiver message])。 - 类分为
.h(接口) 和.m(实现)。 - 使用
@property简化属性和方法的声明。 - ARC (自动引用计数) 是现代 OC 的内存管理标准,只需注意避免循环引用。
- 协议 用于定义接口,常用于委托模式。
- 块 是强大的代码片段,常用于异步回调。
学习资源
- 官方文档:Apple Developer Documentation (最权威,但内容较多)
- 书籍:
- Programming with Objective-C (Apple 官方免费电子书)
- Objective-C Programming: The Big Nerd Ranch Guide (经典入门书籍)
- 在线教程:
- Ray Wenderlich (有大量高质量的 Swift 和 OC 教程)
- Stanford CS193p (Stanford 的 iOS 开发课程,有视频和讲义)
- 社区:
- Stack Overflow
- V2EX (objc 板块)
希望这份教程能帮助你顺利入门 Objective-C!
