iOS开发中User类(用户管理类)的设计

任何一个App都有用户管理和存储用户的个人信息类 ,例如User中所一般包含的的信息user_id、user_name等 一般会有一个User类存储这些信息

User.h文件中
@interface User : NSObject

@property (nonatomic, copy, readonly) NSString *user_id;// id
@property (nonatomic, copy, readonly) NSString *user_name;//用户名
@property (nonatomic, copy, readonly) NSString *login_token;// token
@property (nonatomic, copy, readonly) NSString *nickname;//昵称
@property (nonatomic, copy, readonly) NSString *avatar;//头像
@end

这些是基础的用户信息,需要走注意的是 这些信息暴露在 User.h 中 但是不允许 其它类修改 需要 加上 readonly 关键字 但是在User.m文件中 定义同样名字的属性 但是去掉 readonly 关键字 这样就保证 只在User类中编辑这些属性

User.m文件中
@interface User : NSObject

@property (nonatomic, copy) NSString *user_id;// id
@property (nonatomic, copy) NSString *user_name;//用户名
@property (nonatomic, copy) NSString *login_token;// token
@property (nonatomic, copy) NSString *nickname;//昵称
@property (nonatomic, copy) NSString *avatar;//头像
@end

一般配合 User的添加一个UserManager类 用来管理User类

#import "User.h"

typedef void(^LoginFinishedBlock)(BOOL isSuccess, NSString *errorContent);
typedef void (^RegistFinishedBlock)(BOOL isSuccess, NSString *errorContent);
@interface UserManager : NSObject

@property (nonatomic, assign, readonly) BOOL isAlreadyLogin;
@property (nonatomic, copy) LoginFinishedBlock loginBlock;
@property (nonatomic, copy) RegistFinishedBlock registBlock;


+ (instancetype)shareInstance;

- (User *)getUserInfo;

- (void)removeUserInfo;

- (void)userLoginWithInfo:(NSDictionary *)info
                onFinised:(LoginFinishedBlock)finished;

- (void)userRegisterWithInfo:(NSDictionary *)info
                  onFinished:(RegistFinishedBlock)finished;

@end

对于User类的管理 UserManager 最好以单例形式 一般获取用户信息都在登录和注册的时候获取用户的信息 所以在 UserManager 类中 添加 登录与注册的网络请求 。一般请求结束 数据以json 形式返回 通过UserManager类 将json 数据转化为 User 类中信息,然后在使用的时候 获取 User类来进行各种用户信息的获取和使用
以登录 来讲述

- (void)userLoginWithInfo:(NSDictionary *)info onFinised:(LoginFinishedBlock)finished {
    NSMutableDictionary *paramsDic = [NSMutableDictionary dictionary];
    weakSelf(weakSelf)
    [[LLNetwork shareInstance] postWithURL:@"loginAPI"
                                     token:nil
                                    params:paramsDic
                                 isLoading:YES
                                   success:^(id response) {
                 
                                       //添加模拟的数据 实际操作中 是回传的
                                       response = [self mockResponse1];
                                       response = [UserManager dictionaryWithJSON:response];
                                       BOOL isSuccess = [response[@"is_success"] boolValue];
                                       if (!isSuccess) {
                                           NSString *errorMessage = response[@"error_msg"];
                                           finished (NO, errorMessage);
                                           return;
                                       }
                 
                 //登录成功
                 User *user = [[User alloc] initWithDicionary:response];
                 [weakSelf saveUserInfo:user];
                 finished (YES, nil);
                 
             } failure:^(NSError *error) {
                 finished (NO, nil);
                 
             }];
             

}

登录成功后将 response 信息转化为 User类 中各个属性的值 需要注意的是 User 类一般需要本地化存储 因为在登录成功之后 好多地方需要 User的信息 本地化存储之后 可以方便的获取User信息 。User信息存储方法有很多 简单的可以使用 NSUserDefaults的方式 也可以文件形式 就是writeToFile 。对于存储 User类 需要先进行 归档 将User类信息转化为 NSData 然后 写入到文件中去如下

// 归档
- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.user_id forKey:@"user_id"];
    [aCoder encodeObject:self.user_name forKey:@"user_name"];
    [aCoder encodeObject:self.login_token forKey:@"login_token"];
    [aCoder encodeObject:self.nickname forKey:@"nickname"];
    [aCoder encodeObject:self.avatar forKey:@"avatar"];

}

