「iOS」————單例與代理

iOS學習

  • 單例
  • 代理
      • 代理模式的原理
      • 代理的循環引用
  • 設計模式


單例

優點:

  • 全局訪問:單例模式確保一個類只有一個實例,并提供全局訪問點,方便在整個應用中共享數據或功能。
  • 節省資源:由于只創建一個實例,可以減少內存開銷,避免重復創建相同對象。
  • 控制實例化:通過私有構造函數,防止外部代碼創建多個實例,確保數據一致性。

缺點:

  • 隱藏依賴:使用單例可能導致代碼中隱藏的依賴關系,增加了代碼的耦合性,降低了可測試性。
  • 難以擴展:單例模式不易于擴展,若需要改變實例的行為,可能需要修改單例類的代碼。
  • 線程安全問題:在多線程環境下,單例的實現需要特別注意線程安全,若處理不當可能導致數據不一致。

系統為我們提供的單例類:

UIApplication(應用程序實例類)
NSNotificationCenter(消息中心類)
NSFileManager(文件管理類)
NSUserDefaults(應用程序設置)
NSURLCache(請求緩存類)
NSHTTPCookieStorage(應用程序cookies池)

分為懶漢模式和餓漢模式。懶漢模式是需要時創建,餓漢模式是程序啟動時創建,用的時候拿出來

實現單例模式只需要改寫四種方法:alloc init方法,類方法,copy方法,mutable Copy方法。

懶漢模式:

#import "Singletion.h"@implementation Singletion
static id instance = nil;+(instancetype)allocWithZone:(struct _NSZone *)zone
{if(instance == nil) {@synchronized (self) {if(instance == nil) {instance = [super allocWithZone:zone];}}}return instance;
}+(instancetype)mySingletion {if (instance == nil) {@synchronized (self) {instance = [[self alloc] init];}}return instance;
}-(id)copyWithZone:(NSZone *)zone
{return instance;
}-(id)mutableCopyWithZone:(NSZone *)zone
{return instance;
}

餓漢模式:

#import "Singletion.h"@implementation Singletion
static id instance = nil;
//區別就在于以下函數
+ (void)load{instance = [[self alloc] init];
}+(instancetype)mySingletion {if (instance == nil) {@synchronized (self) {instance = [[self alloc] init];}}return instance;
}+(instancetype)allocWithZone:(struct _NSZone *)zone
{if(instance == nil) {@synchronized (self) {if(instance == nil) {instance = [super allocWithZone:zone];}}}return instance;
}-(id)copyWithZone:(NSZone *)zone
{return instance;
}-(id)mutableCopyWithZone:(NSZone *)zone
{return instance;
}

由于多線程的原因,實現真正的單例模式需要加鎖,有以下兩種方法:

加鎖寫法:

