控制器:
-主视图控制器(TabBarViewController)
-访客视图控制器(UITableViewController)
-欢迎视图控制器(UIViewController)
-OAthen授权视图控制器(UIViewController)
-子视图控制器(UITableViewController)
逻辑关系:
未登录状态下打开App--->访客视图
访客视图点击登录按钮-->OAthen授权界面
OAthen授权后-->欢迎视图控制器(dismiss OAthen控制器时发布通知,切换根控制器)
欢迎视图控制器结束-->主控制器(动画结束后欢迎视图控制器再次发布通知,切换根控制器)
主控制器下的子控制器继承自访客视图控制器,访客视图控制器通过是否登录标识判断显示登录或未登录视图界面
AppDelegate中代码示例:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
//设置主题颜色
setThemeColor()
//设置window
window = UIWindow(frame: UIScreen.mainScreen().bounds)
//设置背景色
window?.backgroundColor = UIColor.whiteColor()
//设置根控制器
setupRootViewController()
//设置主窗口并显示
window?.makeKeyAndVisible()
//监听通知
NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(changeRootViewController(_:)), name: "changeTootViewControllerNotification", object: nil)
return true
}
//设置根控制器
func setupRootViewController() -> Void {
if JSUserAccountTools.sharedTools.isLogin {
//如果用户已登录,根控制器是欢迎界面
window?.rootViewController = JSWelcomeViewController()
}else {
//如果用户未登录,根控制器是访客界面
window?.rootViewController = JSTabBarController()
}
}
//切换根控制器
func changeRootViewController(notic: NSNotification) -> Void {
if notic.object == nil {
window?.rootViewController = JSWelcomeViewController()
}else {
window?.rootViewController = JSTabBarController()
}
}
private func setThemeColor() -> Void{
UITabBar.appearance().tintColor = THEMECOLOR
UINavigationBar.appearance().tintColor = THEMECOLOR
}
deinit{
//移除监听对象
NSNotificationCenter.defaultCenter().removeObserver(self)
}
欢迎视图控制器代码:
import UIKit
import SDWebImage
class JSWelcomeViewController: UIViewController {
private lazy var backgroundImageView: UIImageView = UIImageView(imgName: "ad_background")
private lazy var headImageView: UIImageView = {
let img = UIImageView()
img.layer.cornerRadius = 45
img.layer.borderColor = THEMECOLOR.CGColor
img.layer.borderWidth = 3
img.clipsToBounds = true
img.sd_setImageWithURL(NSURL(string: JSUserAccountTools.sharedTools.userAccount?.avatar_large ?? ""), placeholderImage: UIImage(named: "avatar_default_big"))
return img
}()
private lazy var messageLabel: UILabel = {
let lab = UILabel()
lab.alpha = 0.01
lab.text = "欢迎回来"
lab.font = UIFont.systemFontOfSize(18)
lab.textColor = UIColor.grayColor()
lab.textAlignment = NSTextAlignment.Center
return lab
}()
override func viewDidLoad() {
super.viewDidLoad()
setUI()
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.headImageView.snp_updateConstraints { (make) in
make.top.equalTo(self.view).offset(100)
}
//更改头像的约束(动画)
UIView.animateWithDuration(2.5, delay: 1.5, usingSpringWithDamping: 0.7, initialSpringVelocity: 0, options: [], animations: {
self.view.layoutIfNeeded()
}) { (finished) in
UIView.animateWithDuration(0.25, animations: {
self.messageLabel.alpha = 1
}, completion: { (finished) in
//切换根控制器
NSNotificationCenter.defaultCenter().postNotificationName("changeTootViewControllerNotification", object:"welcome")
})
}
}
//设置视图
private func setUI() -> Void {
//添加控件
view.addSubview(headImageView)
view.addSubview(messageLabel)
//设置约束
headImageView.snp_makeConstraints { (make) in
make.top.equalTo(view).offset(400)
make.centerX.equalTo(view)
make.size.equalTo(CGSizeMake(90, 90))
}
messageLabel.snp_makeConstraints { (make) in
make.top.equalTo(headImageView.snp_bottom).offset(16)
make.centerX.equalTo(view)
}
}
override func loadView() {
view = backgroundImageView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
OAthen视图控制器代码:
import UIKit
import SVProgressHUD
import AFNetworking
class JSOAuthViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//设置导航栏按钮
setupNav()
}
// MARK: - 设置导航栏按钮
private func setupNav ()->() {
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "取消", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(JSOAuthViewController.cancelClick))
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "自动填充", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(JSOAuthViewController.autoFillClick))
}
//左侧导航按钮点击事件
@objc private func cancelClick() -> Void {
dismissViewControllerAnimated(true, completion: nil)
}
//右侧导航按钮点击事件
@objc private func autoFillClick ()->() {
let jsString = "document.getElementById('userId').value='授权账户',document.getElementById('passwd').value='密码'"
webView.stringByEvaluatingJavaScriptFromString(jsString)
}
override func loadView() {
view = webView
view.backgroundColor = UIColor.whiteColor()
}
// MARK: - 懒加载控件
private lazy var webView: UIWebView = {
let view = UIWebView()
let url = NSURL(string: "https://api.weibo.com/oauth2/authorize?client_id=\(APPKEY)&redirect_uri=\(REDIRECT_URI)")!
let request = NSURLRequest(URL: url)
view.loadRequest(request)
view.delegate = self;
return view
}()
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension JSOAuthViewController : UIWebViewDelegate{
//开始加载
func webViewDidStartLoad(webView: UIWebView) {
SVProgressHUD.show()
}
//加载完成
func webViewDidFinishLoad(webView: UIWebView) {
SVProgressHUD.dismiss()
}
//加载失败
func webView(webView: UIWebView, didFailLoadWithError error: NSError?) {
}
//将要加载request
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
let urlString = request.URL?.absoluteString
if let u = urlString where u.hasPrefix(REDIRECT_URI) {
//请求参数键值对
let query = request.URL?.query
if let q = query {
let codeString = q.substringFromIndex("code=".endIndex)
//请求数据
oauthLoadUser(codeString)
return false
}
}
return true
}
}
extension JSOAuthViewController{
private func oauthLoadUser(code: String) -> Void {
//请求数据,获取access_token等信息
JSNetworkTool.sharedNetworkTool.oauthLoadUserAccount(code, success: { (response) in
guard let res = response as? [String: AnyObject] else {
return
}
//字典转模型
let userAccount = JSUserAccountModel(dict: res)
//请求用户信息
self.loadUserInfo(userAccount)
}) { (error) in
print(error)
}
}
//请求用户信息
func loadUserInfo(userAccount: JSUserAccountModel) -> Void {
JSNetworkTool.sharedNetworkTool.loadUserInfo(userAccount, success: { (response) in
//判断是否有值,而且可以转成字典
guard let res = response as? [String: AnyObject] else {
return
}
userAccount.setValue(res["avatar_large"], forKey: "avatar_large")
userAccount.setValue(res["screen_name"], forKey: "screen_name")
// userAccount.avatar_large = res["avatar_large"] as? String
// userAccount.screen_name = res["screen_name"] as? String
JSUserAccountTools.sharedTools.saveUserAccount(userAccount: userAccount)
//将OAuth控制器移除
self.dismissViewControllerAnimated(false, completion: {
//关闭指示器
SVProgressHUD.dismiss()
//切换根控制器
NSNotificationCenter.defaultCenter().postNotificationName("changeTootViewControllerNotification", object: nil)
})
}) { (error) in
print(error)
}
}
}
访客视图控制器:
class JSVistorTableViewController: UITableViewController {
//标识用户是否登录
let isLogin: Bool = JSUserAccountTools.sharedTools.isLogin
//VistorView
var vistorView: JSVistorView?
override func loadView() {
if isLogin {
//已登录
super.loadView()
}else{
//未登录
setupVistorView()
}
}
// MARK: - 设置导航栏
private func setupNav()-> Void{
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "登录", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(loginClick))
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "注册", style: UIBarButtonItemStyle.Plain, target: self, action: #selector(loginClick))
}
// MARK: - 导航栏按钮点击事件
@objc private func loginClick() -> Void {
let oauthVc = JSOAuthViewController()
let naVC = JSNavigationController(rootViewController: oauthVc)
presentViewController(naVC, animated: true, completion: nil)
}
// MARK: - 设置访客视图
private func setupVistorView() -> Void {
vistorView = JSVistorView()
view = vistorView
vistorView?.closure = {[weak self] in
self?.loginClick()
}
//设置导航栏按钮
setupNav()
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
将访客视图UI搭建抽取为单独一个类,并提供对外修改UI的方法
// MARK: - 供外界调用的方法,修改视图信息
func setupVistorViewInfo(imgName: String?,title: String?) -> Void {
if let img = imgName,let tit = title {
//非主页
centerImageView.image = UIImage(named: img)
messageLabel.text = tit
feedImageView.removeFromSuperview()
}else{
//主页:设置动画
setupAnim()
}
}
将OAthen授权获得的数据,存放到一个单例类中,同时做本地化处理,并存放是否登录的标识,防止每一次使用信息都对沙盒进行操作
class JSUserAccountTools: NSObject {
//全局访问点
static let sharedTools: JSUserAccountTools = JSUserAccountTools()
var userAccount: JSUserAccountModel?
var accessToken: String?{
if userAccount?.access_token == nil {
//如果访问令牌为nil,代表未登录,返回nil
return nil
}else {
if userAccount?.expires_Date?.compare(NSDate()) == NSComparisonResult.OrderedDescending {
//访问令牌不为nil,与当前时间比较为降序,未过期,代表登录
return userAccount?.access_token
}else {
//如果访问令牌不为nil,但是时间过期,代表未登录
return nil
}
}
}
//判断用户是否登录标识
var isLogin: Bool {
//如果access_token为nil,代表没登录(如果accessToken为nil,代表isLogin = false)
return accessToken != nil
}
override init() {
super.init()
userAccount = getUserAccount()
}
let path = (NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true).last! as NSString).stringByAppendingPathComponent("userAccount.archiver")
//保存对象
func saveUserAccount(userAccount userAcc: JSUserAccountModel) -> Void {
self.userAccount = userAcc
//归档
NSKeyedArchiver.archiveRootObject(userAcc, toFile: path)
}
//获取对象
func getUserAccount() -> JSUserAccountModel? {
//解档
let userAccount = NSKeyedUnarchiver.unarchiveObjectWithFile(path) as? JSUserAccountModel
return userAccount
}
}