Swift 保存按钮';不同视图中的图像状态
我的应用程序是一个Tableview控制器,其单元格中包含虚构角色的名称。选择单元格后,将显示一个视图控制器,其中包含有关角色的特定详细信息。我希望用户能够标记出他们已经拥有的每个字符 我设置了以下代码来在空圆圈图像和填充圆圈图像之间切换,以表示用户是否拥有该角色Swift 保存按钮';不同视图中的图像状态,swift,Swift,我的应用程序是一个Tableview控制器,其单元格中包含虚构角色的名称。选择单元格后,将显示一个视图控制器,其中包含有关角色的特定详细信息。我希望用户能够标记出他们已经拥有的每个字符 我设置了以下代码来在空圆圈图像和填充圆圈图像之间切换,以表示用户是否拥有该角色 let defaults = UserDefaults.standard var setImageStatus: String = "off" { willSet { if newValue == "on" {
let defaults = UserDefaults.standard
var setImageStatus: String = "off" {
willSet {
if newValue == "on" {
ownedCheck.image = UIImage(named: "filledCircle.jpg")
} else {
ownedCheck.image = UIImage(named: "emptyCircle.jpg")
}
}
}
@IBAction func ownedButtonClicked(_ sender: Any) {
let stat = setImageStatus == "on" ? "off" : "on"
setImageStatus = stat
defaults.set(stat, forKey: "imgStatus")
}
if let imgStatus = defaults.string(forKey: "imgStatus")
{
setImageStatus = imgStatus
} else {
setImageStatus = "off"
}
我遇到的问题是,一旦单击ownedButton,每个字符的圆圈都会保持填充状态。有没有办法使每个角色的按钮都是唯一的
我还不能发布图片,所以这里是tableview代码的截图。
您可以通过在字典中存储字符名称及其关联按钮来解决问题:
//1. Create A Dictionary With The Character's Name As The Key & The Button As The Value
var characterButtonInformation = [String: UIButton]()
然后,您可以参考按钮并轻松地进行检查。下面是一个粗略的例子,如果按钮上有标题,它将改变颜色:
//1. Create Dummy Buttons With A Unique Title (Could Use Tag As Well)
let buttonOne = UIButton(frame: CGRect(x: 0, y: 100, width: 100, height: 100))
buttonOne.titleLabel?.text = "On"
buttonOne.backgroundColor = .green
self.view.addSubview(buttonOne)
let buttonTwo = UIButton(frame: CGRect(x: 0, y: 220, width: 100, height: 100))
buttonTwo.titleLabel?.text = "Off"
buttonTwo.backgroundColor = .green
self.view.addSubview(buttonTwo)
//2. Add These To The Dictionary
characterButtonInformation["Frodo"] = buttonOne
characterButtonInformation["Bilbo"] = buttonTwo
//3. Check The Values For The Characters
for character in characterButtonInformation{
print("""
Character = \(character.key)
Button Title = \(character.value.titleLabel!.text)
""")
//4. Handle The State
if character.value.titleLabel?.text == "On"{
character.value.backgroundColor = .cyan
}
}
然后,您可以将此数据传递给另一个拥有自己的[String:UIButton]
字典的ViewController
更新:由于您使用的是JSON(之前没有显示),因此将字符存储在“可编码结构”中会更容易,例如:
///Structure Used To Store Character Data From JSON
struct Character: Codable {
var characterName: String!
var isOwned: Bool!
var hasMagicPowers: Bool!
}
理想情况下,由于数据的大小,这最适合保存在CoreData中
因此,MainViewController的基本设置如下:
class ViewController: UITableViewController {
//1. Array To Store All The Characters
var characters = [Character]()
//2. Currently Selected Character
var characterToShow: Character!
override func viewDidLoad() {
//1. Fake Data
let frodo: Character = Character(characterName: "Frodo", isOwned: true, hasMagicPowers: false)
let bilbo: Character = Character(characterName: "Bilbo", isOwned: false, hasMagicPowers: false)
let gandalf: Character = Character(characterName: "Gandalf", isOwned: true, hasMagicPowers: false)
characters.append(frodo)
characters.append(bilbo)
characters.append(gandalf)
super.viewDidLoad()
}
override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }
//-------------------------------------
//MARK: TableViewDataSource & Delegates
//-------------------------------------
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return characters.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.cellForRow(at: indexPath) as! CharacterCell
cell.characterName = characters[indexPath.row].characterName
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let indexPath = indexPath.row
characterToShow = characters[indexPath]
self.performSegue(withIdentifier: "showCharacter", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
//1. Get The Character DetailView
let characterDetailView = (segue.destination as! CharacterDetailViewController)
//2. Set The Character Details
characterDetailView.characterDetails = characterToShow
}
}
然后在CharacterDetailView中,根据需要处理角色数据,例如:
class CharacterDetailViewController: UIViewController {
var characterDetails: Character!
override func viewDidLoad() {
super.viewDidLoad()
let characterOwnedButton = UIButton(frame: CGRect(x: 20, y: 66, width: 100, height: 100))
characterOwnedButton.backgroundColor = .cyan
characterOwnedButton.titleLabel?.text = "Not Owned"
if characterDetails.isOwned{
characterOwnedButton.titleLabel?.text = "Owned"
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
当然,您需要管理数据的持久性等,但这应该足以为您指明正确的方向。按照您的逻辑,我建议您稍微修改使用
UserDefaults
的方式,以确定字符是“拥有的”
因此,基本上,我们根据字符的某个唯一标识符存储一个简单的bool
,以检查它是否为“所拥有的”。在我的示例中,我假设您的
character
对象有一个id
变量,该变量的类型为String
,因此执行以下操作将有效:
defaults.bool(forKey:character.id)
bitdefaults.set(newValue,forKey:character.id)
UserDefaults
不应随意用于存储垃圾。你提到你的JSON可以有1500个字符!我绝对不推荐
UserDefaults
,我想说这些数据应该来自服务器或存储在保存这些信息的磁盘上的JSON。但现在你有责任找到适合你的方法
试试看?阅读:分享一些屏幕截图。您的
tableView
数据源函数做什么?但是从您已经共享的代码来看,您似乎需要一些严重的结构改进。示例1:setImageStatus
是一个字符串,而不是bool。示例2:您正在保存此imgStatus
,但没有机制显示哪个字符。好。。。“从技术上讲,你可以这样做,但这只是你计划走的一条痛苦而不雅观的道路。”我在tableView函数的屏幕截图上添加了一个链接。单元格从一个JSON文件中获取数据。目前大约有1500个条目,那么这是否意味着通过这种方式,我必须创建1500个单独的let buttonxxx=。。。表达式?根据您包含的JSON作为数据源以及您拥有的字符数进行更新。
var setImageStatus: Bool = false {
willSet {
if newValue {
//Update UI
ownedCheck.image = UIImage(named: "filledCircle.jpg")
//Save state to user defaults
defaults.set(newValue,
forKey: character.id)
}
else {
//Update UI
ownedCheck.image = UIImage(named: "emptyCircle.jpg")
//Minor Optimization: Remove state from user defaults
defaults.removeObject(forKey: character.id)
}
}
}
@IBAction func ownedButtonClicked(_ sender: Any) {
//Simply toggle the state, the variable's willSet will handle the rest
setImageStatus = !setImageStatus
}
//Call this method from viewDidLoad
func checkIfCharacterIsSelected() {
//Simply retrieve the state, the variable's willSet will handle the rest
setImageStatus = defaults.bool(forKey: character.id)
}