+(instancetype)allocWithZone:(struct _NSZone *)zone
{if(instance == nil) {@synchronized (self) {//自旋鎖if(instance == nil) {instance = [super allocWithZone:zone];}}}return instance;
}

GCD寫法:

+ (instancetype)allocWithZone:(struct _NSZone *)zone {static dispatch_once_t onceToken = 0;dispatch_once(&onceToken, ^{instance = [super allocWithZone:zone];});return instance;
}

dispatch_once 主要是根據 onceToken 的值來決定怎么去執行代碼。

1.當 onceToken = 0 時,線程執行 dispatch_once 的 block 中代碼;

2.當 onceToken = -1 時,線程跳過 dispatch_once 的 block 中代碼不執行;

3.當 onceToken 為其他值時,線程被阻塞,等待 onceToken 值改變。

注意:此處使用GCD寫法要好過加鎖寫法。GCD不僅有更小的開銷,更好的性能,同時還不需要手動管理鎖。

代理

協議是多個類(或者對象)之間協商的一個公共接口,提供了一系列方法的聲明給類們使用;代理是協議的一個典型應用機制。代理模式的核心思想就是通過代理接口分離使用者和服務提供者,降低了模塊之間的耦合度。

在這里插入圖片描述

協議的編寫規范:

  1. 一般情況下, 當前協議屬于誰, 我們就將協議定義到誰的頭文件中

  2. 協議的名稱一般以它屬于的那個類的類名開頭, 后面跟上protocol或者delegate

  3. 協議中的方法名稱一般以協議名稱protocol之前的作為開頭

  4. 一般情況下協議中的方法會將觸發該協議的對象傳遞出去

  5. 一般情況下一個類中的代理屬于的名稱叫做 delegate

  6. 當某一個類要成為另外一個類的代理的時候, 一般情況下在.h中用@protocol 協議名稱;告訴當前類 這是一個協議.在.m中用#import真正的導入一個協議的聲明

注意:

  1. 協議不能聲明成員變量,不能寫實現
  2. 只要父類遵守了某個協議,那么子類也遵守
  3. 協議可以遵守協議,一個協議遵守了另一個協議,就可以擁有另一份協議中的方法聲明

協議中有2個關鍵字可以控制方法是否要實現(默認是@required,在大多數情況下,用途在于程序員之間的交流)

  • @required:這個方法必須要實現(若不實現,編譯器會發出警告)
  • @optional:這個方法不一定要實現

代理模式的原理

在iOS中代理的本質就是代理對象內存的傳遞和操作,我們在委托類設置代理對象后,實際上只是用一個id類型的指針將代理對象進行了一個弱引用。委托方讓代理方執行操作,實際上是在委托類中向這個id類型指針指向的對象發送消息,而這個id類型指針指向的對象,就是代理對象。

組成部分:

  1. 協議(Protocol) - 定義了代理需要實現的方法
  2. 委托方(Delegator) - 持有代理對象并在適當時機調用代理方法
  3. 代理方(Delegate) - 實現協議中定義的方法

請添加圖片描述

回顧一下使用:

首先我們定義一個協議,并且設置定義委托方

@protocol SecondViewControllerDelegate <NSObject>- (void)didUpdateText: (NSString *)text;@end@interface SecondViewController : UIViewController//定義委托方
@property (nonatomic, weak) id<SecondViewControllerDelegate> delegate;
@property (nonatomic, strong) UITextField *textField;@end

在委托方的.m文件中,合適的地方觸發委托方法。要注意確保該委托對象實現了委托方法。所以可以使用respondsToSelector:方法進行檢查

- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor lightGrayColor];self.textField = [[UITextField alloc] initWithFrame: CGRectMake(20, 100, 200, 30)];self.textField.center = self.view.center;self.textField.borderStyle = UITextBorderStyleRoundedRect;//self.textField.text = @"placeholder";self.textField.delegate = self;[self.view addSubview: self.textField];
}
//觸發委托方法
- (void)textFieldDidChangeSelection:(UITextField *)textField {if ([self.delegate respondsToSelector: @selector(didUpdateText:)]) {[self.delegate didUpdateText: textField.text];}
}

再定義代理方:首先要遵循委托方的協議。

#import <UIKit/UIKit.h>
#import "SecondViewController.h"@interface FirstViewController : UIViewController <SecondViewControllerDelegate>@property (nonatomic, strong)UITextField* textField;@end

其次要實現委托協議,并且將自己設置會委托方的代理。即.delegare = self。

- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor lightGrayColor];self.textField = [[UITextField alloc] initWithFrame: CGRectMake(20, 100, 200, 30)];self.textField.center = self.view.center;self.textField.borderStyle = UITextBorderStyleRoundedRect;[self.view addSubview: self.textField];UITapGestureRecognizer* tapGesture = [[UITapGestureRecognizer alloc] initWithTarget: self action: @selector(pushSecondController)];[self.view addGestureRecognizer: tapGesture];
}- (void)pushSecondController {SecondViewController* secondViewController = [[SecondViewController alloc] init];//將委托對象(代理)設置為FirstViewControllersecondViewController.delegate = self;[self.navigationController pushViewController: secondViewController animated: YES];
}//實現委托協議
- (void)didUpdateText:(NSString *)text {//協議傳值self.textField.text = text;
}

