我的应用是一个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
答案 0 :(得分: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 struct'中会更容易。 e.g:
///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()
}
}
当然,您需要管理数据的持久性等,但这应该足以让您指向正确的方向。
答案 1 :(得分:0)
按照你的逻辑,我建议稍微修改你使用UserDefaults
来识别角色所拥有的#34 ;.
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,并保存此信息。但现在你有责任找到适合自己的方式。