#import "Husband.h"
@implementation Husband //-->litteHusband
static Husband *instance = nil;//只是把指针放入静态存储区,刚开始指针置为空,只要使指针不变就好了,然后因为栈区的内存有指针指着,所以不会被销毁
//一开始创建东西的话都是alloc init这时候要确保他创建的,或者调用的那个方法是同一个,一般用share或者diefine,确保的是创建的指针指向的地址是同一个内存地址,这时候就需要保证放在静态储存区,然后给指针创建地址,先判断有没有创建,没有然后alloc一下,调用alloc withzone,保证这个指针指向同一个地址,就是这个指针是同一个,为什么是指针而不是在栈区里面的内存里的东西呢,因为没有指针指向东西会被销毁,然后创建的时候要注意加锁,确保一次只有一个创建,那一步是创建指针和对象,并且完成指针指向对象的过程,只要指针指向对象就不会销毁,然后单例copy属性的时候要确保他不是完整的赋值里面的数据而是用这个所以要重写,因为GCD包含ARC所以不用考虑引用计数,但是arc下的GCD则这些也都要复写
+ (instancetype)sharedHusband {
if (instance == nil) {
instance = [[self alloc] init];//alloc也是调用allocwithzone创建
}
return instance;
}
+ (instancetype)allocWithZone:(struct _NSZone *)zone {//alloc也会用这个方法进行创建
//加锁,确保多个线程同时访问shareHusband时只申请一个实例对象
// @synchronized(self) {
// if (instance == nil) {
// //调用NSObject类的方法进行内存申请
// instance = [super allocWithZone:zone];
//
// }
// }
//onceToken标记block块是否执行过,如果执行过,则onceToken为非零值,如果未执行过则为初始值0
static dispatch_once_t onceToken;//在静态存储区的值,如果没有赋值,系统开始的时候把所有的值置为0,
//block中的代码段只被执行一次,通过onceToken令牌来控制。
dispatch_once(&onceToken, ^{
if (instance == nil) {
//调用NSObject类的方法进行内存申请
NSLog(@"hahah");
instance = [super allocWithZone:zone];
}
});
return instance;
}
//如果一个类的实例对象想调用copy方法实现复制,则必须遵守协议NSCopying,并在当前类中实现copyWithZone
//复写copywithZone
- (id)copyWithZone:(NSZone *)zone {
return self;
}
----
---------------------GCD下的图片加载 -----------------
//1.NSThread来实现多线程
//[self performSelectorInBackground:@selector(downloadImage:) withObject:url];
//2.CocoaOperation实现
//[self downloadImageUsingOperation:url];
//3.GCD实现
[self downloadImageUsingGCD:url];
}
- (void)downloadImageUsingGCD:(NSURL *)url {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData];
//回到主线程
dispatch_async(dispatch_get_main_queue(), ^{
self.image = image;
});
//回到主线程中执行代码时,选用sync或者async的依据:基本上网络加载都是异步炒作
// 如果多线程中dispatch下面的代码需要等到block中的任务执行完成才能执行,就使用sync。
// 如果多线程中剩余代码不关心添加到主队列的block任务的完成情况,就使用async。
});
}
- (void)downloadImageUsingOperation:(NSURL *)url {
//创建一个并发队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData];
//回到主线程更新UI, 先找到主队列,向主队列添加任务
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.image = image;//主界面的imageView的image
}];
}];
}
- (void)downloadImage:(NSURL *)url {
//主线程的autoreleasepool无法管理多线程中的OC对象,因此需要在多线程的入口方法中添加autoreleasepool。
@autoreleasepool {
//for (int i = 0; i < 10; i++) {
NSData *imageData = [NSData dataWithContentsOfURL:url];
UIImage *image = [UIImage imageWithData:imageData];
//}
//所有UI界面的刷新都应该在主线程中完成,因为UI的绘制渲染引擎是工作在主线程中的,不能在多线程完成界面的刷新。
[self performSelectorOnMainThread:@selector(setImage:) withObject:image waitUntilDone:NO];
//把setImage:这个任务添加到主队列中执行,主队列中的任务都是在主线程中完成的。主队列是一个串行队列。
}
//---------
}