当前位置: 首页 > news >正文

网站假设公司排名网络推广与推广

网站假设公司排名,网络推广与推广,茶陵网站建设,php语言入门【iOS】单例模式 什么是单例模式? 定义 单例模式,简单地说就是一个类只对应一个对象,每次使用这个类时,都只能获取到那一个对象。它的详细定义如下: 如果一个类始终只能创建一个实例,则这个类被称为单例…

【iOS】单例模式

什么是单例模式?

定义

单例模式,简单地说就是一个类只对应一个对象,每次使用这个类时,都只能获取到那一个对象。它的详细定义如下:

如果一个类始终只能创建一个实例,则这个类被称为单例类。 有一个全局的接口来访问这个实例。当第一次载入的时候,它通常使用延时加载的方法创建单一实例。 在程序中,一个单例类在程序中只能初始化一次,为了保证在使用中始终都是存在的,所以单例是在存储器的全局区域,在编译时分配内存,只要程序还在运行就会一直占用内存,在APP结束后由系统释放这部分内存 系统方法中,有未知的自动释放池,如果一个对象进行自动释放的话,又可能进入未知的自动释放池,出现内存问题。这就是单例模式不能自动释放的原因

特点

1.单例是一个类,创造出来的对象叫单例对象

2.单例对象使用类方法创建

3.单例一旦被创建,程序结束才会释放,也就是说,单例只初始化一次

4.单例不用程序员管理内存,内存随程序关闭而释放

为什么使用单例模式?

有时候我们需要一个全局的对象,而且要保证全局有且只有一份即可,这时候就需要用到单例设计模式,需要注意:在多线程的环境下做好线程保护。 一般在程序中,经常调用的类,如工具类、公共跳转类等都会采用单例模式

常见的单例模式

在OC语言中,有一些原生的单例类

UIApplication应用程序实例类
NSNotificationCenter消息中心类
NSFileManager文件管理类
NSUserDefaults应用程序设置
NSURLCache请求缓存类
NSHTTPCookieStorage应用程序cookies池

如何使用单例模式?

static关键字

在了解如何使用单例模式之前,我们先来了解一个与之相关的属性修饰关键字——static

static关键字用于修饰局部变量、全局变量和函数。修饰局部变量时,表示该局部变量存储在静态区,修饰全局变量时,表示限制该全局变量只能在当前文件中访问,修饰函数时,则表示限制函数只能在当前源文件中使用。

静态内存存储区在整个程序运行期间都存在

我们需要用static关键字来修饰单例变量,将变量限制在当前类的文件,否则在其他类中可以使用extern来拿到这个单例并修改

创建单例

我们来试着创建一个单例

#import <Foundation/Foundation.h>NS_ASSUME_NONNULL_BEGIN@interface singleton : NSObject
+ (id)instance;
@endNS_ASSUME_NONNULL_END#import "singleton.h"@implementation singleton
static id instance = nil;+ (id)instance {if (!instance) {instance = [[super allocWithZone:NULL] init];}return instance;
}@end#import <UIKit/UIKit.h>
#import "AppDelegate.h"
#import "singleton.h"int main(int argc, char * argv[]) {NSString * appDelegateClassName;@autoreleasepool {NSLog(@"singleton:%d",[singleton instance] == [singleton instance]);NSLog(@"%d",[singleton instance] == [[singleton alloc] init]);}return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

运行后得到以下结果:

我们发现,当使用自定义的类方法创建对象时,的确实现了我们想要的效果,创建出了单例。但是,当使用alloc init创建对象时,得到的并不是单例,与使用类方法创建的对象也并不相同。

这个时候我们就需要重写alloc init方法,来保证无论使用什么方法创建,这个类始终只有一个对象。这时我们只需重写allocWithZone:方法就可以了。

我们平时在初始化对象时使用的方法[[Class alloc] init],其实做了两件事,alloc方法为对象分配内存空间,init是对对象的初始化(包括设置成员变量初值等工作)。而给对象分配内存空间,除了alloc方法,还有一个方法就是allocWithZone:。使用alloc方法时,其实也是调用了allocWithZone方法的,所以只需要在allocWithZone里重写,就可以覆盖所有会生成新的实例的方法

这里的allocWithZone:方法,它的参数是被忽略的,正确的做法是传nil或者NULL。

此外,为了防止copy方法生成新的实例,还要重写copyWithZone和mutableCopyWithZone。

​#import "singleton.h"@implementation singleton
static id instance = nil;+ (id)instance {if (!instance) {instance = [[super allocWithZone:NULL] init];}return instance;
}+ (instancetype)allocWithZone:(struct _NSZone *)zone{return instance;
}
-(id)copyWithZone:(NSZone *)zone{return instance;
}-(id)mutableCopyWithZone:(NSZone *)zone{return instance;
}@end

懒汉模式

创建单例有两种模式,分别是懒汉模式和饿汉模式。这两种模式的区别就在于在什么时候去创建对象,懒汉模式就是在第一次用到类的时候才会实例化,饿汉模式就是在类加载的时候就进行实例化。下面先介绍一下懒汉模式

懒汉模式一般用于访问量较小的时候,用时间换空间。通俗地说,懒汉模式就像一个大懒虫,这个懒虫现在有很多穿过的脏衣服,但是他却不打算洗这些衣服,等到实在没衣服穿了,他才会去洗这些衣服。

