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
相关推荐
TheNextByte14 小时前
如何将 iPhone 备份到外置硬盘?
ios·iphone
佛系打工仔4 小时前
绘制K线第三章:拖拽功能实现
android·前端·ios
游戏开发爱好者88 小时前
2025年iOS应用上架App Store全指南,开发者必看
android·ios·小程序·https·uni-app·iphone·webview
HH思️️无邪8 小时前
Flutter 项目 -从 0 到 1 实现 iOS WatchApp
flutter·ios
TheNextByte110 小时前
如何将 iPhone 上的联系人备份到 iCloud?
ios·iphone·icloud
牛马11110 小时前
iOS swift 自定义View
ios·cocoa·swift
2501_9151063210 小时前
HBuilderX 项目上架 iOS app上架 App Store 的关键流程
android·ios·小程序·https·uni-app·iphone·webview
2501_9151063210 小时前
iOS 文件管理,在不越狱的前提下管理 iPhone / iPad 文件
android·ios·小程序·uni-app·iphone·webview·ipad
牛马11110 小时前
ios swift处理json数据
ios·json·swift
黑码哥10 小时前
iOS开屏广告多机型屏幕适配最佳实践
macos·ios·cocoa·广告·商业·开屏广告