在不同视图中保存按钮的图像状态

问题描述 投票:-1回答:2

我的应用程序是一个Tableview控制器,其单元格包含虚构角色的名称。选择单元格后,将显示一个视图控制器,其中包含有关该字符的特定详细信息。我希望用户能够标记他们已经拥有的每个角色。

我设置以下代码以在空圆图像和实心圆图像之间切换,以表示用户是否拥有该角色。

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"
    } 

我遇到的问题是,一旦点击了ownButton,圆圈就会为每个角色保持填充状态。有没有办法让按钮对每个角色都是唯一的?

我还不能发布图片,所以这里是tableview代码的截图。 https://i.imgur.com/ofxgoSJ.jpg

swift
2个回答
0
投票

您可以通过在字典中存储字符名称及其关联的按钮来解决您的问题:

//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(之前未显示过),因此将字符存储在`Codable结构'中会更容易,例如:

  ///Structure Used To Store Character Data From JSON
     struct Character: Codable {

     var characterName: String!
     var isOwned: Bool!
     var hasMagicPowers: Bool!
  }

理想情况下,由于数据的大小,这最适合保存在Core Data中。

因此,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()

   }
}

当然,您需要管理数据的持久性等,但这应该足以让您指向正确的方向。


0
投票

按照你的逻辑,我建议稍微修改你使用UserDefaults来识别角色是“拥有”的方式。

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)
}

所以基本上,我们将一个简单的bool存储在角色的某个唯一标识符上,以检查它是否“拥有”。 在我的例子中,我假设您的character对象有一个id类型的String变量,因此执行以下操作将起作用:

  • defaults.bool(forKey: character.id)
  • defaults.set(newValue, forKey: character.id)位。

但是,不应该不小心使用UserDefaults来存放垃圾。 你提到你的JSON可能有1500个字符!我绝对不会推荐UserDefaults,我会说这些数据应来自存储在磁盘上的服务器或JSON,并保存这些信息。但现在您有责任找到适合您的方式。

尝试?阅读:https://medium.com/@deepcut/understanding-ios-data-persistence-nsuserdefaults-and-the-file-system-cf062dc53761

© www.soinside.com 2019 - 2024. All rights reserved.