我正在开发一个应用程序,登录和移至主ViewController时遇到问题。
目标:如果用户尚未登录,则登录到CannabisListViewController之后,显示LoginViewController。
现在,当我在模拟器中选择“登录”按钮时,令牌和令牌的到期日期将打印在标题中。我还验证了后端会生成新令牌。
API响应
Server WSGIServer/0.2 CPython/3.7.2
Set-Cookie csrftoken=XelHDMTehmhJxLe5q6uqDYCymZV1iUaKNzRqtOcYYrmMvNkKTnuRbkjHEM2LR8Xo; expires=Fri, 26 Feb 2021 03:58:03 GMT; Max-Age=31449600; Path=/; SameSite=Lax, sessionid=5cu84ccaquq46ga8kazfjequ136y24g1; expires=Fri, 13 Mar 2020 03:58:03 GMT; HttpOnly; Max-Age=1209600; Path=/; SameSite=Lax
Date Fri, 28 Feb 2020 03:58:03 GMT
Content-Type application/json
Content-Length 50
Vary Accept, Cookie
X-Frame-Options SAMEORIGIN
Allow POST, OPTIONS
后端:Django / Django Rest Framework和Django Rest Auth
我现在在哪里:我也在使用UserDefaults存储我认为是令牌的内容,但是我不确定是否正确实现了令牌或如何存储令牌,因此我可以检查它是否存在并基于此更改ViewController。 >
SceneDelegate
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { // IF USER IS LOGGED IN if let _ = userToken?.key { // CREATE TAB BAR // let tabController = UITabBarController() // Instantiate the storyboards let cannabisStoryboard = UIStoryboard(name: "Cannabis", bundle: nil) let profileStoryboard = UIStoryboard(name: "Profile", bundle: nil) // Instantiate the view controllers to storyboards let cannabisVC = cannabisStoryboard.instantiateViewController(withIdentifier: "Cannabis") as! CannabisViewController let profileVC = profileStoryboard.instantiateViewController(withIdentifier: "Profile") as! ProfileViewController // Displays the items in below order in tab bar let vcData: [(UIViewController, UIImage, UIImage)] = [ (cannabisVC, UIImage(named: "Cannabis_icon")!, UIImage(named: "Cannabis_icon_selected")!), (profileVC, UIImage(named: "Profile_icon")!, UIImage(named: "Profile_icon_selected")!), ] let vcs = vcData.map { (vc, defaultImage, selectedImage) -> UINavigationController in let nav = UINavigationController(rootViewController: vc) nav.tabBarItem.image = defaultImage nav.tabBarItem.selectedImage = selectedImage return nav } tabController.viewControllers = vcs tabController.tabBar.isTranslucent = false tabController.delegate = tabBarDelegate // Disables rendering for tab bar images if let items = tabController.tabBar.items { for item in items { if let image = item.image { item.image = image.withRenderingMode(UIImage.RenderingMode.alwaysOriginal) } if let selectedImage = item.selectedImage { item.selectedImage = selectedImage.withRenderingMode(UIImage.RenderingMode.alwaysOriginal) } // Hides title item.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0) } } // Customize Navigation bar UINavigationBar.appearance().backgroundColor = UIColor(rgb: 0x00ffcc) // window?.rootViewController = tabController self.window?.makeKeyAndVisible() // CREATE TAB BAR // } else { let loginStoryboard = UIStoryboard(name: "Login", bundle: nil) let loginViewController = loginStoryboard.instantiateViewController(withIdentifier: "Login") as! LoginViewController window?.rootViewController = loginViewController } guard let _ = (scene as? UIWindowScene) else { return }
LoginViewController
(这基本上是场景委托,但是我打算使用它来在ProfileViewController中登录和注销用户)import UIKit class LoginViewController: UIViewController { // MARK: - Outlets @IBOutlet var usernameTextField: UITextField! @IBOutlet var passwordTextField: UITextField! @IBOutlet var loginButton: UIButton! // MARK: - Properties let rest = APIClient() override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } // MARK: - Actions @IBAction func loginButtonDidTouch(_ sender: Any) { guard let username = usernameTextField.text else { return } guard let password = passwordTextField.text else { return } // MARK: URL guard let url = URL(string: APIClient.shared.loginURL) else { return } // rest.requestHttpHeaders.add(value: "application/x-www-form-urlencoded", forKey: "Content-Type") rest.requestHttpHeaders.add(value: "application/json", forKey: "Content-Type") rest.httpBodyParameters.add(value: "\(username)", forKey: "username") rest.httpBodyParameters.add(value: "\(password)", forKey: "password") rest.makeRequest(toURL: url, withHttpMethod: .post) { (results) in // MARK: Response print("\n\n### Response HTTP Headers ###\n") if let response = results.response { for (key, value) in response.headers.allValues() { print(key, value) } } print("\n\n### End Response HTTP Headers ###\n") // MARK: Data if let data = results.data { let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase guard let item = try? decoder.decode(CustomUser.self, from: data) else { return } print(item.key) let userAuthToken = item.key UserDefaults.standard.set(userAuthToken, forKey: "key") Helper.login() } else { print("Unable to serialize data") } DispatchQueue.main.async { let spinner = UIActivityIndicatorView(style: .medium) spinner.startAnimating() spinner.frame = CGRect(x: 0, y: 0, width: 5, height: 44) } } print(username) print(password) } }
Helper Function
登录/退出功能
(如果有人想要额外的挑战,我还会得到TabBarDelegate的弱参考警告)class Helper { class func login() { let tabController = UITabBarController() // Instantiate the storyboards let cannabisStoryboard = UIStoryboard(name: "Cannabis", bundle: nil) let profileStoryboard = UIStoryboard(name: "Profile", bundle: nil) // Instantiate the view controllers to storyboards let cannabisVC = cannabisStoryboard.instantiateViewController(withIdentifier: "Cannabis") as! CannabisViewController let profileVC = profileStoryboard.instantiateViewController(withIdentifier: "Profile") as! ProfileViewController // Displays the items in below order in tab bar let vcData: [(UIViewController, UIImage, UIImage)] = [ (cannabisVC, UIImage(named: "Cannabis_icon")!, UIImage(named: "Cannabis_icon_selected")!), (profileVC, UIImage(named: "Profile_icon")!, UIImage(named: "Profile_icon_selected")!), ] let vcs = vcData.map { (vc, defaultImage, selectedImage) -> UINavigationController in let nav = UINavigationController(rootViewController: vc) nav.tabBarItem.image = defaultImage nav.tabBarItem.selectedImage = selectedImage return nav } tabController.viewControllers = vcs tabController.tabBar.isTranslucent = false tabController.delegate = TabBarDelegate() (Weak reference warning here) // Disables rendering for tab bar images if let items = tabController.tabBar.items { for item in items { if let image = item.image { item.image = image.withRenderingMode(UIImage.RenderingMode.alwaysOriginal) } if let selectedImage = item.selectedImage { item.selectedImage = selectedImage.withRenderingMode(UIImage.RenderingMode.alwaysOriginal) } // Hides title item.imageInsets = UIEdgeInsets(top: 6, left: 0, bottom: -6, right: 0) } } // Customize Navigation bar UINavigationBar.appearance().backgroundColor = UIColor(rgb: 0x00ffcc) // let appDelegate = UIApplication.shared.delegate as! AppDelegate guard let window = appDelegate.window else { return } window.rootViewController = tabController } class func logout() { let loginStoryboard = UIStoryboard(name: "Login", bundle: nil) let loginViewController = loginStoryboard.instantiateViewController(withIdentifier: "Login") as! LoginViewController let appDelegate = UIApplication.shared.delegate as! AppDelegate guard let window = appDelegate.window else { return } window.rootViewController = loginViewController } }
用户模型
如前所述,当我在LoginViewController中选择“登录”按钮时,令牌信息会打印出来,但登录屏幕永远不会移至应用程序的主要部分。我假设错误出在将令牌存储在UserDelegate中并验证它是否确实存在的地方,但是我可能是错的。struct CustomUser: Codable { static var current: CustomUser! var id: Int var username: String var password: String var email: String var photo: URL var token: String var key: String }
会发生什么
[我曾尝试搜索Google,但主要是在Auth0(我对现在要做的事情有了更好的了解之后,计划在以后实施)和FireBase上找到教程。
[如果有更好的方法来实现我想做的事情,我也愿意尝试一下。如果您参考了我可以查看的教程(并保存以供以后使用),请分享!
提前感谢!
我正在开发一个应用程序,登录和移至主ViewController时遇到问题。目标:如果用户尚未登录,则登录后将其登录到...
guard let window = appDelegate.window else { return }
这将作为appDelegate.window为nil返回。