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;逐步深入到内核如…