Objective-C 基础教程
前言
本教程旨在为初学者提供一份系统、全面的 Objective-C 语言入门指南,Objective-C 是 Apple 平台(iOS, macOS, watchOS, tvOS)开发的主要语言,它是在 C 语言的基础上,增加了 Smalltalk 式的消息传递机制,理解这一点是掌握 Objective-C 的关键。

本教程将带您从零开始,逐步了解 Objective-C 的基本概念、语法和编程范式,并最终能够编写简单的 Objective-C 程序。
目录
-
第一章:准备工作与环境搭建
- 1 什么是 Objective-C?
- 2 开发环境:Xcode
- 3 创建第一个项目:Hello World
-
第二章:语言基础 - C 语言的基石
- 1 main 函数与程序入口
- 2 基本数据类型
- 3 变量与常量
- 4 运算符
- 5 控制流语句 (if, for, while, switch)
-
第三章:Objective-C 的核心:面向对象编程
(图片来源网络,侵删)- 1 面向对象思想简介
- 2 类 与对象
- 3 实例变量 与属性
- 4 方法
- 5 消息传递
-
第四章:深入类与对象
- 1 接口 与实现
- 2 对象的创建与初始化
- 3 访问修饰符 (
@public,@private,@protected) - 4 self 和 super 关键字
- 5 点语法
-
第五章:常用数据结构
- 1 字符串 (
NSString) - 2 数组 (
NSArray与NSMutableArray) - 3 字典 (
NSDictionary与NSMutableDictionary) - 4 集合 (
NSSet与NSMutableSet)
- 1 字符串 (
-
第六章:内存管理
- 1 手动引用计数
- 2 自动引用计数
- 3
@property的内存管理修饰符 (strong,weak,copy,assign) - 4 循环引用问题与解决方案
-
第七章:协议 与分类
(图片来源网络,侵删)- 1 协议 - 定义行为接口
- 2 分类 - 为现有类添加方法
-
第八章:块
- 1 什么是块?
- 2 块的语法与使用
- 3 块与变量捕获
-
第九章:实战演练:一个简单的计算器类
- 1 设计
Calculator类 - 2 编写代码
- 3 测试功能
- 1 设计
-
第十章:总结与进阶
- 1 本教程回顾
- 2 推荐学习资源
- 3 下一步:学习 Cocoa Touch / Cocoa 框架
第一章:准备工作与环境搭建
1 什么是 Objective-C?
Objective-C(简称 OC)是一套通用的、面向对象的编程语言,它扩展了标准的 ANSI C 语言,添加了面向对象的能力,它的语法独特,使用方括号 [] 来发送消息,[myObject doSomething],这种消息传递机制是 OC 的核心。
2 开发环境:Xcode
要进行 Objective-C 开发,您需要 Apple 官方的集成开发环境 Xcode,它包含了代码编辑器、编译器、调试器、模拟器以及 Interface Builder(用于构建用户界面)。
- 下载地址:Mac App Store (搜索 "Xcode")
- 注意:Xcode 仅在 macOS 系统上运行。
3 创建第一个项目:Hello World
- 打开 Xcode,选择 "Create a new Xcode project"。
- 选择 "macOS" -> "Command Line Tool",然后点击 "Next"。
- 为产品命名(
HelloWorld),语言选择 Objective-C,然后点击 "Next"。 - 选择一个位置保存项目,点击 "Create"。
您会看到一个项目结构,找到 main.m 文件,这是程序的入口点,我们将在下一章详细讲解它。
第二章:语言基础 - C 语言的基石
Objective-C 是 C 的超集,因此所有 C 语言的特性在 OC 中都适用。
1 main 函数与程序入口
main.m 文件的内容如下:
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[]) {
@autoreleasepool {
// 程序代码
NSLog(@"Hello, World!");
}
return 0;
}
#import <Foundation/Foundation.h>:导入 Foundation 框架,Foundation 包含了 OC 的基本类(如字符串、数组等)和运行时支持。#import和#include类似,但它能自动防止重复导入。int main(...):标准的 C 程序入口函数。@autoreleasepool { ... }:自动释放池,所有创建的对象都应该放在一个自动释放池中,以便系统能够及时回收内存。NSLog(@"Hello, World!");:在控制台打印日志。 表示一个 OC 字符串。NSLog会自动在输出后添加时间戳和换行符。
点击 Xcode 的运行按钮(▶️),您将在控制台看到输出:2025-10-27 10:30:00.123 HelloWorld[12345:67890] Hello, World!
2 基本数据类型
int: 整数float: 单精度浮点数double: 双精度浮点数char: 字符BOOL: 布尔值,值为YES或NO(本质上是1和0)。
int myAge = 30; float price = 19.99f; BOOL isStudent = YES;
3 变量与常量
- 变量:使用
const关键字声明。const int MAX_AGE = 100; // MAX_AGE = 101; // 错误!常量不能修改。
- 宏:预处理指令,用于文本替换。
#define PI 3.14159
4 运算符
与 C 语言相同,包括:
- 算术运算符:, , , ,
- 比较运算符:, ,
>,<,>=,<= - 逻辑运算符:
&&(与), (或), (非) - 赋值运算符:, , , 等等
5 控制流语句
- if-else
if (age >= 18) { NSLog(@"You are an adult."); } else { NSLog(@"You are a minor."); } - for 循环
for (int i = 0; i < 5; i++) { NSLog(@"Count: %d", i); } - while 循环
int count = 0; while (count < 5) { NSLog(@"While count: %d", count); count++; }
第三章:Objective-C 的核心:面向对象编程
面向对象编程是一种编程范式,它使用“对象”这一概念来组织和构建程序。
1 面向对象思想简介
- 类:创建对象的蓝图或模板,它定义了对象的属性(数据)和行为(方法)。
- 对象:类的实例,是真实世界事物的抽象,拥有类中定义的属性和行为。
2 类 与对象
想象一个 Dog 类。
- 类 (Dog):定义了所有狗都有的属性(名字、颜色)和行为(叫、跑)。
- 对象 (myDog):一个具体的狗,比如名字叫 "旺财",颜色是 "黄色"。
3 实例变量 与属性
- 实例变量:存储对象数据的变量,通常在类的实现部分声明,对外部不可见(封装)。
- 属性:一种特殊的实例变量,通过
@property关键字声明,它自动生成 getter 和 setter 方法,并提供了对实例变量的安全访问。
4 方法
定义对象行为的函数,OC 中的方法分为两种:
- 实例方法:以 开头,作用于对象实例,可以访问实例变量。
- 类方法:以 开头,作用于类本身,不能访问实例变量,通常用于创建对象或提供工具性功能。
// 实例方法
- (void)bark {
NSLog(@"Woof! Woof!");
}
// 类方法
+ (instancetype)dogWithName:(NSString *)name {
// ... 创建并返回一个 Dog 对象
}
5 消息传递
这是 OC 的精髓,我们不是直接“调用”一个对象的方法,而是向该对象“发送一条消息”。
- 语法:
[接收者 消息] - 示例:
Dog *myDog = [[Dog alloc] init]; // 创建 Dog 对象 [myDog bark]; // 向 myDog 对象发送 bark 消息
这行代码的含义是:请
myDog这个对象执行bark这个方法。
第四章:深入类与对象
1 接口 与实现
一个类通常由两个文件组成:
- 头文件 (
.h):类的接口,声明类的公共部分,包括属性、方法签名,它告诉外界“这个类能做什么”。 - 实现文件 (
.m):类的实现,提供属性和方法的具体代码,它告诉外界“这个类是如何做到的”。
Dog.h (接口)
#import <Foundation/Foundation.h> // @interface ... @end 定义类的接口 @interface Dog : NSObject // Dog 继承自 NSObject,所有 OC 类的基类 @property (nonatomic, copy) NSString *name; // 属性声明 // 方法声明 - (void)bark; - (void)run; @end
Dog.m (实现)
#import "Dog.h"
// @implementation ... @end 定义类的实现
@implementation Dog
// 方法实现
- (void)bark {
NSLog(@"%@ says: Woof!", self.name); // self 指向当前对象
}
- (void)run {
NSLog(@"%@ is running!", self.name);
}
@end
2 对象的创建与初始化
创建对象并调用初始化方法的标准格式:
ClassName *objectName = [[ClassName alloc] init];
alloc:分配内存,创建一个对象。init:初始化对象,设置其初始状态。
Dog *myDog = [[Dog alloc] init]; myDog.name = @"旺财"; [myDog bark]; // 输出: 旺财 says: Woof!
3 访问修饰符
@public: 任何地方都可以访问。@protected: 默认值,只有该类及其子类可以访问。@private: 只有该类本身可以访问。@package: 在同一个框架内可以访问。
现代 OC 开发更倾向于使用 @property 和访问控制来达到封装的目的,而不是直接声明 @public 的实例变量。
4 self 和 super 关键字
self:指代当前正在执行方法的对象实例,相当于 C++/Java 中的this。super:指代当前对象的父类,用于调用父类的方法。
@implementation Dog
- (void)someMethod {
[self bark]; // 调用 Dog 类的 bark 方法
[super init]; // 调用父类 NSObject 的 init 方法
}
@end
5 点语法
点语法是访问 @property 的便捷方式,它让代码看起来更像访问成员变量。
- 点语法的本质:它仍然是方法调用!
object.property = value;等同于[object setProperty:value];value = object.property;等同于value = [object property];
Dog *myDog = [[Dog alloc] init]; // 使用点语法 myDog.name = @"旺财"; // 等同于使用方法调用 [myDog setName:@"旺财"]; NSLog(@"%@", myDog.name); // 输出: 旺财
第五章:常用数据结构
Foundation 框架提供了丰富的集合类。
1 字符串 (NSString)
不可变字符串,创建后内容不能改变。
NSString *greeting = @"Hello"; NSString *name = @"Alice"; NSString *message = [greeting stringByAppendingFormat:@", %@!", name]; NSLog(@"%@", message); // 输出: Hello, Alice!
2 数组 (NSArray 与 NSMutableArray)
NSArray: 不可变数组,创建后,元素数量和内容都不能改变。NSMutableArray: 可变数组,可以添加、删除、修改元素。
// NSArray NSArray *immutableArray = @[@"Apple", @"Banana", @"Cherry"]; NSLog(@"First fruit: %@", [immutableArray objectAtIndex:0]); // 索引从0开始 NSLog(@"First fruit: %@", immutableArray[0]); // 使用现代语法 // NSMutableArray NSMutableArray *mutableArray = [NSMutableArray arrayWithArray:immutableArray]; [mutableArray addObject:@"Date"]; NSLog(@"Mutable array: %@", mutableArray);
3 字典 (NSDictionary 与 NSMutableDictionary)
键值对集合。
NSDictionary: 不可变字典。NSMutableDictionary: 可变字典。
// NSDictionary
NSDictionary *person = @{
@"name": @"Bob",
@"age": @30, // NSNumber对象
@"city": @"New York"
};
NSLog(@"Name: %@", person[@"name"]);
// NSMutableDictionary
NSMutableDictionary *mutableDict = [NSMutableDictionary dictionaryWithDictionary:person];
[mutableDict setObject:@"Engineer" forKey:@"job"];
NSLog(@"Mutable dict: %@", mutableDict);
4 集合 (NSSet 与 NSMutableSet)
无序的、不包含重复元素的集合。
NSSet *uniqueNumbers = [NSSet setWithObjects:@1, @2, @3, @2, nil]; NSLog(@"Count: %lu", (unsigned long)uniqueNumbers.count); // 输出: 3
第六章:内存管理
在 OC 中,对象存储在堆上,需要手动或自动管理其生命周期。
1 手动引用计数
这是旧 OC 的方式,每个对象都有一个“引用计数器”,记录有多少个指针指向它。
alloc,new,copy,mutableCopy: 计数器 +1。retain: 计数器 +1。release: 计数器 -1。- 当计数器变为 0 时,对象被销毁,内存被回收。
// MRC 示例 (现代开发不常用) Person *p1 = [[Person alloc] init]; // retainCount = 1 Person *p2 = [p1 retain]; // retainCount = 2 [p1 release]; // retainCount = 1 [p2 release]; // retainCount = 0, p1 和 p2 被销毁
2 自动引用计数
现代 OC 开发必须使用 ARC,编译器在编译时自动插入 retain, release, autorelease 代码,开发者无需手动管理,规则是:
- 谁创建,谁释放 (
alloc,new,copy,mutableCopy的结果)。 - 谁
retain,谁release。 @property会自动处理 getter/setter 的内存管理。
3 @property 的内存管理修饰符
这些修饰符告诉编译器如何自动生成 setter 方法。
| 修饰符 | 含义 | 适用场景 |
|---|---|---|
strong |
强引用,持有对象,使其计数器+1。 | 对象类型(NSString, NSArray, 自定义类等),默认值。 |
weak |
弱引用,不持有对象,对象销毁时自动置为 nil。 |
避免循环引用,如 delegate、outlet 连接。 |
copy |
复制对象,持有的是传入对象的副本。 | 可变对象(如 NSMutableString),防止外部修改影响内部。 |
assign |
简单赋值,不持有对象,不改变计数器。 | 基本数据类型(int, float, BOOL)和 weak 的旧语法。 |
@interface Person : NSObject @property (nonatomic, strong) NSString *name; // name 是强引用 @property (nonatomic, weak) id delegate; // delegate 是弱引用,防止循环引用 @end
4 循环引用问题与解决方案
当两个对象互相强引用时,它们的引用计数永远不会降为 0,导致内存泄漏。
错误示例:
@interface A : NSObject @property (nonatomic, strong) B *b; @end @interface B : NSObject @property (nonatomic, strong) A *a; @end // ... 创建 A 和 B 并互相赋值,它们将永远不会被释放。
解决方案:
将其中一方的引用改为 weak,通常是“拥有者”强引用“被拥有者”,“被拥有者”用 weak 引用“拥有者”以避免循环。
第七章:协议 与分类
1 协议 - 定义行为接口
协议定义了一组方法,但不实现它们,任何类都可以遵循协议,并实现协议中定义的方法,类似于 Java 的接口或 C++ 的纯虚类。
MyProtocol.h
#import <Foundation/Foundation.h> @protocol MyProtocol <NSObject> // 遵循 NSObject 协议 @required // 必须实现的方法 - (void)requiredMethod; @optional // 可选实现的方法 - (void)optionalMethod; @end
MyClass.h
#import <Foundation/Foundation.h> #import "MyProtocol.h" @interface MyClass : NSObject <MyProtocol> // 遵循 MyProtocol @end
MyClass.m
#import "MyClass.h"
@implementation MyClass
- (void)requiredMethod {
NSLog(@"Required method is implemented.");
}
// 可以选择不实现 optionalMethod
@end
2 分类 - 为现有类添加方法
分类允许您为已存在的类(即使您没有源代码,如 NSString)添加新的方法,这不会影响原有类的实现。
NSString+Utilities.h
#import <Foundation/Foundation.h> // 为 NSString 类添加一个分类 @interface NSString (Utilities) - (BOOL)isValidEmail; // 检查字符串是否是有效的邮箱格式 @end
NSString+Utilities.m
#import "NSString+Utilities.h"
@implementation NSString (Utilities)
- (BOOL)isValidEmail {
// ... 实现邮箱验证逻辑
return [self containsString:@"@"];
}
@end
在任何地方,您都可以对 NSString 对象调用 isValidEmail 方法。
第八章:块
块是 C 语言级别的特性,可以看作是“可以执行的代码片段”或“匿名函数”,它在 OC 中被广泛用于异步编程、动画和集合操作。
1 什么是块?
块是一个对象,可以存储在变量中,作为参数传递,或者作为返回值。
2 块的语法与使用
语法:^ 后面跟着参数列表、返回类型和大括号内的代码。
// 1. 定义一个块变量
void (^simpleBlock)() = ^{
NSLog(@"This is a simple block.");
};
// 2. 执行这个块
simpleBlock();
// 3. 带参数和返回值的块
int (^addBlock)(int, int) = ^(int a, int b) {
return a + b;
};
int sum = addBlock(5, 3);
NSLog(@"Sum: %d", sum); // 输出: Sum: 8
3 块与变量捕获
块可以“捕获”其定义作用域内的变量,默认情况下,捕获的是变量的常量副本,意味着在块内不能修改。
int x = 100;
void (^capturingBlock)() = ^{
// NSLog(@"x is %d", x); // 可以读取 x
// x = 200; // 编译错误!默认情况下不能修改。
};
如果需要在块内修改变量,必须在变量声明时加上 __block 修饰符。
__block int y = 100;
void (^modifyingBlock)() = ^{
y = 200; // 可以修改 y
NSLog(@"y is now %d", y);
};
modifyingBlock();
NSLog(@"y is %d", y); // 输出: y is 200
第九章:实战演练:一个简单的计算器类
让我们创建一个 Calculator 类,它能够执行基本的加、减、乘、除运算。
1 设计 Calculator 类
- 属性:
double result:存储当前的计算结果。
- 方法:
- (void)add:(double)operand- (void)subtract:(double)operand- (void)multiply:(double)operand- (void)divide:(double)operand- (void)clear
2 编写代码
Calculator.h
#import <Foundation/Foundation.h> @interface Calculator : NSObject @property (nonatomic, assign) double result; - (void)add:(double)operand; - (void)subtract:(double)operand; - (void)multiply:(double)operand; - (void)divide:(double)operand; - (void)clear; @end
Calculator.m
#import "Calculator.h"
@implementation Calculator
- (void)add:(double)operand {
self.result += operand;
}
- (void)subtract:(double)operand {
self.result -= operand;
}
- (void)multiply:(double)operand {
self.result *= operand;
}
- (void)divide:(double)operand {
if (operand != 0) {
self.result /= operand;
} else {
NSLog("Error: Division by zero.");
}
}
- (void)clear {
self.result = 0;
}
@end
3 测试功能
在 main.m 中测试我们的 Calculator 类。
#import <Foundation/Foundation.h>
#import "Calculator.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Calculator *myCalculator = [[Calculator alloc] init];
NSLog(@"Initial result: %f", myCalculator.result);
[myCalculator add:10];
NSLog(@"After adding 10: %f", myCalculator.result);
[myCalculator multiply:2.5];
NSLog(@"After multiplying by 2.5: %f", myCalculator.result);
[myCalculator subtract:5];
NSLog(@"After subtracting 5: %f", myCalculator.result);
[myCalculator divide:2];
NSLog(@"After dividing by 2: %f", myCalculator.result);
[myCalculator clear];
NSLog(@"After clearing: %f", myCalculator.result);
}
return 0;
}
运行程序,您将看到计算器按预期工作。
第十章:总结与进阶
1 本教程回顾
本教程涵盖了 Objective-C 的核心基础,包括:
- 开发环境与项目结构
- C 语言基础
- 面向对象编程思想与核心语法
- Foundation 框架中的常用类
- 现代内存管理
- 协议、分类和块等高级特性
掌握了这些知识,您已经具备了使用 Objective-C 进行开发的基础。
2 推荐学习资源
- 官方文档:Apple Developer Documentation 是最权威、最准确的资料。
- 书籍:
- Programming with Objective-C (Apple 官方电子书,免费)
- Objective-C Programming: The Big Nerd Ranch Guide
- 在线课程:Coursera, Udemy, Ray Wenderlich 等平台上有大量高质量的 iOS/macOS 开发课程。
3 下一步:学习 Cocoa Touch / Cocoa 框架
语言只是工具,真正的开发离不开框架,Objective-C 主要用于开发 Apple 平台的应用。
- Cocoa Touch:用于开发 iOS 和 watchOS 应用,核心框架包括
UIKit(用户界面)、Foundation(基础类)等。 - Cocoa:用于开发 macOS 应用,核心框架包括
AppKit(用户界面)、Foundation等。
下一步,您应该开始学习如何使用 UIKit 或 AppKit 来构建用户界面,处理用户交互,并与系统进行更深入的交互,祝您学习愉快!