代理的循環引用

一下代碼會發生代理的循環引用:B強引用A,而A的delegate屬性指向B,這里的delegate是用strong修飾的,所以A也會強引用B。因此,通常情況下,我們都是用弱引用weak來修飾delegate

@protocol ClssADelegate
- (void)eat;
@end@interface ClassA : UIViewController
@property (nonatomic, strong) id  delegate;//改為弱引用weak
@end//ClassB:
@interface ClassB ()
@property (nonatomic, strong) ClassA *classA;
@end@implementation ClassB
- (void)viewDidLoad {[super viewDidLoad];self.classA = [[ClassA alloc] init];self.classA.delegate = self;
}

請添加圖片描述

下面我們看幾種傳值方式的優缺點:

請添加圖片描述

設計模式

此處簡介一下設計模式,后期再繼續補充。

KVO/通知 -------> 觀察者模式

觀察者模式定義了一種一對多的依賴關系,讓多個觀察者對象同時監聽某一個主題對象。這個主題對象在狀態上發生變化時,會通知所有觀察者對象,使它們能夠自動更新自己。
優勢:解耦合
接口隔離原則、開放-封閉原則

KVC --------> KVC模式
單例模式

利用應用程序只有一個該類的實例對象這一特殊性來實現資源共享。
優勢:使用簡單,延時求值,易于跨模塊
劣勢:這塊內存知道程序退出時才能釋放
單一職責原則
舉例:[UIApplication sharedApplication]。

代理模式

委托方將不想完成的任務交給代理方處理,并且需要委托方通知代理方才能處理。
優勢: 解耦合
開放-封閉原則
舉例:tableview的數據源和代理

策略模式

策略模式定義了一系列的算法,并將每一個算法封裝起來,而且使它們還可以相互替換。策略模式讓算法獨立于使用它的客戶而獨立變化。
優勢:使算法的變化獨立于使用算法的用戶
接口隔離原則、多用組合,少用繼承、針對接口編程,而非實現
舉例:賬號密碼輸入格式的判斷、NSArray的sortedArrayUsingSelector等等

MVC模式

將程序書寫分為三層,分別為模型、視圖、控制器,每層都有各自的職責完成各自的工作。
優勢: MVC模式使系統,層次清晰,職責分明,易于維護
對擴展開放-對修改封閉

MVVM模式

用于解決MVC模式下C層代碼冗雜的情況(過多的網絡請求以及業務邏輯處理)而出現的MVVM模式,其相比于MVC多了一層ViweModel(業務處理和數據轉化)層,專門用于處理數據。
當功能簡單時,MVVM反而會增加很多代碼,所以對于簡單的功能,MVC更加的方便。

三種工廠模式

通過給定參數來返回對應的實例,完全對用戶隱藏其實現的原理。
優勢:易于替換,面向抽象編程
依賴倒置原則

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/95072.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/95072.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/95072.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Microsoft Dynamics AX 性能優化解決方案

一、方案背景Microsoft Dynamics AX 是功能強大的企業ERP系統&#xff0c;雖然Microsoft 已推出基于云的現代化 ERP 平臺 Dynamics 365 Finance and Operations&#xff0c;提供了更高的性能和持續更新&#xff0c;用來替代Dynamics AX。在考慮升級到Dynamics 365之前&#xff…

ARM保留的標準中斷處理程序入口和外設中斷處理程序入口介紹

在ARM架構中&#xff0c;中斷處理是一個關鍵機制&#xff0c;它允許CPU在執行主程序時能夠響應外部或內部的事件。對于ARM MCU&#xff08;微控制器單元&#xff09;而言&#xff0c;中斷處理程序入口通常分為兩類&#xff1a;ARM保留的標準中斷處理程序入口和外設中斷處理程序…

