不知道在哪里放置 saveData 以在 Swift 中使用 userDefaults 保存数据
Don't know where to place saveData to save data with userDefaults in Swift
我正在尝试在被用户更改后保存我的数据,我正在从我的模型中保存数据,同时我也在从我的模型中获取数据 class,我想保存数据一旦视图消失,所有数据都将被保存,我可以从我的模型中获取数据(当我再次初始化它时),我有点迷失了实现它的方式:\
这是我的 VC 代码:我在哪里设置我的 tableView 单元格 + 想在那里使用 saveData() :
import UIKit
import PanModal
class FilterTableViewController: UIViewController, UITableViewDelegate,UITableViewDataSource, PanModalPresentable {
//Instance of our ViewModel
private var filterViewModel = FilterViewModel()
//Our Model Instance:
// private var filterModel = FilterModel()
let tableView = UITableView()
var safeArea: UILayoutGuide!
let buttonView = UIView()
var panScrollable: UIScrollView? {
return tableView
}
var albumsPickerIndexPath: IndexPath? // indexPath of the currently shown albums picker in tableview.
// var delegate: FilterTableViewDelegate?
var datesCell = DatesCell()
var selectedAlbumByUser = ""
// var userFilter: FilterModel?
override func viewDidLoad() {
super.viewDidLoad()
safeArea = view.layoutMarginsGuide
setupTableView()
self.tableView.dataSource = self
self.tableView.delegate = self
setupButtonView()
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
// MARK: - Views Configurations
func setupTableView() {
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor,constant: 120).isActive = true
tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
tableView.separatorStyle = .singleLine
tableView.isScrollEnabled = false
tableView.allowsSelection = true
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 600
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
tableView.tableFooterView = UIView(frame: .zero)
}
func setupButtonView() {
view.addSubview(buttonView)
buttonView.translatesAutoresizingMaskIntoConstraints = false
buttonView.backgroundColor = .white
buttonView.layer.cornerRadius = 15;
// buttonView.clipsToBounds = true
NSLayoutConstraint.activate([
buttonView.topAnchor.constraint(equalTo: tableView.bottomAnchor),
buttonView.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor,constant: 10),
buttonView.leadingAnchor.constraint(equalTo: view.leadingAnchor,constant: 16),
buttonView.trailingAnchor.constraint(equalTo: view.trailingAnchor,constant: -16),
buttonView.widthAnchor.constraint(equalToConstant: 100),
buttonView.heightAnchor.constraint(equalToConstant: 40),
])
let applyFiltersButton = UIButton()
applyFiltersButton.setTitle("Apply Filters", for: .normal)
applyFiltersButton.setTitleColor(.white, for: .normal)
applyFiltersButton.layer.cornerRadius = 15;
// myFirstButton.clipsToBounds = true
applyFiltersButton.backgroundColor = #colorLiteral(red: 0.1957295239, green: 0.6059523225, blue: 0.960457623, alpha: 1)
applyFiltersButton.contentHorizontalAlignment = .center;
applyFiltersButton.titleLabel?.font = UIFont(name: "Helvetica", size:16)
self.buttonView.addSubview(applyFiltersButton)
applyFiltersButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
applyFiltersButton.topAnchor.constraint(equalTo: buttonView.topAnchor),
applyFiltersButton.bottomAnchor.constraint(equalTo: buttonView.bottomAnchor),
applyFiltersButton.leadingAnchor.constraint(equalTo: buttonView.leadingAnchor),
applyFiltersButton.trailingAnchor.constraint(equalTo: buttonView.trailingAnchor),
applyFiltersButton.widthAnchor.constraint(equalToConstant: 100),
applyFiltersButton.heightAnchor.constraint(equalToConstant: 40),
applyFiltersButton.centerXAnchor.constraint(equalTo: buttonView.centerXAnchor),
applyFiltersButton.centerYAnchor.constraint(equalTo: buttonView.centerYAnchor)
])
}
func indexPathToInsertDatePicker(indexPath: IndexPath) -> IndexPath {
if let albumsPickerIndexPath = albumsPickerIndexPath, albumsPickerIndexPath.row < indexPath.row {
return indexPath
} else {
return IndexPath(row: indexPath.row + 1, section: indexPath.section)
}
}
// MARK: - UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// If datePicker is already present, we add one extra cell for that
if albumsPickerIndexPath != nil {
return 5 + 1
} else {
return 5
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.row {
case 0:
let byActivityCell = UINib(nibName: "byActivityCell",bundle: nil)
self.tableView.register(byActivityCell,forCellReuseIdentifier: "byActivityCell")
let activityCell = tableView.dequeueReusableCell(withIdentifier: "byActivityCell", for: indexPath) as! byActivityCell
activityCell.selectionStyle = .none
activityCell.activityDelegate = filterViewModel
return activityCell
case 1:
let byTypeCell = UINib(nibName: "ByType",bundle: nil)
self.tableView.register(byTypeCell,forCellReuseIdentifier: "byTypeCell")
let typeCell = tableView.dequeueReusableCell(withIdentifier: "byTypeCell", for: indexPath) as! ByType
typeCell.selectionStyle = .none
typeCell.byTypeDelegate = filterViewModel
return typeCell
case 2:
let byHashtagsCell = UINib(nibName: "ByHashtags",bundle: nil)
self.tableView.register(byHashtagsCell,forCellReuseIdentifier: "byHashtagsCell")
let hashtagsCell = tableView.dequeueReusableCell(withIdentifier: "byHashtagsCell", for: indexPath) as! ByHashtags
hashtagsCell.selectionStyle = .none
hashtagsCell.byHashtagsDelegate = filterViewModel
return hashtagsCell
case 3:
let byDatesCell = UINib(nibName: "DatesCell",bundle: nil)
self.tableView.register(byDatesCell,forCellReuseIdentifier: "byDatesCell")
let datesCell = tableView.dequeueReusableCell(withIdentifier: "byDatesCell", for: indexPath) as! DatesCell
datesCell.selectionStyle = .none
datesCell.datesTableViewCellDelegate = self
return datesCell
case 4:
let byAlbumCell = UINib(nibName: "AlbumCell",bundle: nil)
self.tableView.register(byAlbumCell,forCellReuseIdentifier: "byAlbumCell")
let albumCell = tableView.dequeueReusableCell(withIdentifier: "byAlbumCell", for: indexPath) as! AlbumCell
// albumCell.configureCell(choosenAlbum: filterViewModel.getSelectedAlbum())
albumCell.selectionStyle = .none
filterViewModel.getAlbum = { selectedAlbum in
albumCell.configureCell(choosenAlbum: selectedAlbum)
}
return albumCell
case 5:
let albumPickerCell = UINib(nibName: "AlbumsPickerTableViewCell", bundle: nil)
self.tableView.register(albumPickerCell, forCellReuseIdentifier: "albumPickerCell")
let albumsPicker = tableView.dequeueReusableCell(withIdentifier: "albumPickerCell", for: indexPath) as! AlbumsPickerTableViewCell
// albumsPicker.albumsPickerCellDelegate = self
albumsPicker.albumsPickerCellDelegate = filterViewModel
return albumsPicker
default:
return UITableViewCell()
}
}
// MARK: TableViewDelegate Methods:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
tableView.beginUpdates()
// 1 - We Delete the UIPicker when the user "Deselect" thr row.
if let datePickerIndexPath = albumsPickerIndexPath, datePickerIndexPath.row - 1 == indexPath.row {
tableView.deleteRows(at: [datePickerIndexPath], with: .fade)
self.albumsPickerIndexPath = nil
let albumCell = tableView.cellForRow(at: indexPath) as! AlbumCell
UIView.animate(withDuration: 1) {
albumCell.arrowPickerView.transform = CGAffineTransform.identity
}
} else {
// 2
// if let datePickerIndexPath = albumsPickerIndexPath {
// tableView.deleteRows(at: [datePickerIndexPath], with: .fade)
// }
let albumCell = tableView.cellForRow(at: indexPath) as! AlbumCell
UIView.animate(withDuration: 1) {
albumCell.arrowPickerView.transform = CGAffineTransform(rotationAngle: .pi)
}
albumsPickerIndexPath = indexPathToInsertDatePicker(indexPath: indexPath)
tableView.insertRows(at: [albumsPickerIndexPath!], with: .fade)
tableView.deselectRow(at: indexPath, animated: true)
}
tableView.endUpdates()
}
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
if indexPath.row == 4 {
return indexPath
} else {
return nil
}
}
}
extension FilterTableViewController: DatesTableViewCellDelegate {
func didButtonFromPressed() {
let pickerController = CalendarPickerViewController(
baseDate: Date(),
selectedDateChanged: { [weak self] date in
guard let self = self else { return }
// self.item.date = date
// self.filterModel.startDate = date
self.tableView.reloadRows(at: [IndexPath(row: 3, section: 0)], with: .fade)
})
present(pickerController, animated: true, completion: nil)
}
func didButtonToPressed() {
//TODO: Present our custom calendar
let calendarController = CalendarPickerViewController(
baseDate: Date(),
selectedDateChanged: { [weak self] date in
guard let self = self else { return }
// self.filterModel.endDate = date
self.tableView.reloadRows(at: [IndexPath(row: 3, section: 0)], with: .fade)
})
self.present(calendarController, animated: true, completion: nil)
}
}
这是我的模型:
import Foundation
import UIKit
class FilterModel {
let userDefaults = UserDefaults.standard
var byActivity: String = ""
var postType: [String] = []
var hashTags: [String] = []
var startDate: Date = Date()
var endDate: Date = Date()
var album: String = ""
init() {
// First we need to fetch the data from the local storeage and insert into the vars:
self.fetchData()
}
deinit {
//Second we need to save the data in the local storeage:
self.saveData()
print("Im being deinited")
}
// MARK: - UserDefaults Section:
//Fetch - Retrieve from NSUserDefaults(local):
func fetchData() {
self.byActivity = userDefaults.string(forKey: k.UserDefaultsSaveKeys.byActivitySaveKey) ?? self.byActivity
self.postType = userDefaults.stringArray(forKey: k.UserDefaultsSaveKeys.postTypeSaveKey) ?? self.postType
self.hashTags = userDefaults.stringArray(forKey: k.UserDefaultsSaveKeys.hashTagsSaveKey) ?? self.hashTags
self.startDate = userDefaults.object(forKey: k.UserDefaultsSaveKeys.startDateSaveKey) as? Date ?? self.startDate
self.endDate = userDefaults.object(forKey: k.UserDefaultsSaveKeys.endDateSaveKey) as? Date ?? self.endDate
self.album = userDefaults.string(forKey: k.UserDefaultsSaveKeys.albumSaveKey) ?? self.album
print("Checking \(userAlreadyExist(kUsernameKey: k.UserDefaultsSaveKeys.albumSaveKey) )")
}
//Save - Save to local(NSUserDefaults):
func saveData() {
userDefaults.set(self.byActivity, forKey: "SavedByActivity")
userDefaults.set(self.postType, forKey: "SavedPostType")
userDefaults.set(self.hashTags, forKey: "SavedHashTags")
userDefaults.set(self.startDate, forKey: "SavedStartDate")
userDefaults.set(self.endDate,forKey: "SavedEndDate")
userDefaults.set(self.album,forKey: k.UserDefaultsSaveKeys.albumSaveKey)
}
//Testing function
func userAlreadyExist(kUsernameKey: String) -> Bool {
return userDefaults.object(forKey: kUsernameKey) != nil
}
}
试试这个?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
filterViewModel.fetchData()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisppear(animated)
filterViewModel.saveData()
}
我建议你检查是否已保存。
userDefaults.string (forKey: k.UserDefaultsSaveKeys.albumSaveKey)
如果仍然存在,则检查密钥:
userDefaults.set (self.byActivity, forKey: "SavedByActivity")
userDefaults.set (self.postType, forKey: "SavedPostType")
userDefaults.set (self.hashTags, forKey: "SavedHashTags")
userDefaults.set (self.startDate, forKey: "SavedStartDate")
userDefaults.set (self.endDate, forKey: "SavedEndDate")
您可以尝试在您的 FilterModel 中编写通用保存方法:
func saveValue(_ value: Any, forKey key: String) {
UserDefaults.standard.set(value, forKey: key)
}
然后像这样在你的委托方法中调用它:
func didButtonToPressed() {
//TODO: Present our custom calendar
let calendarController = CalendarPickerViewController(
baseDate: Date(),
selectedDateChanged: { [weak self] date in
guard let self = self else { return }
self.filterModel.saveValue(date, forKey: "SavedEndDate")
self.tableView.reloadRows(at: [IndexPath(row: 3, section: 0)], with: .fade)
})
self.present(calendarController, animated: true, completion: nil)
}
确保您用于保存值的密钥与您检索它的密钥相同。
在 deinit 中保存数据也不是一个好的做法,因为 deinit 有一些其他目的,当实例被释放以释放内存时调用。这不会在视图从屏幕上消失后立即发生。
我正在尝试在被用户更改后保存我的数据,我正在从我的模型中保存数据,同时我也在从我的模型中获取数据 class,我想保存数据一旦视图消失,所有数据都将被保存,我可以从我的模型中获取数据(当我再次初始化它时),我有点迷失了实现它的方式:\ 这是我的 VC 代码:我在哪里设置我的 tableView 单元格 + 想在那里使用 saveData() :
import UIKit
import PanModal
class FilterTableViewController: UIViewController, UITableViewDelegate,UITableViewDataSource, PanModalPresentable {
//Instance of our ViewModel
private var filterViewModel = FilterViewModel()
//Our Model Instance:
// private var filterModel = FilterModel()
let tableView = UITableView()
var safeArea: UILayoutGuide!
let buttonView = UIView()
var panScrollable: UIScrollView? {
return tableView
}
var albumsPickerIndexPath: IndexPath? // indexPath of the currently shown albums picker in tableview.
// var delegate: FilterTableViewDelegate?
var datesCell = DatesCell()
var selectedAlbumByUser = ""
// var userFilter: FilterModel?
override func viewDidLoad() {
super.viewDidLoad()
safeArea = view.layoutMarginsGuide
setupTableView()
self.tableView.dataSource = self
self.tableView.delegate = self
setupButtonView()
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return .lightContent
}
// MARK: - Views Configurations
func setupTableView() {
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor,constant: 120).isActive = true
tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
tableView.separatorStyle = .singleLine
tableView.isScrollEnabled = false
tableView.allowsSelection = true
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 600
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
tableView.tableFooterView = UIView(frame: .zero)
}
func setupButtonView() {
view.addSubview(buttonView)
buttonView.translatesAutoresizingMaskIntoConstraints = false
buttonView.backgroundColor = .white
buttonView.layer.cornerRadius = 15;
// buttonView.clipsToBounds = true
NSLayoutConstraint.activate([
buttonView.topAnchor.constraint(equalTo: tableView.bottomAnchor),
buttonView.bottomAnchor.constraint(equalTo: safeArea.bottomAnchor,constant: 10),
buttonView.leadingAnchor.constraint(equalTo: view.leadingAnchor,constant: 16),
buttonView.trailingAnchor.constraint(equalTo: view.trailingAnchor,constant: -16),
buttonView.widthAnchor.constraint(equalToConstant: 100),
buttonView.heightAnchor.constraint(equalToConstant: 40),
])
let applyFiltersButton = UIButton()
applyFiltersButton.setTitle("Apply Filters", for: .normal)
applyFiltersButton.setTitleColor(.white, for: .normal)
applyFiltersButton.layer.cornerRadius = 15;
// myFirstButton.clipsToBounds = true
applyFiltersButton.backgroundColor = #colorLiteral(red: 0.1957295239, green: 0.6059523225, blue: 0.960457623, alpha: 1)
applyFiltersButton.contentHorizontalAlignment = .center;
applyFiltersButton.titleLabel?.font = UIFont(name: "Helvetica", size:16)
self.buttonView.addSubview(applyFiltersButton)
applyFiltersButton.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
applyFiltersButton.topAnchor.constraint(equalTo: buttonView.topAnchor),
applyFiltersButton.bottomAnchor.constraint(equalTo: buttonView.bottomAnchor),
applyFiltersButton.leadingAnchor.constraint(equalTo: buttonView.leadingAnchor),
applyFiltersButton.trailingAnchor.constraint(equalTo: buttonView.trailingAnchor),
applyFiltersButton.widthAnchor.constraint(equalToConstant: 100),
applyFiltersButton.heightAnchor.constraint(equalToConstant: 40),
applyFiltersButton.centerXAnchor.constraint(equalTo: buttonView.centerXAnchor),
applyFiltersButton.centerYAnchor.constraint(equalTo: buttonView.centerYAnchor)
])
}
func indexPathToInsertDatePicker(indexPath: IndexPath) -> IndexPath {
if let albumsPickerIndexPath = albumsPickerIndexPath, albumsPickerIndexPath.row < indexPath.row {
return indexPath
} else {
return IndexPath(row: indexPath.row + 1, section: indexPath.section)
}
}
// MARK: - UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// If datePicker is already present, we add one extra cell for that
if albumsPickerIndexPath != nil {
return 5 + 1
} else {
return 5
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.row {
case 0:
let byActivityCell = UINib(nibName: "byActivityCell",bundle: nil)
self.tableView.register(byActivityCell,forCellReuseIdentifier: "byActivityCell")
let activityCell = tableView.dequeueReusableCell(withIdentifier: "byActivityCell", for: indexPath) as! byActivityCell
activityCell.selectionStyle = .none
activityCell.activityDelegate = filterViewModel
return activityCell
case 1:
let byTypeCell = UINib(nibName: "ByType",bundle: nil)
self.tableView.register(byTypeCell,forCellReuseIdentifier: "byTypeCell")
let typeCell = tableView.dequeueReusableCell(withIdentifier: "byTypeCell", for: indexPath) as! ByType
typeCell.selectionStyle = .none
typeCell.byTypeDelegate = filterViewModel
return typeCell
case 2:
let byHashtagsCell = UINib(nibName: "ByHashtags",bundle: nil)
self.tableView.register(byHashtagsCell,forCellReuseIdentifier: "byHashtagsCell")
let hashtagsCell = tableView.dequeueReusableCell(withIdentifier: "byHashtagsCell", for: indexPath) as! ByHashtags
hashtagsCell.selectionStyle = .none
hashtagsCell.byHashtagsDelegate = filterViewModel
return hashtagsCell
case 3:
let byDatesCell = UINib(nibName: "DatesCell",bundle: nil)
self.tableView.register(byDatesCell,forCellReuseIdentifier: "byDatesCell")
let datesCell = tableView.dequeueReusableCell(withIdentifier: "byDatesCell", for: indexPath) as! DatesCell
datesCell.selectionStyle = .none
datesCell.datesTableViewCellDelegate = self
return datesCell
case 4:
let byAlbumCell = UINib(nibName: "AlbumCell",bundle: nil)
self.tableView.register(byAlbumCell,forCellReuseIdentifier: "byAlbumCell")
let albumCell = tableView.dequeueReusableCell(withIdentifier: "byAlbumCell", for: indexPath) as! AlbumCell
// albumCell.configureCell(choosenAlbum: filterViewModel.getSelectedAlbum())
albumCell.selectionStyle = .none
filterViewModel.getAlbum = { selectedAlbum in
albumCell.configureCell(choosenAlbum: selectedAlbum)
}
return albumCell
case 5:
let albumPickerCell = UINib(nibName: "AlbumsPickerTableViewCell", bundle: nil)
self.tableView.register(albumPickerCell, forCellReuseIdentifier: "albumPickerCell")
let albumsPicker = tableView.dequeueReusableCell(withIdentifier: "albumPickerCell", for: indexPath) as! AlbumsPickerTableViewCell
// albumsPicker.albumsPickerCellDelegate = self
albumsPicker.albumsPickerCellDelegate = filterViewModel
return albumsPicker
default:
return UITableViewCell()
}
}
// MARK: TableViewDelegate Methods:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: false)
tableView.beginUpdates()
// 1 - We Delete the UIPicker when the user "Deselect" thr row.
if let datePickerIndexPath = albumsPickerIndexPath, datePickerIndexPath.row - 1 == indexPath.row {
tableView.deleteRows(at: [datePickerIndexPath], with: .fade)
self.albumsPickerIndexPath = nil
let albumCell = tableView.cellForRow(at: indexPath) as! AlbumCell
UIView.animate(withDuration: 1) {
albumCell.arrowPickerView.transform = CGAffineTransform.identity
}
} else {
// 2
// if let datePickerIndexPath = albumsPickerIndexPath {
// tableView.deleteRows(at: [datePickerIndexPath], with: .fade)
// }
let albumCell = tableView.cellForRow(at: indexPath) as! AlbumCell
UIView.animate(withDuration: 1) {
albumCell.arrowPickerView.transform = CGAffineTransform(rotationAngle: .pi)
}
albumsPickerIndexPath = indexPathToInsertDatePicker(indexPath: indexPath)
tableView.insertRows(at: [albumsPickerIndexPath!], with: .fade)
tableView.deselectRow(at: indexPath, animated: true)
}
tableView.endUpdates()
}
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
if indexPath.row == 4 {
return indexPath
} else {
return nil
}
}
}
extension FilterTableViewController: DatesTableViewCellDelegate {
func didButtonFromPressed() {
let pickerController = CalendarPickerViewController(
baseDate: Date(),
selectedDateChanged: { [weak self] date in
guard let self = self else { return }
// self.item.date = date
// self.filterModel.startDate = date
self.tableView.reloadRows(at: [IndexPath(row: 3, section: 0)], with: .fade)
})
present(pickerController, animated: true, completion: nil)
}
func didButtonToPressed() {
//TODO: Present our custom calendar
let calendarController = CalendarPickerViewController(
baseDate: Date(),
selectedDateChanged: { [weak self] date in
guard let self = self else { return }
// self.filterModel.endDate = date
self.tableView.reloadRows(at: [IndexPath(row: 3, section: 0)], with: .fade)
})
self.present(calendarController, animated: true, completion: nil)
}
}
这是我的模型:
import Foundation
import UIKit
class FilterModel {
let userDefaults = UserDefaults.standard
var byActivity: String = ""
var postType: [String] = []
var hashTags: [String] = []
var startDate: Date = Date()
var endDate: Date = Date()
var album: String = ""
init() {
// First we need to fetch the data from the local storeage and insert into the vars:
self.fetchData()
}
deinit {
//Second we need to save the data in the local storeage:
self.saveData()
print("Im being deinited")
}
// MARK: - UserDefaults Section:
//Fetch - Retrieve from NSUserDefaults(local):
func fetchData() {
self.byActivity = userDefaults.string(forKey: k.UserDefaultsSaveKeys.byActivitySaveKey) ?? self.byActivity
self.postType = userDefaults.stringArray(forKey: k.UserDefaultsSaveKeys.postTypeSaveKey) ?? self.postType
self.hashTags = userDefaults.stringArray(forKey: k.UserDefaultsSaveKeys.hashTagsSaveKey) ?? self.hashTags
self.startDate = userDefaults.object(forKey: k.UserDefaultsSaveKeys.startDateSaveKey) as? Date ?? self.startDate
self.endDate = userDefaults.object(forKey: k.UserDefaultsSaveKeys.endDateSaveKey) as? Date ?? self.endDate
self.album = userDefaults.string(forKey: k.UserDefaultsSaveKeys.albumSaveKey) ?? self.album
print("Checking \(userAlreadyExist(kUsernameKey: k.UserDefaultsSaveKeys.albumSaveKey) )")
}
//Save - Save to local(NSUserDefaults):
func saveData() {
userDefaults.set(self.byActivity, forKey: "SavedByActivity")
userDefaults.set(self.postType, forKey: "SavedPostType")
userDefaults.set(self.hashTags, forKey: "SavedHashTags")
userDefaults.set(self.startDate, forKey: "SavedStartDate")
userDefaults.set(self.endDate,forKey: "SavedEndDate")
userDefaults.set(self.album,forKey: k.UserDefaultsSaveKeys.albumSaveKey)
}
//Testing function
func userAlreadyExist(kUsernameKey: String) -> Bool {
return userDefaults.object(forKey: kUsernameKey) != nil
}
}
试试这个?
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
filterViewModel.fetchData()
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisppear(animated)
filterViewModel.saveData()
}
我建议你检查是否已保存。
userDefaults.string (forKey: k.UserDefaultsSaveKeys.albumSaveKey)
如果仍然存在,则检查密钥:
userDefaults.set (self.byActivity, forKey: "SavedByActivity")
userDefaults.set (self.postType, forKey: "SavedPostType")
userDefaults.set (self.hashTags, forKey: "SavedHashTags")
userDefaults.set (self.startDate, forKey: "SavedStartDate")
userDefaults.set (self.endDate, forKey: "SavedEndDate")
您可以尝试在您的 FilterModel 中编写通用保存方法:
func saveValue(_ value: Any, forKey key: String) {
UserDefaults.standard.set(value, forKey: key)
}
然后像这样在你的委托方法中调用它:
func didButtonToPressed() {
//TODO: Present our custom calendar
let calendarController = CalendarPickerViewController(
baseDate: Date(),
selectedDateChanged: { [weak self] date in
guard let self = self else { return }
self.filterModel.saveValue(date, forKey: "SavedEndDate")
self.tableView.reloadRows(at: [IndexPath(row: 3, section: 0)], with: .fade)
})
self.present(calendarController, animated: true, completion: nil)
}
确保您用于保存值的密钥与您检索它的密钥相同。
在 deinit 中保存数据也不是一个好的做法,因为 deinit 有一些其他目的,当实例被释放以释放内存时调用。这不会在视图从屏幕上消失后立即发生。