iOS Delegate模式

文章目录

  • [一、 Delegate 模式的概念](#一、 Delegate 模式的概念)
  • [二、Delegate 的实现步骤](#二、Delegate 的实现步骤)
    • [步骤 1: 定义一个协议(Protocol)](#步骤 1: 定义一个协议(Protocol))
    • [步骤 2: 在主类中添加一个 delegate 属性](#步骤 2: 在主类中添加一个 delegate 属性)
    • [步骤 3: 实现协议的类遵守协议并实现方法](#步骤 3: 实现协议的类遵守协议并实现方法)
    • [步骤 4: 设置 delegate](#步骤 4: 设置 delegate)
  • [三、Delegate 模式的特点](#三、Delegate 模式的特点)
  • [四、Delegate 模式的常见场景](#四、Delegate 模式的常见场景)
    • [1. 视图控制器与视图组件之间的通信](#1. 视图控制器与视图组件之间的通信)
    • [2. 处理用户输入事件](#2. 处理用户输入事件)
    • [3. 自定义控件的回调](#3. 自定义控件的回调)
    • [4. 事件的传递与回调](#4. 事件的传递与回调)
    • [5. 解耦设计](#5. 解耦设计)
    • [6. 常见框架与委托](#6. 常见框架与委托)

一、 Delegate 模式的概念

  • 核心思想:一个对象定义协议(Protocol),让其他对象遵守协议并实现相关方法,最终将任务交给这些对象完成。
  • 使用场景:实现对象之间的事件回调、数据传递 和 解耦。

二、Delegate 的实现步骤

步骤 1: 定义一个协议(Protocol)

协议中声明了需要实现的方法。

objectivec 复制代码
@protocol MyDelegate <NSObject>
- (void)taskDidComplete;  // 定义协议方法
@end

步骤 2: 在主类中添加一个 delegate 属性

主类通过 weak 引用委托对象,避免循环引用。

objectivec 复制代码
@interface MyClass : NSObject
@property (nonatomic, weak) id<MyDelegate> delegate;  // 弱引用
- (void)startTask;
@end

@implementation MyClass
- (void)startTask {
    NSLog(@"Task is starting...");
    // 模拟任务完成
    [self.delegate taskDidComplete];  // 调用委托对象的方法
}
@end

步骤 3: 实现协议的类遵守协议并实现方法

其他类通过遵守 MyDelegate 协议来实现任务。

objectivec 复制代码
@interface AnotherClass : NSObject <MyDelegate>
@end

@implementation AnotherClass
- (void)taskDidComplete {
    NSLog(@"Task completed! Delegate notified.");
}
@end

步骤 4: 设置 delegate

主类通过 delegate 属性与实现类建立连接。

objectivec 复制代码
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        MyClass *myClass = [[MyClass alloc] init];
        AnotherClass *anotherClass = [[AnotherClass alloc] init];
        
        myClass.delegate = anotherClass;  // 设置委托对象
        [myClass startTask];  // 触发任务
    }
    return 0;
}

输出:

objectivec 复制代码
Task is starting...
Task completed! Delegate notified.

三、Delegate 模式的特点

  • 解耦:实现者(委托对象)和调用者(主类)分离,降低耦合度。
  • 灵活性:不同的对象可以遵守协议,实现不同的逻辑。
  • 单向通信:委托对象实现协议方法,主类通过调用这些方法实现通信。

四、Delegate 模式的常见场景

1. 视图控制器与视图组件之间的通信

在 iOS 中,视图组件(如 UITableView、UITextField)通过 Delegate 与控制器通信,传递事件和数据。

示例:UITableView 的 Delegate 和 DataSource

UITableView 的事件(例如单元格选中、滚动)通过 UITableViewDelegate 和 UITableViewDataSource 协议回调到控制器中。

objectivec 复制代码
@interface ViewController () <UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong) UITableView *tableView;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.tableView = [[UITableView alloc] initWithFrame:self.view.bounds];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    [self.view addSubview:self.tableView];
}

// UITableViewDataSource 方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 10; // 返回行数
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if (!cell) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
    }
    cell.textLabel.text = [NSString stringWithFormat:@"Row %ld", (long)indexPath.row];
    return cell;
}

// UITableViewDelegate 方法
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"Selected row: %ld", (long)indexPath.row);
}
@end

2. 处理用户输入事件

委托模式在输入控件(如 UITextField 和 UITextView)中广泛使用,用于处理用户输入。

objectivec 复制代码
@interface ViewController () <UITextFieldDelegate>
@property (nonatomic, strong) UITextField *textField;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.textField = [[UITextField alloc] initWithFrame:CGRectMake(50, 100, 200, 40)];
    self.textField.borderStyle = UITextBorderStyleRoundedRect;
    self.textField.delegate = self;
    [self.view addSubview:self.textField];
}

// UITextFieldDelegate 方法
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder]; // 隐藏键盘
    return YES;
}
@end

3. 自定义控件的回调

在开发自定义控件时,可以定义一个 delegate,让外部类(通常是视图控制器)实现回调方法,处理控件的行为。

示例:自定义控件

objectivec 复制代码
@protocol CustomViewDelegate <NSObject>
- (void)customViewButtonWasTapped;
@end

@interface CustomView : UIView
@property (nonatomic, weak) id<CustomViewDelegate> delegate;
@end

@implementation CustomView
- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        UIButton *button = [[UIButton alloc] initWithFrame:CGRectMake(50, 50, 100, 50)];
        [button setTitle:@"Tap Me" forState:UIControlStateNormal];
        [button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
        [button addTarget:self action:@selector(buttonTapped) forControlEvents:UIControlEventTouchUpInside];
        [self addSubview:button];
    }
    return self;
}

- (void)buttonTapped {
    [self.delegate customViewButtonWasTapped];
}
@end

使用自定义控件:

objectivec 复制代码
@interface ViewController () <CustomViewDelegate>
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    CustomView *customView = [[CustomView alloc] initWithFrame:self.view.bounds];
    customView.delegate = self;
    [self.view addSubview:customView];
}

// CustomViewDelegate 方法
- (void)customViewButtonWasTapped {
    NSLog(@"Button was tapped in custom view.");
}
@end

4. 事件的传递与回调

在对象之间需要传递事件或执行回调时,Delegate 是一种常用方案。

  • 例如:网络请求完成后,将结果返回给调用者。
  • 例如:任务完成通知某个对象。

5. 解耦设计

Delegate 可以用于降低对象之间的耦合度。例如:

  • UITableView 和其数据源分离,控制器实现协议方法,而 UITableView 并不知道具体实现。
  • MVC 架构中,Controller 与 View 通过 Delegate 通信,解耦逻辑与界面代码。

6. 常见框架与委托

  • UITableViewDelegate / UITableViewDataSource:表格视图事件与数据源回调。
  • UICollectionViewDelegate / UICollectionViewDataSource:集合视图的数据源与事件处理。
  • UITextFieldDelegate:文本输入控件的事件回调。
  • NSURLSessionDelegate:网络请求结果的回调。
  • CLLocationManagerDelegate:位置服务的事件回调。

最佳实践:对于单一事件回调,推荐使用 Block,而对于复杂逻辑、多方法回调,使用 Delegate 模式更合适。

相关推荐
冬奇Lab20 小时前
一天一个开源项目(第46篇):Caddy - 自动 HTTPS 的现代化 Web 服务器,支持 HTTP/3
网络协议·nginx·开源
吴佳浩2 天前
OpenClaw macOS 完整安装与本地模型配置教程(实战版)
人工智能·macos·agent
开心就好20252 天前
iOS App 安全加固流程记录,代码、资源与安装包保护
后端·ios
开心就好20252 天前
iOS App 性能测试工具怎么选?使用克魔助手(Keymob)结合 Instruments 完成
后端·ios
zhongjiahao3 天前
面试常问的 RunLoop,到底在Loop什么?
ios
Sheffield4 天前
Docker的跨主机服务与其对应的优缺点
linux·网络协议·docker
wvy4 天前
iOS 26手势返回到根页面时TabBar的动效问题
ios
RickeyBoy4 天前
iOS 图片取色完全指南:从像素格式到工程实践
ios
aiopencode5 天前
使用 Ipa Guard 命令行版本将 IPA 混淆接入自动化流程
后端·ios
二流小码农5 天前
鸿蒙开发:路由组件升级,支持页面一键创建
android·ios·harmonyos