美文网首页iOS学习笔记
iOS学习笔记-单例

iOS学习笔记-单例

作者: Izzieo_O | 来源:发表于2016-02-18 00:44 被阅读138次

    1.系统中常用单例

    [[UIApplication sharedApplication] statusBarStyle];
        
    [NSNotificationCenter defaultCenter];
        
    [NSUserDefaults standardUserDefaults];
        
    [NSFileManager defaultManager];
    

    单例模式中,一般用于管理某对象持有资源,可以全局共享。
    大部分使用单例模式共享信息。

    2.单例使用

    2.1.创建

    2.1.1常规方式

    声明一个静态变量持有对象

    static ManageViewController *center = nil;
        
    if (center == nil) {
        center = [[ManageViewController alloc] init];
    }
        
    return center;
    

    存在问题:可能AppDlegate与ViewController访问时,同时进入center = [[ManageViewController alloc] init];

    2.1.2.使用dispatch_once 避免上述问题(最佳)
        static ManageViewController *center = nil;
        
        static dispatch_once_t predicate;
        
        dispatch_once(&predicate, ^{
            
            center = [[ManageViewController alloc] init];
            
        });
        
        return  center;
    
    2.1.3.使用initialize方法

    每个类调用任意方法时,都会先调用initialize

    +(void)initialize{
        
        static ManageViewController *center = nil;
        
        if (self == [ManageViewController class]) {
            
            center = [[ManageViewController alloc] init];
        }
        
    }
    

    2.2.创建单例注意

    2.2.1防止其他类调用
    +(instancetype)manageCenter{
        
        static dispatch_once_t predicate;
        
        dispatch_once(&predicate, ^{
            
            center = (ManageViewController *)@"ManageViewController";
            
            center = [[ManageViewController alloc] init];
            
        });
        
        //防止子类使用
        
        NSString *classString = NSStringFromClass([self class]);//获取当前类名
        
        if ([classString isEqualToString:@"ManageViewController"] == NO) {
            
            NSParameterAssert(nil);//如果不符合,此处崩溃提示:Invalid parameter not satisfying:nil
        }
        
        return  center;
    }
    
    2.2.2.保证只有一个实例对象

    一个单例类作为管理中心,系统开销很大。实例化一个对象,消耗很大。

    重写init方法

    +(instancetype)manageCenter{
        
        static dispatch_once_t predicate;
        
        dispatch_once(&predicate, ^{
            
            center = (ManageViewController *)@"ManageViewController";
            
            center = [[ManageViewController alloc] init];
            
        });
        
        //防止子类使用
       
        NSString *classString = NSStringFromClass([self class]);//获取当前类名
        
        if ([classString isEqualToString:@"ManageViewController"] == NO) {
            
            NSParameterAssert(nil);
        }
        
        return  center;
    }
    -(instancetype)init{
        
        NSString *string = (NSString *)center;
    
        //判断string是否为字符串类型以及是否等于给定字符串
        if ([string isKindOfClass:[NSString class]] == YES && [string isEqualToString:@"ManageViewController"]) {
            self = [super init];
            
            if (self) {
            
               //防止子类使用
                
                NSString *classString = NSStringFromClass([self class]);
                
                if ([classString isEqualToString:@"ManageViewController"] == NO) {
                    
                    NSParameterAssert(nil);
                }
                
            }
            return self;
        }else{
            return nil;
        } 
       
    }
    

    若是子类执行alloc init方法,此时center值为空,不符合if条件,返回空。
    执行manageCenter方法时,单例对象(center)指向字符串。开始执行init,符合判断条件,实例化对象。而之后执行alloc init时,center值变为ManageViewController值,不符合if中判断条件,返回nil。

    3.本地存储优化

    使用第三方“FastCoder”.也可使用官方方法(遵守NSCoding协议) :

    - (void)encodeWithCoder:(NSCoder *)aCoder;
    - (nullable instancetype)initWithCoder:(NSCoder*)aDecoder; 
    
    3.1.用单例设计存储数据接口,用单例接口隔离实现细节

    StoreValue.m中

    +(ManageValue *)sharedInstance{
        
        static dispatch_once_t predicate;
        
        dispatch_once(&predicate, ^{
            
            manageValue = (ManageValue *)@"manage";
            manageValue = [[ManageValue alloc] init];
            
        });
        
        //防止子类使用
        
        NSString *classString = NSStringFromClass([self class]);
        
        if ([classString isEqualToString:@"ManageValue"] == NO) {
            
            NSParameterAssert(nil);
        }
        
        return manageValue;
        
    }
    
    //保证只有一个实例,重写init 方法
    -(instancetype)init{
        
        NSString *string = (NSString *)manageValue;
        
        if ([string isKindOfClass:[NSString class]] == YES && [string isEqualToString:@"manage"]) {
            self = [super init];
            
            if (self) {
                
                //防止子类使用
                
                NSString *classString = NSStringFromClass([self class]);
                
                NSLog(@"%@",classString);
                
                if ([classString isEqualToString:@"ManageValue"] == NO) {
                    
                    NSParameterAssert(nil);
                }
                
            }
            
            return self;
        }else{
            
            return nil;
        }
        
        
    }
    
    -(void)storeValue:(id)value withKey:(NSString *)key{
        
        //value、key值不能为空
        NSParameterAssert(value);
        NSParameterAssert(key);
        
        //value值转化为NSData,后进行存储
        NSData *data = [FastCoder dataWithRootObject:value];
        
        if (data) {
            
            [[NSUserDefaults standardUserDefaults] setObject:data forKey:key];
            
        }
    }
    
    -(id)valueWithKey:(NSString *)key{
        
        NSParameterAssert(key);
        
        NSData *data = [[NSUserDefaults standardUserDefaults] valueForKey:key];
        
        return [FastCoder objectWithData:data];
    }
    
    

    测试一下:
    ViewController.m中

        StaffModel *model = [[StaffModel alloc] init];
        
        model.name = @"AA";
        
        model.salary = @"1000";
        
        ManageValue *value = [ManageValue sharedInstance];
        
        //存值
        [value storeValue:model withKey:@"data"];
        
        StaffModel *temp = [[StaffModel alloc] init];
        
        //取值    
        temp = [value valueForKey:@"data"];
        
        NSLog(@"%@",temp.name);
    
    

    输出得到值。

    3.2.在单例提供的接口上实现上层封装

    好处:
    把实现细节隔离。如果要修改存储方案,只需要修改实现方法中的细节。改动少。

    创建一个分类,添加方法

    -(void)storeValueByKey:(NSString *)key{
        
        [[ManageValue sharedInstance] storeValue:self withKey:key];
        
    }
    
    +(id)getValueWithKey:(NSString *)key{
        
        return [[ManageValue sharedInstance] valueForKey:key];
        
    }
    

    ViewController.m中

    [model storeValueByKey:@"data"];
        
    StaffModel *temp = [StaffModel getValueWithKey:@"data"];
        
    NSLog(@"%@",temp.name);
    

    声明:参考网络资源,若侵权,请告知。

    相关文章

      网友评论

        本文标题:iOS学习笔记-单例

        本文链接:https://www.haomeiwen.com/subject/pgppkttx.html