// 反归档
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {
        self.user_id = [aDecoder decodeObjectForKey:@"user_id"];
        self.user_name = [aDecoder decodeObjectForKey:@"user_name"];
        self.login_token = [aDecoder decodeObjectForKey:@"login_token"];
        self.nickname = [aDecoder decodeObjectForKey:@"nickname"];
        self.avatar = [aDecoder decodeObjectForKey:@"avatar"];
    }
    return self;
}

登录成功之后将User信息存储

- (void)saveUserInfo:(User *)user {
    
    //userDefaults bug  暂时抛弃了
    //    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
    //    [userDefaults setObject:[NSKeyedArchiver archivedDataWithRootObject:user] forKey:kMSuserInfo];
    //    [userDefaults synchronize];
    NSData *userData = [NSKeyedArchiver archivedDataWithRootObject:user];
    NSString *path = [self getDataFilePath];
    BOOL isWriteSuccess = [userData writeToFile:path atomically:YES];
    if (isWriteSuccess) {
        DebugLog(@"write success");
    } else {
        DebugLog(@"write failure");
    }
    
}

开始笔者也是使用 NSUserDefaults的方式存储User信息 但是 偶尔会出现 存储的User信息丢失的现象 所以改用 writeToFile的方式 有知道的大神请给解答一二。

获取User信息也是 通过UserManger 单例获取的

- (User *)getUserInfo {
    NSString *path = [self getDataFilePath];
    NSData *userData = [[NSData alloc] initWithContentsOfFile:path];
    
    //    NSData *userData = [[NSUserDefaults standardUserDefaults] objectForKey:kMSuserInfo];
    if (!userData) {
        return nil;
    }
    User *user = (User *)[NSKeyedUnarchiver unarchiveObjectWithData:userData];
    return user;
}

退出登录的时候 需要将User信息给清除掉,但是 一般App都有清除缓存的功能 ,注意清除缓存的时候需要将 User文件的地址给过滤掉

- (void)removeUserInfo {

    NSString *path = [self getDataFilePath];
    [self deleteFileWithName:path];
    
}

- (NSString * )getDataFilePath {
    
    // 注意清理缓存的时候 要过滤掉User 文件
    NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
    NSString *userPath = [NSString stringWithFormat:@"%@/MS_USER_INFO",docPath];
    [[NSFileManager defaultManager] createDirectoryAtPath:userPath withIntermediateDirectories:YES attributes:nil error:nil];
    NSString *filePath = [userPath stringByAppendingPathComponent:@"user.data"];
    DebugLog(@"++++ user存储地址 +++ %@", filePath);
    return filePath;
}

- (void)deleteFileWithName:(NSString *)pathName {
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSString *path = [self getDataFilePath];
    BOOL deleteSuccess = [fileManager removeItemAtPath:path error:nil];
    if (deleteSuccess) {
        DebugLog(@"delete  success");
    } else {
        DebugLog(@"delete failure");
    }
        
}

一般App好多页面都会根据用户是否登录显示不同的页面 或者进行不同的逻辑操作
所以一般 会添加 用户是否登录的属性
@property (nonatomic, assign, readonly) BOOL isAlreadyLogin;
注意属性 必须是 readonly 防止被代码不规范的小伙伴在其它地方修改

- (BOOL)isAlreadyLogin {
    User *user = [self getUserInfo];
    if (user.login_token.length > 0 && user.user_name.length  > 0) {
        return YES;
    }
    return NO;
}

此处只是简单的判断是否登录逻辑 ,如果需要可以做其它更加严谨的判断
使用的时候 直接获取 通过 UserManager 获取 User类即可

- (void)getUserInfoButtonAction {
    User *user = [[UserManager shareInstance] getUserInfo];
    BOOL isAlreadyLogin = [UserManager shareInstance].isAlreadyLogin;
    NSString *user_id = user.user_id;
    NSString *user_name = user.user_name;
    NSString *login_token = user.login_token;
    NSString *nickname = user.nickname;
    NSString *avatar = user.avatar;
    self.label.text = [NSString stringWithFormat:@"isAlreadyLogin = %ld user_id = %@\n  user_name = %@\n login_token = %@\n nickname = %@\n avatar =  %@\n",isAlreadyLogin, user_id, user_name, login_token, nickname, avatar];
    
}

这就是基础User类与UserManager类的大部分逻辑 欢迎各位批评指正 简单的的demo代码地址如下
https://coding.net/u/liwb/p/UserProject/git/tree/master/UserProduct?public=true

你可能感兴趣的:(iOS开发中User类(用户管理类)的设计)