防火墻環境下的全網服務器數據自動化備份平臺搭建:基于 rsync 的完整實施指南

一、項目總覽 1.內容介紹 本文以 3 臺 CentOS 7.9 服務器&#xff08;Web 服務器、NFS 服務器、備份服務器&#xff09;為載體&#xff0c;詳解如何在全防火墻開啟的前提下&#xff0c;搭建一套自動化數據備份平臺&#xff1a;每日自動打包 Web 站點、NFS 共享數據及系統關鍵…

Spring之【Import】

目錄 Import注解 源碼分析 使用示例 ImportSelector 源碼分析 使用示例 DeferredImportSelector 源碼分析 使用示例 ImportBeanDefinitionRegistrar 源碼分析 使用示例 Import注解 源碼分析 處理組件類上的Import注解 將Import引入類對應的BeanDefinition對象添加…

RN項目環境搭建和使用-Mac版本(模擬器啟動不起來的排查)

ReactNative&#xff1a; https://github.com/facebook/react-native https://reactnative.cn/docs/getting-started &#xff08;可以先通讀一下這個&#xff09; 環境搭建 &#xff08;mac版&#xff09;https://juejin.cn/post/7404860612758765605 搭建之前確認版本&#x…

懸賞任務系統網站兼職賺錢小程序搭建地推抖音視頻任務拉新源碼功能詳解二開

功能詳解&#xff08;一&#xff09;登錄與注冊1、登錄&#xff1a;打開系統用戶端&#xff0c;輸入已注冊的手機號&#xff0c;若為首次登錄或忘記密碼&#xff0c;可通過 “找回密碼” 功能&#xff0c;按提示驗證身份后重置密碼登錄。 2、注冊&#xff1a;點擊 “注冊” 按鈕…

scikit-learn/sklearn學習|線性回歸解讀

【1】引言 前序學習進程中&#xff0c;對SVM相關的數學原理進行了探索和推導&#xff0c;相關文章鏈接包括且不限于&#xff1a; python學智能算法&#xff08;二十六&#xff09;|SVM-拉格朗日函數構造-CSDN博客 python學智能算法&#xff08;二十八&#xff09;|SVM-拉格朗…

音視頻學習(五十一):AAC編碼器

什么是AAC編碼器&#xff1f; 高級音頻編碼&#xff08;Advanced Audio Coding&#xff0c;簡稱AAC&#xff09; 是一種有損音頻壓縮技術&#xff0c;旨在作為MP3的下一代標準而開發。它的主要目標是在比MP3更低的比特率下提供更好的音質&#xff0c;同時具備更強的靈活性和功能…

10-netty基礎-手寫rpc-定義協議頭-02

netty系列文章&#xff1a; 01-netty基礎-socket02-netty基礎-java四種IO模型03-netty基礎-多路復用select、poll、epoll04-netty基礎-Reactor三種模型05-netty基礎-ByteBuf數據結構06-netty基礎-編碼解碼07-netty基礎-自定義編解碼器08-netty基礎-自定義序列化和反序列化09-n…

計算機畢設缺乏創新點?基于大數據的快手平臺用戶活躍度分析系統給你思路【程序開發+項目定制】

精彩專欄推薦訂閱&#xff1a;在 下方專欄&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f496;&#x1f525;作者主頁&#xff1a;計算機畢設木哥&#x1f525; &#x1f496; 文章目錄 一、項目介紹二…

01.【面試題】在SpringBoot中如何實現多數據源配置

文章目錄 1. 什么是多數據源 1.1 基本概念 1.2 傳統單數據源 vs 多數據源 單數據源架構 多數據源架構 2. 為什么需要多數據源 2.1 業務場景需求 2.2 技術優勢 3. 多數據源的實現方式 3.1 靜態多數據源 3.2 動態多數據源 4. 環境準備 4.1 創建SpringBoot項目 pom.xml依賴配置 4.…

redis主從模型與對象模型

