任何一个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