新浪微博客户端(15)-保存用户名和密码

检测本地是否保存有用户的密码。如果有,则下次自动登录;如果没有,则提示用户登录。

DJAccount.h

#import <Foundation/Foundation.h>

@interface DJAccount : NSObject


/** 访问token */
@property (nonatomic,copy) NSString *access_token;
/** 过期时间,单位是秒 */
@property (nonatomic,copy) NSNumber *expires_in;
/** 当前user id */
@property (nonatomic,copy) NSString *uid;
/** 当前帐号创建时间 */
@property (nonatomic,strong) NSDate *create_time;

+ (instancetype)accountWithDictionary:(NSDictionary *)dict;


@end

DJAccount.m

#import "DJAccount.h"


@interface DJAccount() <NSCoding>

@end

@implementation DJAccount



+ (instancetype)accountWithDictionary:(NSDictionary *)dict {

    DJAccount *account = [[DJAccount alloc] init];
    
    account.access_token = dict[@"access_token"];
    account.expires_in = dict[@"expires_in"];
    account.uid = dict[@"uid"];
    account.create_time = [NSDate date];
    
    return account;
}



- (void)encodeWithCoder:(NSCoder *)encoder {

    [encoder encodeObject:self.access_token forKey:@"access_token"];
    [encoder encodeObject:self.expires_in forKey:@"expires_in"];
    [encoder encodeObject:self.uid forKey:@"uid"];
    [encoder encodeObject:self.create_time forKey:@"create_time"];
    
}

- (instancetype)initWithCoder:(NSCoder *)decoder {

    if (self = [super init]) {
        self.access_token = [decoder decodeObjectForKey:@"access_token"];
        self.expires_in = [decoder decodeObjectForKey:@"expires_in"];
        self.uid = [decoder decodeObjectForKey:@"uid"];
        self.create_time = [decoder decodeObjectForKey:@"create_time"];
    }
    return self;

}


@end

DJAccountTool.h

#import <Foundation/Foundation.h>

@class DJAccount;

@interface DJAccountTool : NSObject


+ (void)saveAccount:(DJAccount *)account;

+ (DJAccount *)account;


@end

DJAccountTool.m

#import "DJAccountTool.h"
#import "DJAccount.h"

#define DJAccountPath [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"account.archiver"]


@implementation DJAccountTool



+ (void)saveAccount:(DJAccount *)account {

    [NSKeyedArchiver archiveRootObject:account toFile:DJAccountPath];
    
}



+ (DJAccount *)account {
    
    
    DJAccount *account = [NSKeyedUnarchiver unarchiveObjectWithFile:DJAccountPath];
    // 判断当前帐号是否过期
    long long expires_in = [account.expires_in longLongValue];
    // 获得过期时间
    NSDate *expires_time = [account.create_time dateByAddingTimeInterval:expires_in];
    // 获得当前时间
    NSDate *now_time = [NSDate date];
    // 如果now大于expires_time,则代表过期
    NSComparisonResult result = [expires_time compare:now_time];
    if (result != NSOrderedDescending) {
        return nil;
    }
    return account;
}


@end

UIWindow+Extension.m

#import "UIWindow+Extension.h"
#import "DJMainViewController.h"
#import "DJNewFeatureViewController.h"

@implementation UIWindow (Extension)

+ (void)switchRootViewController {

    // 获取当前主窗口
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
 
    NSString *versionKey = @"CFBundleVersion";
    // 从Info.plist中读取当前软件版本号
    NSString *currentVersion = [NSBundle mainBundle].infoDictionary[versionKey];
    // 从沙盒中读取保存的历史版本号
    NSString *lastVersion = [[NSUserDefaults standardUserDefaults] objectForKey:versionKey];
    
    // 判断当前软件版本号是否与沙盒中保存的一致
    if ([currentVersion isEqualToString:lastVersion]) { // 版本号一致
        DJMainViewController *mainVc = [[DJMainViewController alloc] init];
        window.rootViewController = mainVc;
    } else { // 版本号不一致,显示新特性,并将当前软件版本号保存到沙盒
        /* 1.显示新特性 */
        DJNewFeatureViewController *newVc = [[DJNewFeatureViewController alloc] init];
        window.rootViewController = newVc;
        /* 2.将当前版本号写入到沙盒 */
        [[NSUserDefaults standardUserDefaults] setValue:currentVersion forKey:versionKey];
        // 立即将内存中的数据同步到沙盒
        [[NSUserDefaults standardUserDefaults] synchronize];
    }

}

