【iOS进阶】【多线程】3-单例、autoreleasepool

一、单例

1>单例模式是一种常用的软件设计模式

  通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源

  如果希望系统中某个类的对象只能存在一个,单例模式是最好的解决方案

2>应用场景:

  音频播放,背景音乐!

  硬件资源:加速器、[UIScreen mainScreen]

  为了区分单例,单例的创建方法一般为:sharedXX, mainXXX

  iOS中最常见的单例就是UIApplication

3>具体实现

1.单例类的声明

#import "DemoObj.h"

@implementation DemoObj
/**
 *  单例:
 *  1.重写allocWithZone
 *  2.添加sharedDemoObj方法
 */

//在iOS中,所有对象的内存空间的分配(如alloc),最终都会调用allocWithZone
//如果需要做单例,需要重写此方法
//GCD提供了一个方法,专门用来创建单例的
+(id)allocWithZone:(struct _NSZone *)zone{
    
    //定义一个静态DemoObj变量
    static DemoObj *instance;

    //dispatch_once是线程安全的
    static dispatch_once_t onceToken;
    //dispatch_once宏可以保证块代码中的指令只被执行一次
    dispatch_once(&onceToken, ^{
        //永远只会被执行一次,dispatch_once只会被实例化一次
        instance = [super allocWithZone:zone];
    });
    return instance;
}

+(instancetype)sharedDemoObj{
    
    return [[self alloc] init];
}

@end

2.单例类的调用

#import "ViewController.h"
#import "DemoObj.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    DemoObj *obj = [DemoObj sharedDemoObj];
    NSLog(@"%@",obj);
    DemoObj *obj1 = [DemoObj sharedDemoObj];
    NSLog(@"%@",obj1);
}

@end

4>单例小结

  1.优点

    可以阻止其他对象实例化单例对象的副本,从而确保所有对象都访问唯一实例

  2.缺点

    单例对象一旦建立,对象指针是保存在静态区的,单例对象在堆中分配的内存空间,会在应用程序终止后才会被释放

  3.提示

    只有确实需要唯一使用的对象才需要考虑单例模式,不要滥用单例

二、autoreleasepool

1>iOS开发中的内存管理

  在iOS开发中,并没有JAVA或C#中的垃圾回收机制

  使用ARC开发,只是在编译时,编译器会根据代码结构自动添加了retain、release和autorelease

2>自动释放池的工作原理

  标记为autorelease的对象在出了作用域范围后,会被添加到最近一次创建的自动释放池中

  当自动释放池被销毁或耗尽时,会向自动释放池中的所有对象发送release消息

  每个线程都需要有@autoreleasepool,否则可能会出现内存泄漏,但是使用NSThread多线程技术,并不会为后台线程创建自动释放池

3>autoreleasepool常见面试代码

for (int i = 0; i < 10; ++i) {
    NSString *str = @"Hello World";
    str = [str stringByAppendingFormat:@" - %d", i];
    str = [str uppercaseString];
    NSLog(@"%@", str);
}

问:以上代码存在什么样的问题?如果循环的次数非常大时,应该如何修改?

答:该for循环一直在创建变量,可能在for完成之前,内存已经被耗尽。

  解决办法

  1.如果i很大,for循环可以这样设计:

@autorelease{
    for (int i = 0; i < 10; ++i) {
        NSString *str = @"Hello World";
        str = [str stringByAppendingFormat:@" - %d", i];
        str = [str uppercaseString];
        NSLog(@"%@", str);
    }
}

  2.如果i很巨大,for循环可以这样设计:

for (int i = 0; i < 10; ++i) {
    @autoreleasepool{
        NSString *str = @"Hello World";
        str = [str stringByAppendingFormat:@" - %d", i];
        str = [str uppercaseString];
        NSLog(@"%@", str);
    }
}

 

posted @ 2015-04-21 20:45  锟斤拷Dy  阅读(252)  评论(0)    收藏  举报