在 NSUserDefaults 的表格视图单元格中保存收藏按钮的状态

Posted

技术标签:

【中文标题】在 NSUserDefaults 的表格视图单元格中保存收藏按钮的状态【英文标题】:Save state of favorite button in Table view Cell in NSUserDefaults 【发布时间】:2017-08-04 04:30:54 【问题描述】:

我已经为这类问题经历了很多解决方案,但我仍然卡住了,不知道如何将按钮的状态保存到 NSUserDefaults 中。

Here is the picture for demo

这是我的 Tableview 控制器

override func viewDidLoad() 

    super.viewDidLoad()
    navigationItem.title = "Contacts"
    tableView.register(RecordCell.self, forCellReuseIdentifier: "cellId")



override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let myCell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath as IndexPath) as! RecordCell


    myCell.starButton.tag = indexPath.row
    myCell.myTableViewController = self
    return myCell

这是我的自定义 Cell 类

class RecordCell: UITableViewCell 

var myTableViewController: HomepageController?

override init(style: UITableViewCellStyle, reuseIdentifier: String?) 
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    setupViews()


required init?(coder aDecoder: NSCoder) 
    fatalError("init(coder:) has not been implemented")


let nameLabel: UILabel = 
    let label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    label.font = UIFont (name: "SFCompactDisplay-Regular", size: 14)
    return label
()
let companyLabel: UILabel = 
    let label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    label.font = UIFont (name: "SFCompactDisplay-Light", size: 10)
    return label
()
let shortname: UILabel = 
    let label = UILabel()
    label.textColor = UIColor.white
    label.translatesAutoresizingMaskIntoConstraints = false
    label.font = UIFont (name: "SFCompactDisplay-Regular", size: 12)
    label.textAlignment = .center
    label.backgroundColor = UIColor(patternImage: UIImage(named: "avatar")!)
    return label
()
let starButton: UIButton = 
    let button = UIButton(type: .system)
    button.setImage(UIImage(named: "star"), for: .normal)
    button.translatesAutoresizingMaskIntoConstraints = false
    return button
()
let playButton: UIButton = 
    let button = UIButton(type: .system)
    button.setImage(UIImage(named: "playback"), for: .normal)
    button.translatesAutoresizingMaskIntoConstraints = false
    return button
()

func setupViews() 
    addSubview(nameLabel)
    addSubview(companyLabel)
    addSubview(shortname)
    addSubview(starButton)
    addSubview(playButton)

    starButton.addTarget(self, action: #selector(RecordCell.starAction), for: .touchUpInside)

// playButton.addTarget(self, action: #selector(RecordCell.playAudio), for: .touchUpInside)

    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-8-[v4(40)]-8-[v0]-8-[v1(30)]-8-[v2(30)]-8-|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": nameLabel, "v1": starButton,"v2":playButton, "v4":shortname]))
    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-56-[v3]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v3": companyLabel]))


    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-2-[v0][v3]-7-|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": nameLabel,"v3": companyLabel]))
    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": starButton]))
    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": playButton]))
    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-2-[v0(40)]-7-|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0": shortname]))



func starAction() 
    starButton.setImage(UIImage(named:"star-active"), for: .normal)

【问题讨论】:

一个建议。将按钮的状态存储在用户默认值中并不是一个好的编程习惯。如果您真的想(重新)存储按钮的状态,更好的方法是创建一个单例类并将按钮的当前状态写入其中。 我是 Swift 新手,对单例模式一无所知。我只是尝试一些简单的东西。顺便说一句,非常感谢你的建议。我稍后会考虑 【参考方案1】:

RecordCell类中添加标签作为变量

class RecordCell: UITableViewCell 

var myTableViewController: HomepageController?
var favID:Int = 0
.....//other code

视图控制器

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let myCell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath as IndexPath) as! RecordCell

    myCell.favID = indexPath.row //set value to favID variable
    myCell.myTableViewController = self
    myCell.updateSelection() //call this method to update the selection
    return myCell

RecordCell 类中

override func awakeFromNib() 
    super.awakeFromNib()
    updateSelection()


func updateSelection() 
    let key = "\(favID)" 
    let userDefault = UserDefault.standard
    let isFav = userDefault.bool(forKey: key)
    starButton.isSelected = isFav


let starButton: UIButton = 
    let button = UIButton(type: .system)
    button.setImage(UIImage(named: "star"), for: .normal) //add image for different states
    button.setImage(UIImage(named:"star-active"), for: .selected) //add image for different states
    button.translatesAutoresizingMaskIntoConstraints = false
    return button
()

func setupViews() 
    ....
    ....//other code
    updateSelection()


func starAction() 
    starButton.isSelected = !starButton.isSelected //toggle selection
    let key = "\(favID)" 
    let userDefault = UserDefault.standard
    userDefault.set(starButton.isSelected, forKey: key)
    userDefault.synchronize()

这是一个基于索引的示例,如果可能,您可以使用表中显示的对象的任何唯一标识符作为键。或者在数据模型本身中设置一个 isFav 变量。

【讨论】:

感谢您的回复,它确实切换但状态未正确保存,我认为可能是索引路径的问题 你有多个部分吗?现在保存的行为如何? 点击任意一行中的一个按钮,它不会只保存该行的状态,如果我点击切换所有按钮,它会保存所有 希望您使用isSelected而不是在答案中选择' 是的,现在可以使用了。非常感谢你拯救了我的一天【参考方案2】:
func starAction() 

     let userDefault = UserDefault.standard
      userDefault.set(true, forKey: "KEY_IS_SELECTED")
    starButton.setImage(UIImage(named:"star-active"), for: .normal)

获取最喜欢的按钮状态:

let userDefault = UserDefault.standard
let state = userDefault.bool(forKey: "KEY_IS_SELECTED")

//get stored state of button
//use state of button

【讨论】:

感谢您的回复,但问题是我希望用户可以根据 isSelected 属性切换按钮的状态然后保存。也基于联系人的每一行

以上是关于在 NSUserDefaults 的表格视图单元格中保存收藏按钮的状态的主要内容,如果未能解决你的问题,请参考以下文章

停止调用 cellForRowAtIndexPath

Swift NSUserDefaults TableView 多个单元格

UITableview 不通过 willdisplaycell 选择单元格

杀死/退出应用程序后,如何在 UITableView 中使用 NSUserDefaults 显示自定义单元格,Xcode Swift

在每个单元格都包含表格视图的表格视图中选择新单元格时,无法取消选择先前选择的单元格

在表格视图单元格按钮上查看表格视图单元格文本