@end

AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    
    
    
    // 1. 创建窗口
    self.window = [[UIWindow alloc] init];
    self.window.frame = [UIScreen mainScreen].bounds;
    
    // 2. 显示窗口
    [self.window makeKeyAndVisible];

    // 3. 判断当前帐户是否已经被授权来决定根控制器显示
    DJAccount *account = [DJAccountTool account];
    if (account) { // 之前已经成功授权
        [UIWindow switchRootViewController];
    } else { // 尚未成功授权
       self.window.rootViewController = [[DJOAuthViewController alloc] init];
    }
    
    return YES;
}

DJOAuthViewController.m

#import "DJOAuthViewController.h"
#import "AFNetworking.h"
#import "DJAccount.h"
#import "DJAccountTool.h"
#import "MBProgressHUD+MJ.h"


@interface DJOAuthViewController () <UIWebViewDelegate>

@end

@implementation DJOAuthViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    /* client_id&redirect_uri */
    NSString *client_id = @"249054863";
    NSString *redirect_uri = @"https://www.baidu.com";
    
    UIWebView *webView = [[UIWebView alloc] init];
    webView.frame = self.view.bounds;
    webView.delegate = self;
    
    [self.view addSubview:webView];
    
    NSString *urlString = [NSString stringWithFormat:@"https://api.weibo.com/oauth2/authorize?client_id=%@&redirect_uri=%@",client_id,redirect_uri];
    
    NSURL *url = [NSURL URLWithString:urlString];
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
    
    [webView loadRequest:urlRequest];

}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


#pragma mark - webView 代理方法

- (void)webViewDidStartLoad:(UIWebView *)webView {
    [MBProgressHUD showMessage:@"加载中..."];

}


- (void)webViewDidFinishLoad:(UIWebView *)webView {
    [MBProgressHUD hideHUD];
}


/** 此方法可用于拦截http请求 */
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
    NSString *urlString = request.URL.absoluteString;
    DJLog(@"current access url str : %@",urlString);

    // 1. 判断当前地址是否是回调地址(https://www.baidu.com/?code=27a3d9fb9bbc5d3c20be9ae8e4331b02)
    NSRange range= [urlString rangeOfString:@"code="];
    if (range.length != 0) { // 是回调地址
        // 2.截取code=后面的参数值
        NSUInteger fromIndex = range.location + range.length;
        NSString *code = [urlString substringFromIndex:fromIndex]; // code 就是授权成功的请求标记
        // 3.使用授权成功的请求标记(code)来换取accessToken
        [self getAccessTokenWithCode:code];
        // 4.禁止加载回调地址
        return NO;
    }
    
    
    
    return YES;
}




- (void)getAccessTokenWithCode:(NSString *)code {

    // 1. 创建请求管理者
    AFHTTPSessionManager *requestManager = [AFHTTPSessionManager manager];
    
    // 2. 配置请求参数
    NSString *urlString = @"https://api.weibo.com/oauth2/access_token"; // 请求授权的access_token URL
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    params[@"client_id"] = @"249054863";
    params[@"client_secret"] = @"71d5b761bac9f377af3b938f6d89ba85";
    params[@"grant_type"] = @"authorization_code";
    params[@"code"] = code;
    params[@"redirect_uri"] = @"https://www.baidu.com";
    
    // 3. 发送请求
    [requestManager POST:urlString parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, NSDictionary *  _Nullable dict) {
        
        [MBProgressHUD hideHUD];
        // 1. 将返回的字典转换为模型
        DJAccount *account = [DJAccount accountWithDictionary:dict];
        // 2. 存储当前帐号信息
        [DJAccountTool saveAccount:account];
        // 3. 切换根控制器到DJMainViewController
        [UIWindow switchRootViewController];
        
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        [MBProgressHUD showError:@"授权失败"];
         DJLog(@"failure responseObject: %@",error);
    }];
    
}



@end

最终效果:

 

原文地址:https://www.cnblogs.com/yongdaimi/p/6005673.html