在使用懒汉模式的时候,要注意保证线程的安全性。

多线程和单线程

线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的,也就是说不同的线程可以执行同样的函数。

多线程是指程序中包含多个执行流,也就是在一个程序中可以同时运行多个不同的线程来执行不同的任务

加锁

在单线程中,我们上面所用到的创建单例的方法其实就是懒汉模式,可以直接使用上面的方法来创建懒汉模式,而在多线程中,为了确保线程安全,我们可以用@synchronized来加锁,@synchronized可以防止不同的线程同时执行同一段代码,因此加锁后每次访问该代码就都只能一个行程进行访问。

#import "FirstMethod.h"@implementation FirstMethod
static id instance = nil;
+ (instancetype)instance {@synchronized (self) {if (!instance) {instance = [[super allocWithZone:NULL] init];}}return instance;
}
@end

这一段代码可以在确保线程安全的情况下实现单例,但是我们细看会发现调用insrance方法后,如果instance已经存在,可以直接将instance作为返回值传递出去,没有必要进入锁。于是我们加锁之前先做一次判断

#import "FirstMethod.h"@implementation FirstMethod
static id instance = nil;
+ (instancetype)instance {if (!instance) {@synchronized (self) {if (!instance) {instance = [[super allocWithZone:NULL] init];}}}return instance;
}
@end

注意:这里内层的if不能省略,因为如果省略了内层的if,只是对对象的创建和初始化加了锁,而不是对创建单例过程加锁,也就是说有可能会有两个线程同时进入外层的if,然后先后一个一个执行alloc init,这样就可能导致创建出两个不一样的对象。

GCD的dispatch_once

GCD:全称是Grand Central Dispatch,可译为“牛逼的中枢调度器”,是苹果公司为多核的并行运算提出的解决方案,会自动利用更多的CPU内核(比如双核、四核),自动管理线程的生命周期(创建线程、调度任务、销毁线程),程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码。

另一种确保线程安全的方法就是使用GCD的dispatch_once来创建单例

#import "singleton.h"@implementation singleton
static id instance = nil;+ (id)instance {static dispatch_once_t onceToken;dispatch_once(&onceToken, ^{instance = [[super alloc] init];});return instance;
}+ (instancetype)allocWithZone:(struct _NSZone *)zone{return instance;
}
@end

下面解释一下dispatch_once是怎样确保线程安全并创建单例的。

我们看到上述代码中出现了dispatch_once_t变量和dispatch_once函数

dispatch_once_t变量

这里的intptr_t长度是所在平台的位数,用来存放地址。

dispatch_once函数

dispatch_once无论单线程还是多线程,都只执行一次,在安全的前提下也保证了性能,同时实现了单例的创建。

当onceToken为0时,线程执行dispatch_once的block中的代码

当onceToken为-1时,线程跳过dispatch_once的block中的代码

当onceToken为其他值时,线程被阻塞,等待onceToken值改变

饿汉模式

#import "singleton.h"@implementation singleton
static id instance = nil;+ (void)load {[super load];instance = [[self allocWithZone:NULL] init];
}+ (id)instance {instance = [[self allocWithZone:NULL] init];return instance;
}
@end

load方法:当类加载到运行环境中时调用且仅调用一次,同时一个类只会加载一次(程序启动时,所有类加载一次,不管有没有在当前视图中用到)

http://www.tj-hxxt.cn/news/76435.html

相关文章:

  • 路桥做网站的公司网络推广员一个月多少钱
  • 网站建设课程设计心得国内打开google网页的方法
  • 公司网站如何做优化网站推广排名服务
  • Html5做旅游网站的设计思路天津关键词优化专家
  • 做网站订阅号百度竞价关键词查询
  • 女生化妆品网站建设规划书河北优化seo
  • 做生物卷子的网站百度口碑
  • 红酒公司的网站建设找资源的关键词有哪些
  • wordpress评论通知站长百度推广和优化有什么区别
  • 百度商桥在网站百度广告标识
  • 学院网站建设与管理办法市场营销师报名官网
  • 给别人做网站别人违法经营6有没有可以代理推广的平台
  • 手表网站那个好seo优化一般包括哪些内容
  • 怎样才能做一个手机网站东莞seo建站哪家好
  • 做网站实例公司在百度怎么推广
  • 可以看国外网站的dns英文谷歌优化
  • 海外网站建设青岛网络seo公司
  • html5做网站心得体会搜索引擎优化技术都有哪些
  • ftp发布asp.net网站优化网站排名需要多少钱
  • 做境外域名网站百度竞价推广流程
  • 广州海珠区赤岗 新港网站建设公司推销产品怎么推广
  • 杭州网站设计推荐柚米洛阳市网站建设
  • 做网站一般收取多少钱外贸网站推广平台
  • 企业网站程序带wap百度营销推广登录
  • 深圳知名网站建设山东建站管理系统
  • 免费拒绝收费网站全国最好网络优化公司
  • a站是啥网站制作的要点和步骤详解
  • 如何做整人网站个人博客网站
  • 头条网站怎么做的网站top排行榜
  • 高端网站建设公司无锡做网站的公司