首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

Objective-C 基礎筆記(五):Protocol 與委託模式詳解——從 Android 對比到 iOS 實戰

     編輯:關於C語言

Objective-C 基礎筆記(五):Protocol 與委託模式詳解——從 Android 對比到 iOS 實戰

Protocol(協議) 本質是一組方法清單,聲明了「能做什麼」,不關心「怎麼做」。任何類別只要實現協議中的方法,就宣稱遵循該協議。在 iOS/macOS 開發中,Apple 大量採用委託模式解耦 View 與 Controller,這正是 Protocol 的經典應用場景。

從熟悉的 Android 點擊監聽說起

Android 中按鈕點擊採用介面回調:

// 1. 定義介面
public interface OnClickListener {
    void onClick(View v);
}

// 2. View 持有介面引用
public void setOnClickListener(OnClickListener l) {
    if (!isClickable()) setClickable(true);
    getListenerInfo().mOnClickListener = l;
}

// 3. Activity 實現介面並註冊
button.setOnClickListener(new OnClickListener() {
    @Override public void onClick(View v) { ... }
});

核心機制:View 內部維護 ListenerInfo 對象,將監聽器保存;事件分發時調用 onClick。這是典型的「介面+回調」解耦。

iOS 中的對應:Protocol + Delegate

Objective-C 用 @protocol 定義協議,用 id<Protocol> 持有委託對象,respondsToSelector: 動態檢查方法實現——這比 Java 介面更靈活(可選方法、運行時檢查)。

完整 Demo:自定義 Button 與雙重委託

Button.h —— 定義兩個協議與委託屬性

#import <Foundation/Foundation.h>
@class Button;

@protocol ButtonDelegate <NSObject>
- (void)onClick:(Button *)btn;
@end

@protocol ButtonLongClickDelegate <NSObject>
- (void)onLongClick:(Button *)btn;
@end

@interface Button : NSObject
@property (nonatomic, retain) id<ButtonDelegate> delegate;
@property (nonatomic, retain) id<ButtonLongClickDelegate> longClickDelegate;
// 模擬系統觸發
- (void)click;
- (void)longClick;
@end

Button.m —— 觸發時安全調用

#import "Button.h"

@implementation Button
- (void)click {
    if ([_delegate respondsToSelector:@selector(onClick:)]) {
        [_delegate onClick:self];
    } else {
        NSLog(@"onClick 委託未實現");
    }
}
- (void)longClick {
    if ([_longClickDelegate respondsToSelector:@selector(onLongClick:)]) {
        [_longClickDelegate onLongClick:self];
    } else {
        NSLog(@"longClick 委託未實現");
    }
}
- (void)dealloc {
    [_delegate release];
    [_longClickDelegate release];
    [super dealloc];
}
@end

委託實現類(分離關注點)

// ButtonListener.m
- (void)onClick:(Button *)btn { NSLog(@"按鈕被點擊了"); }

// ButtonLongClickListener.m
- (void)onLongClick:(Button *)btn { NSLog(@"按鈕被長按了"); }

Main.m —— 組裝

int main() {
    @autoreleasepool {
        Button *button = [[[Button alloc] init] autorelease];
        ButtonListener *listener = [[[ButtonListener alloc] init] autorelease];
        ButtonLongClickListener *longListener = [[[ButtonLongClickListener alloc] init] autorelease];

        button.delegate = listener;
        button.longClickDelegate = longListener;

        [button click];      // 輸出:按鈕被點擊了
        [button longClick];  // 輸出:按鈕被長按了
    }
    return 0;
}

關鍵差異對比表

維度Android (Interface)iOS (Protocol + Delegate)
定義方式interface 關鍵字@protocol 指令
方法屬性全部強制實現(Java 8 前)可標記 @optional,運行時用 respondsToSelector: 判斷
持有引用強引用(需注意洩漏)通常 weak/assign 避免循環引用
多委託單介面多方法或多介面多個 @protocol + 多個 delegate 屬性

最佳實踐提醒

  • 委託屬性務必用 weak (ARC) 或 assign (MRC) 打破循環引用。
  • 協議繼承 <NSObject> 可獲得 respondsToSelector: 等基礎方法。
  • 協議方法命名建議帶上發送者參數(如 (Button *)btn),方便委託識別來源。

通過對比 Android 介面回調與 iOS Protocol/Delegate,可以清晰看到兩種平台對「解耦」的不同哲學:前者靠靜態類型檢查,後者靠動態消息轉發。理解這一點,能幫助你在跨平台架構設計時做出更合理的抽象決策。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved