iOS開發(fā)中User類(用戶管理類)的設(shè)計

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

這些是基礎(chǔ)的用戶信息,需要走注意的是 這些信息暴露在 User.h 中 但是不允許 其它類修改 需要 加上 readonly 關(guān)鍵字 但是在User.m文件中 定義同樣名字的屬性 但是去掉 readonly 關(guān)鍵字 這樣就保證 只在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 類中 添加 登錄與注冊的網(wǎng)絡(luò)請求 滤蝠。一般請求結(jié)束 數(shù)據(jù)以json 形式返回 通過UserManager類 將json 數(shù)據(jù)轉(zhuǎn)化為 User 類中信息到千,然后在使用的時候 獲取 User類來進(jìn)行各種用戶信息的獲取和使用
以登錄 來講述

- (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) {
                 
                                       //添加模擬的數(shù)據(jù) 實際操作中 是回傳的
                                       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 信息轉(zhuǎn)化為 User類 中各個屬性的值 需要注意的是 User 類一般需要本地化存儲 因為在登錄成功之后 好多地方需要 User的信息 本地化存儲之后 可以方便的獲取User信息 包晰。User信息存儲方法有很多 簡單的可以使用 NSUserDefaults的方式 也可以文件形式 就是writeToFile 尝艘。對于存儲 User類 需要先進(jìn)行 歸檔 將User類信息轉(zhuǎn)化為 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信息 但是 偶爾會出現(xiàn) 存儲的User信息丟失的現(xiàn)象 所以改用 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好多頁面都會根據(jù)用戶是否登錄顯示不同的頁面 或者進(jìn)行不同的邏輯操作
所以一般 會添加 用戶是否登錄的屬性
@property (nonatomic, assign, readonly) BOOL isAlreadyLogin;
注意屬性 必須是 readonly 防止被代碼不規(guī)范的小伙伴在其它地方修改

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

此處只是簡單的判斷是否登錄邏輯 背亥,如果需要可以做其它更加嚴(yán)謹(jǐn)?shù)呐袛?br> 使用的時候 直接獲取 通過 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];
    
}

這就是基礎(chǔ)User類與UserManager類的大部分邏輯 歡迎各位批評指正 簡單的的demo代碼地址如下
https://coding.net/u/liwb/p/UserProject/git/tree/master/UserProduct?public=true

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末秒际,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子狡汉,更是在濱河造成了極大的恐慌娄徊,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件盾戴,死亡現(xiàn)場離奇詭異寄锐,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)捻脖,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進(jìn)店門锐峭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來中鼠,“玉大人可婶,你說我怎么就攤上這事≡停” “怎么了矛渴?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長惫搏。 經(jīng)常有香客問我具温,道長,這世上最難降的妖魔是什么筐赔? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任铣猩,我火速辦了婚禮,結(jié)果婚禮上茴丰,老公的妹妹穿的比我還像新娘达皿。我一直安慰自己,他們只是感情好贿肩,可當(dāng)我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布峦椰。 她就那樣靜靜地躺著,像睡著了一般汰规。 火紅的嫁衣襯著肌膚如雪汤功。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天溜哮,我揣著相機(jī)與錄音滔金,去河邊找鬼色解。 笑死,一個胖子當(dāng)著我的面吹牛餐茵,可吹牛的內(nèi)容都是我干的冒签。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼钟病,長吁一口氣:“原來是場噩夢啊……” “哼萧恕!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起肠阱,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤票唆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后屹徘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體走趋,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年噪伊,在試婚紗的時候發(fā)現(xiàn)自己被綠了簿煌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡鉴吹,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出豆励,到底是詐尸還是另有隱情,我是刑警寧澤技扼,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布剿吻,位于F島的核電站串纺,受9級特大地震影響造垛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜办斑,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一乡翅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧尚洽,春花似錦靶累、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽侧到。三九已至匠抗,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間心软,已是汗流浹背著蛙。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留顷蟆,地道東北人腐魂。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓削樊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親甸箱。 傳聞我的和親對象是個殘疾皇子迅脐,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容