iOS 开发:Objective-C 之分类及协议

在 Objective-C 中,分类 (Category)协议 (Protocol) 是实现代码解耦、扩展功能和组件化开发的核心工具。


一、 分类 (Category)

分类 允许你在不修改原始类代码、不使用继承的情况下,动态地为现有的类添加新方法。

1. 核心作用

  • 扩展系统类 :给 NSString, NSArray 等添加自定义工具方法。
  • 分解大型类 :将一个庞大的 .m 文件按功能拆分成多个小文件(如 User+Login.m, User+Profile.m)。

2. 代码案例:给 NSString 增加一个校验邮箱的功能

NSString+Email.h (声明)

objectivec 复制代码
#import <Foundation/Foundation.h>

@interface NSString (Email)
// 声明一个新方法
- (BOOL)isEmailFormat;
@end

NSString+Email.m (实现)

objectivec 复制代码
#import "NSString+Email.h"

@implementation NSString (Email)
- (BOOL)isEmailFormat {
    NSString *emailRegex = @"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}";
    NSPredicate *emailTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", emailRegex];
    return [emailTest evaluateWithObject:self];
}
@end

使用方法:

objectivec 复制代码
#import "NSString+Email.h"

NSString *myMail = @"test@example.com";
if ([myMail isEmailFormat]) {
    NSLog(@"这是一个有效的邮箱");
}

3. 注意事项

  • 只能添加方法,不能添加成员变量(可以通过"关联对象"实现,但属于进阶内容)。
  • 方法覆盖 :如果分类中的方法名与原类重复,分类的方法会"覆盖"原类。建议分类方法名加上前缀(如 my_isEmailFormat)。

二、 协议 (Protocol)

协议 定义了一套方法列表,但不负责实现。任何类都可以声明"遵守"这个协议并实现其中的方法。它类似于 Java 或 C# 中的 Interface(接口)

1. 核心关键字

  • @required必须实现的方法(默认)。
  • @optional可选实现的方法。

2. 代码案例:定义一个"管家"协议

HouseKeeperProtocol.h

objectivec 复制代码
#import <Foundation/Foundation.h>

@protocol HouseKeeperProtocol <NSObject>

@required
- (void)cleanRoom; // 必须打扫房间

@optional
- (void)cookDinner; // 可以选择是否做饭

@end

Person.h (类声明遵守协议)

objectivec 复制代码
#import "HouseKeeperProtocol.h"

// 在类名后用 <> 表示遵守协议
@interface Person : NSObject <HouseKeeperProtocol>
@end

Person.m (实现协议方法)

objectivec 复制代码
@implementation Person

- (void)cleanRoom {
    NSLog(@"正在用吸尘器打扫...");
}

// cookDinner 是可选的,可以不写
@end

三、 协议的高级用法:委托模式 (Delegate)

这是协议在 iOS 开发中最常用的场景(如 TableView 的点击事件)。

objectivec 复制代码
// 1. 定义协议
@protocol DownloadDelegate <NSObject>
- (void)downloadDidFinish:(NSString *)filePath;
@end

// 2. 在下载器类中定义 delegate 属性
@interface Downloader : NSObject
@property (nonatomic, weak) id<DownloadDelegate> delegate; 
- (void)start;
@end

@implementation Downloader
- (void)start {
    NSLog(@"下载中...");
    // 3. 通知代理对象
    if ([self.delegate respondsToSelector:@selector(downloadDidFinish:)]) {
        [self.delegate downloadDidFinish:@"/path/to/file"];
    }
}
@end

四、 分类 vs 协议:怎么选?

特性 分类 (Category) 协议 (Protocol)
主要目的 扩展:给现有类增加功能 规范:定义一套行为准则
方法实现 必须在分类的 .m 中实现 协议本身不实现,由遵守它的类实现
状态存储 不允许添加成员变量 不涉及变量,只涉及方法
使用场景 比如想给所有 UIButton 加一个抖动动画 比如定义"凡是能飞的物体(鸟、飞机)都要有 fly 方法"

总结

  • 如果你想让某个现有的类"更强大 ",用 Category
  • 如果你想让不同的类"遵守同一种约定 "或者实现"回调通知 ",用 Protocol
相关推荐
懋学的前端攻城狮14 小时前
iOS 列表性能优化实战:从 45fps 到 60fps 的蜕变
ios·性能优化·ui kit
斯班奇的好朋友阿法法14 小时前
鸿蒙 vs iOS vs 微信小程序:开发平台全面对比
ios·微信小程序·harmonyos
@大迁世界1 天前
14个你现在必须关闭的 iOS 26 设置,不然手机很快被它榨干
macos·ios·智能手机·objective-c·cocoa
YJlio2 天前
10.2.8 以其他账户运行服务(Running services in alternate accounts):为什么“把服务切到某个用户账号下运行”,本质上是在改变服务的整个安全上下文?
python·安全·ios·机器人·django·iphone·7-zip
pop_xiaoli2 天前
【iOS】KVC与KVO
笔记·macos·ios·objective-c·cocoa
90后的晨仔2 天前
《swiftUI进阶 第10章:现代状态管理(iOS 17+)》
ios
sakiko_2 天前
UIKit学习笔记4-使用UITableView制作滚动视图
笔记·学习·ios·swift·uikit
小锋学长生活大爆炸2 天前
【开源软件】这次iPhone也是用上Claw了 | PhoneClaw
ios·开源软件·iphone·claw
SameX2 天前
独立开发一个把走过的路变成 km² 的 App,聊聊 25m 网格和后台 GPS 的坑
ios
XD7429716362 天前
科技早报晚报|2026年4月30日:Agent 安全壳、浏览器 iOS 测试台与可穿戴数据 API,今天更值得看的 3 个技术机会
科技·ios·开源项目·科技新闻·开发者工具