I want to save and fetch UIMenuElement state in userdefaults. I have written the following code. Is it the right way to save. Or the code can be improved?
private func addMenuControlForSubtitles() {
let actionState: UIMenuElement.State = UserDefaults.standard.value(forKey: "captionState") as! UIMenuElement.State
let onAction = UIAction(title: Constants.Playback.subtitlesOnTitle, state: actionState) { [weak self] action in
self?.subtitlesLabel.isHidden = false
action.state = .on
UserDefaults.standard.set(action.state, forKey: "captionState")
}
let offAction = UIAction(title: Constants.Playback.subtitlesOffTitle, state: actionState) { [weak self] action in
self?.subtitlesLabel.isHidden = true
action.state = .off
UserDefaults.standard.set(action.state, forKey: "captionState")
}
/// Create the submenu.
let submenu = UIMenu(title: Constants.Playback.subtitlesMenuTitle,
options: [.displayInline, .singleSelection],
children: [onAction, offAction])
let captions = UIImage(systemName: "captions.bubble")
subtitlesMenu = UIMenu(title: Constants.Playback.productCardMenuTitle, image: captions, children: [submenu])
/// set initial state to hidden subtitles.
offAction.state = .on
subtitlesLabel.isHidden = true
/// set icon in transport bar menu.
subtitlesMenu = UIMenu(title: Constants.Playback.productCardMenuTitle, image: captions, children: [submenu])
#if os(tvOS)
if let subtitlesMenu = subtitlesMenu {
playerViewController.transportBarCustomMenuItems.append(subtitlesMenu)
}
#endif
}
Also I want to remove the userdeafult data before killing the app.
user23492857 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.
-
First of all, it will be better to move this business logic to a separate class with a hardcoded key as a constant
class UserDefaultsManager { static let shared = UserDefaultsManager() private let captionStateKey = "captionState" func getCaptionState() -> UIMenuElement.State? { return UserDefaults.standard.value(forKey: captionStateKey) as? UIMenuElement.State } func setCaptionState(_ state: UIMenuElement.State) { UserDefaults.standard.set(state, forKey: captionStateKey) } // Method to clear specific UserDefaults keys func clearUserDefaults() { UserDefaults.standard.removeObject(forKey: captionStateKey) } }
-
Forced downcasting is really dangerous (it can crash the app when there is no element). Try to use optional with default values
as! UIMenuElement.State
Like:
let actionState = UserDefaultsManager.shared.getCaptionState() ?? .off
- To clear UserDefault before killing the app, you should call an additional function from step on in the AppDelegate
func applicationWillTerminate(_ application: UIApplication) {
// Clear UserDefaults data before the app is terminated
UserDefaultsManager.shared.clearUserDefaults()
}