美文网首页iOS CraziesiOS Developer
iOS单例和NSUserDefaults混合使用

iOS单例和NSUserDefaults混合使用

作者: 退役程序猿 | 来源:发表于2017-04-27 17:58 被阅读144次

    前言:

    • 在我们iOS项目中存储一些用户配置信息或者一些其他公共信息我们首先回想到用单例来做,但是单例是在app结束生命之后单例的所有属性就会消失,有得时候又不是很适合我们的需求,比如我们要记录一个登录状态或者是用户配置信息这些信息是一直存在也必须存在的,这时候我们的单例就心有余而力不足了,于是我就研究了一套单例和NSUserDefaults配合使用的案例。

    实现原理:

    • 首先我们实现一个单例类和一个属性Models用来存储一些属性,存储的同时我们把这个单例属性Models以NSData类型来存储到NSUserDefaults中,之后尽管app杀死单例属性消失我们的NSUserDefaults中也会把这个单例Models存储下来以便下次启动app的时候读取到单例Models中在使用。

    单例的实现:

    • MRC的实现我就不讲了我就直接讲下ARC单例类实现,上代码。
    新建一个单例类文件(UserInfoContext)继承NSObject
    UserInfoContext.h文件代码实现:
    新建一个单例Models
    //导入单例Modesl头文件
    #import "UserInfo.h"
    @property(nonatomic,strong) UserInfo *userInfo;
    +(UserInfoContext*)sharedUserInfoContext;
    
    UserInfoContext.m文件代码实现:
    @synthesize userInfo;
    static UserInfoContext *sharedUserInfoContext = nil;
    +(UserInfoContext*)sharedUserInfoContext{
    static dispatch_once_t token;
    dispatch_once(&token, ^{
        if(sharedUserInfoContext == nil){
            sharedUserInfoContext = [[self alloc] init];
        }
    });
    return sharedUserInfoContext;
    }
    +(id)allocWithZone:(struct _NSZone *)zone{
        static dispatch_once_t token;
         dispatch_once(&token, ^{
             if(sharedUserInfoContext == nil){
                 sharedUserInfoContext = [super allocWithZone:zone]; 
             }
         });
             return sharedUserInfoContext;
    }
    - (instancetype)init{
     self = [super init];
     if(self){
        //实例化这个Models
         sharedUserInfoContext.userInfo = [[UserInfo alloc] init];
     }
     return self;
    }
    - (id)copy{
         return self;
    }
    - (id)mutableCopy{
         return self;
    }
    
    新建一个单例Models(UserInfo)存放属性继承NSObject
    UserInfo.h文件代码实现:
    @interface UserInfo : NSObject<NSCoding>{
        BOOL isLogin;//判断是否登录
        NSString *phoneNumber;//手机号
        NSString *cookie;//cookie
        NSInteger tabBarSelected;//tabbar
        NSString *deviceid;//设备号
    }
    @property (nonatomic,assign) BOOL isLogin;
    @property (nonatomic,copy) NSString *phoneNumber;
    @property (nonatomic,copy) NSString *cookie;
    @property (nonatomic,assign) NSInteger tabBarSelected;
    @property (nonatomic,copy) NSString *deviceid;
    
    UserInfo.m文件代码实现(属性编码解码):
    @synthesize isLogin;
    @synthesize phoneNumber;
    @synthesize cookie;
    @synthesize tabBarSelected;
    @synthesize deviceid;
    - (void)encodeWithCoder:(NSCoder *)aCoder{
        [aCoder encodeBool:self.isLogin forKey:@"isLogin"];
        [aCoder encodeObject:self.phoneNumber     forKey:@"phoneNumber"];
        [aCoder encodeObject:self.cookie forKey:@"cookie"];
        [aCoder encodeInteger:self.tabBarSelected forKey:@"tabBarSelected"];
        [aCoder encodeObject:self.deviceid forKey:@"deviceid"];  
    }
    - (instancetype)initWithCoder:(NSCoder *)aDecoder{
        if (self =[super init]) {
            self.isLogin = [aDecoder decodeBoolForKey:@"isLogin"];
            self.phoneNumber = [aDecoder     decodeObjectForKey:@"phoneNumber"];
            self.cookie = [aDecoder decodeObjectForKey:@"cookie"];
            self.tabBarSelected = [aDecoder     decodeIntegerForKey:@"tabBarSelected"];
            self.deviceid = [aDecoder decodeObjectForKey:@"deviceid"];
        }
        return self;
    }
    @end
    
    新建一个工具类(Utilities)存放属性继承NSObject

    为了更好的简便的使用这个这个单例和NSUserDefaults的读取和存储

    Utilities.h文件代码实现:
    //单例-> NSUserDefaults
    +(void)SetNSUserDefaults:(UserInfo *)userInfo;
    //NSUserDefaults-> 单例
    +(UserInfo *)GetNSUserDefaults;
    
    Utilities.m文件代码实现:
    //存储单例Models(UserInfo)到NSUserDefaults
    +(void)SetNSUserDefaults:(UserInfo *)userInfo{
        NSData *data = [NSKeyedArchiver archivedDataWithRootObject:userInfo];
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        [defaults setObject:data forKey:@"user"];
        [defaults synchronize];  
    }
    //读取NSUserDefaults存储内容return到单例Modesl(UserInfo)中
    +(UserInfo *)GetNSUserDefaults{
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSData *data = [defaults objectForKey:@"user"];
        return [NSKeyedUnarchiver unarchiveObjectWithData:data];
    }
    

    以上代码我们屡屡

    1.开始我们实现了一个单例类(UserInfoContext);
    2.在单例类中实现了一个属性Models(UserInfo);
    3.实现了一个工具类方便把单例属性Models(UserInfo)存储到NSUserDefaults以及把NSUserDefaults内容读取到单例属性Models(UserInfo)中。

    • 下面我们来试验调用赋值给单例Models(UserInfo)同时把单例Models(UserInfo)存储到NSUserDefaults中

    //存储在单例中
     UserInfo *user = [UserInfoContext sharedUserInfoContext].userInfo;
     user.isLogin = YES;
     user.phoneNumber = @"13552539636"
     user.cookie = @"QQ396368888";
     //启动app默认选中TabBar
     user.tabBarSelected = 0;
    //在把单例存储到NSUserDefaults(调用工具类方法)
    [Utilities SetNSUserDefaults:user];
    
    • 在AppDelegate类中得didFinishLaunchingWithOptions方法中直接读取NSUserDefaults内容到单例使用

    //读取用户状态和配置信息到单例中
    [UserInfoContext sharedUserInfoContext].userInfo= [Utilities GetNSUserDefaults];
    
    • 以上我们完整的一套流程就做好了,我为什么要做这个呢,是因为我们产品提出了一个奇葩的要求就是要启动默认显示哪个TabBar和一些用户设置像App主题皮肤等等一系列要求,所以单例就不够用了。
    • 代码就不上GitHub了这上面代码没有少一句照搬都可以。

    相关文章

      网友评论

      • 码客波锣:只用userdefault不可以吗?为什么要用单例?
        退役程序猿:@NobilityAtom 数据改变是改变单例。杀死app之后在存单例。读一次存一次肯定要比时时刻刻使用ud要省内存
        码客波锣:@中国小青年 确定存取只存取一次吗?数据要是改变怎么办? 省事的话 确实比直接用ud 会简单点 但是用 ud +model 然后重写属性的set get 方法存取ud 就可以了 没必要 ud + 单例。至于最后说 杀死app会缓存数据 那是必须的 因为缓存是最根本的需求 所以谈不上优势
        退役程序猿:这样配合使用userdefault只会读一次存一次。我个人感觉这样回省事而起性能上会不会比较好。app在线状态操作的是单例。杀死app存储。启动读取。

      本文标题:iOS单例和NSUserDefaults混合使用

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