iOS开发:根据用户登录状态切换菜单内容求助
解决根据登录状态动态切换菜单的问题
你的问题核心在于settings数组是静态初始化的——它只在SettingLauncher对象创建时计算一次,之后哪怕登录状态改变,这个数组也不会自动更新。要实现菜单随登录状态动态切换,我们需要让菜单选项每次显示时都根据当前登录状态重新生成。
解决方案步骤:
1. 将settings改为计算属性
把原来的常量数组改成计算属性,这样每次访问settings时都会重新读取Keychain的登录状态并生成对应菜单:
// 替换原来的let settings: [Setting] = { ... }() var settings : [Setting] { let isLoggedIn = KeychainWrapper.standard.string(forKey: "myKey") == "true" // 定义所有可能的菜单选项 let settingOne = Setting(name: .Profile, imageName: "profile-icon") let settingTwo = Setting(name: .Login, imageName: "login-icon") let settingThree = Setting(name: .Orders, imageName: "orders-icon") let settingFour = Setting(name: .Category, imageName: "category-icon") let settingSix = Setting(name: .SignOut, imageName: "login-icon") // 根据登录状态返回对应菜单 if isLoggedIn { return [settingOne, settingThree, settingFour, settingSix] } else { return [settingTwo, settingThree, settingFour] } }
2. 修正showHambuger方法,确保显示最新菜单
在显示菜单前先刷新CollectionView的数据,保证展示的是最新的选项:
func showHambuger(){ guard let window = UIApplication.shared.keyWindow else { return } blackView.backgroundColor = UIColor(white: 0, alpha: 0.5) blackView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleCancel))) // 先刷新CollectionView数据,确保菜单是最新的 collectionView.reloadData() window.addSubview(blackView) window.addSubview(collectionView) let height = CGFloat(settings.count) * cellHeight let y = window.frame.height - height collectionView.frame = CGRect(x: 0, y: window.frame.height, width: window.frame.width, height: height) blackView.frame = window.frame blackView.alpha = 0 UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut) { self.blackView.alpha = 1 self.collectionView.frame = CGRect(x: 0, y: y, width: self.collectionView.frame.width, height: self.collectionView.frame.height) } }
3. 修复handleCancel的参数问题
原来的handleCancel方法参数在手势触发时会报错(手势不会传递Setting参数),我们拆分方法处理两种场景:
// 处理黑色区域点击(无Setting参数) @objc func handleCancel() { animateMenuDismissal() } // 处理菜单选项点击(带Setting参数) private func handleCancelWithSetting(_ setting: Setting) { animateMenuDismissal { completed in if setting.name != .Cancel { self.defaultController?.showControllerForSetting(setting: setting) } } } // 提取动画逻辑为公共方法 private func animateMenuDismissal(completion: ((Bool) -> Void)? = nil) { UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut) { self.blackView.alpha = 0 if let window = UIApplication.shared.keyWindow { self.collectionView.frame = CGRect(x: 0, y: window.frame.height, width: self.collectionView.frame.width, height: self.collectionView.frame.height) } } completion: { completed in completion?(completed) } } // 更新didSelectItemAt方法 func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let setting = settings[indexPath.item] handleCancelWithSetting(setting) }
4. 确保登录/登出操作更新Keychain
在你的登录/登出逻辑中,确保成功后正确修改Keychain的值:
// 登录成功时 KeychainWrapper.standard.set("true", forKey: "myKey") // 登出成功时 KeychainWrapper.standard.removeObject(forKey: "myKey") // 或者设置为"false",根据你的判断逻辑调整
这样修改后,每次点击汉堡按钮显示菜单时,都会重新读取当前登录状态并生成对应的菜单选项,完美实现动态切换的效果。
内容的提问来源于stack exchange,提问作者Kaveh Naseri
相关产品推荐
相关产品推荐

