Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 保存按钮';不同视图中的图像状态_Swift - Fatal编程技术网

Swift 保存按钮';不同视图中的图像状态

Swift 保存按钮';不同视图中的图像状态,swift,Swift,我的应用程序是一个Tableview控制器,其单元格中包含虚构角色的名称。选择单元格后,将显示一个视图控制器,其中包含有关角色的特定详细信息。我希望用户能够标记出他们已经拥有的每个字符 我设置了以下代码来在空圆圈图像和填充圆圈图像之间切换,以表示用户是否拥有该角色 let defaults = UserDefaults.standard var setImageStatus: String = "off" { willSet { if newValue == "on" {

我的应用程序是一个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"
    } 
我遇到的问题是,一旦单击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)
  • defaults.set(newValue,forKey:character.id)
    bit
但是,
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)
}