redis淘汰策略 首先我們要明確這里說的淘汰策略是淘汰散列表中的key-value&#xff0c;而不是value中的各個數據結構 過期key中 volatile-lru 從設置了過期時間的鍵中&#xff0c;移除最近最少使用的鍵&#xff08;LRU算法&#xff09;。適合需要優先保留高頻訪問數據的場景…

快速搭建開源網頁編輯器(vue+TinyMCE)

文章目錄 Tiny MCE 安裝方法 1. 安裝node.js 2. 創建vue3項目 3. 安裝TinyMCE依賴并使用 (1)在component文件夾創建Editor.vue文件 (2)編輯App.vue文件 (3)運行項目 (4)獲取并設置API key (5)設置中文菜單 Tiny MCE 安裝方法 1. 安裝node.js 下載地址:https://nod…

ADK【4】內置前端調用流程

文章目錄說明ADK內置前端ADK內置前端開啟流程說明 本文學自賦范社區公開課&#xff0c;僅供學習和交流使用&#xff0c;不用作任何商業用途&#xff01; ADK內置前端 ADK作為最新一代Agent開發框架&#xff0c;不僅功能特性非常領先&#xff0c;而且還內置了非常多的工具&am…

LLMs之GPT-5:OpenAI 發布更智能、更快速、更有用的 AI 模型—內置思考能力,賦能人人專家級智能—技術突破、性能評估與安全保障全面解讀

LLMs之GPT-5&#xff1a;OpenAI 發布更智能、更快速、更有用的 AI 模型—內置思考能力&#xff0c;賦能人人專家級智能—技術突破、性能評估與安全保障全面解讀 導讀&#xff1a;2025年8月7日&#xff0c;OpenAI 發布了 GPT-5&#xff0c;這是他們目前最智能的 AI 系統。它在編…

Java 中操作 R 的全面指南

Java 中操作 R 的全面指南 引言 Java作為一種廣泛使用的編程語言,具有跨平臺、高性能、可擴展等特點。隨著大數據和機器學習的興起,Java在處理和分析復雜數據集方面發揮著越來越重要的作用。R語言,作為一種專門用于統計計算和圖形展示的語言,同樣在數據分析領域有著舉足輕…

數據結構——優先級隊列(PriorityQueue):一文解決 Top K 問題!

目錄 1.優先級隊列 2. 堆的概念 3. 堆的存儲方式 4. 堆的創建 4.1 向下調整 4.2 堆的創建 4.3 堆的插入 4.4 堆的刪除 5.用堆模擬實現優先級隊列 6.常用接口的介紹 6.1 PriorityQueue 的特性 6.2 PriorityQueue 的方法 7. Top K問題 1.優先級隊列 隊列是一種先進先…

C語言自定義類型深度解析:聯合體與枚舉

在C語言中&#xff0c;自定義類型為數據組織提供了極大的靈活性。除了常用的結構體&#xff0c;聯合體&#xff08;共用體&#xff09;和枚舉也是非常重要的自定義類型。本文將結合實例&#xff0c;詳細解析聯合體和枚舉的特性、用法及實際應用場景。 一、聯合體&#xff08;Un…

Numpy科學計算與數據分析:Numpy數據分析基礎之統計函數應用

Numpy統計函數實戰&#xff1a;數據的聚合與分析 學習目標 通過本課程的學習&#xff0c;學員將掌握Numpy中用于統計分析的關鍵函數&#xff0c;如求和(sum)、平均值(mean)、標準差(std)等&#xff0c;能夠熟練地在實際數據集中應用這些函數進行數據的聚合與分析。 相關知識…

從引導加載程序到sysfs:Linux設備樹的完整解析與驅動綁定機制

摘要本報告旨在為嵌入式Linux開發者詳細梳理設備樹&#xff08;Device Tree, DT&#xff09;在系統啟動中的完整解析流程。報告將從引導加載程序&#xff08;Bootloader&#xff09;如何準備和傳遞設備樹二進制文件&#xff08;DTB&#xff09;開始&#xff0c;逐步深入到內核如…