【问题标题】:Updating a data model with UserDefaults使用 UserDefaults 更新数据模型
【发布时间】:2018-06-20 19:39:01
【问题描述】:

我正在使用集合视图来显示大约 30 个不同的单元格。每个单元格代表一项冬季运动。这些单元格由静态数据模型填充,并在每次应用更新时更新(无数据库)。

由于我总是添加到运动列表中,我想在添加的最新运动上显示“新”徽章。当用户点击该特定运动时,“NEW”徽章会消失并通过 UserDefaults 持续存在。截图如下:

我的进度如下。我只是坚持坚持“新”属性,所以一旦点击“新”运动,布尔值就会变为 false 并在 UserDefaults 中更新。

模型。我将在此处更新新标志。如果为真,它将显示徽章(最终将取消隐藏图像视图。

struct WinterModel {
    let sportName: String
    var new: Bool
}

struct WinterData {
    static func allSports() -> [WinterModel] {
        return [
            WinterModel(sportName: "Luge", new: true),
            WinterModel(sportName: "Curling", new: false),
            WinterModel(sportName: "Skeleton", new: false),
            WinterModel(sportName: "Speed Skating", new: false),
            WinterModel(sportName: "Bobsleigh", new: false)
            // 30+ more
        ]
    }
}

主 VC。 填充集合视图。

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {

    var winter = WinterData.allSports()

    @IBOutlet weak var sportCollectionView: UICollectionView!

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return winter.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ID", for: indexPath as IndexPath) as! WinterSportCell
        let sport = winter[indexPath.item]
        cell.sport = sport
        return cell
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        sportCollectionView.dataSource = self
        sportCollectionView.delegate = self
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        // Cell was changed... Change data model to false?
    }

}

最后,UICollectionViewCell

class WinterSportCell: UICollectionViewCell { 
    @IBOutlet weak var sportNameLabel: UILabel!
    @IBOutlet weak var newOutlet: UILabel!
    var sport: WinterModel! {
        didSet {
            self.updateUI()
        }
    }
    func updateUI() {
        sportNameLabel.text = sport.sportName
        if sport.new {
            newOutlet.isHidden = false
        } else {
            newOutlet.isHidden = true
        }
    }
}

如何配置 UserDefaults,以便在用户点击该单元格时数据模型的“新”属性更新为 false?

【问题讨论】:

    标签: swift uicollectionview nsuserdefaults uicollectionviewcell


    【解决方案1】:

    您可以添加属性 id 或检查 winterModel.name 以更新属性。您需要使用 codable 将模型保存到 UserDefault。

    struct WinterModel: Codable {
        var id: Int
        let sportName: String
        var new: Bool
    }
    
    struct WinterDefaults {
    
        private static let winterDefaults = UserDefaults.standard
        private static let key = "Winter"
        private static let decoder = JSONDecoder()
        private static let encoder = JSONEncoder()
        private init() {}
    
        static func getWinterModels() -> [WinterModel]? {
    
            var winterModel: [WinterModel]?
            if let data = UserDefaults.standard.value(forKey: key) as? Data {
                winterModel = try? decoder.decode([WinterModel].self, from: data)
            }
    
            return winterModel
        }
    
        static func saveWinterModels(with winter: [WinterModel]) {
            let data = try? encoder.encode(winter)
            winterDefaults.set(data, forKey: key)
        }
    
        static func updateWinterModels(with winter: WinterModel) {
    
            var winterModels = getWinterModels()
    
            if winterModels != nil {
    
                for i in 0..<winterModels!.count {
                    if winterModels?[i].id == winter.id {
                        winterModels?[i].new = false
                    }
                }
    
                saveWinterModels(with: winterModels!)
            }
        }
    
    }
    
    class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {
    
        @IBOutlet weak var sportCollectionView: UICollectionView!
    
        var winterList: [WinterModel]?
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
            sportCollectionView.dataSource = self
            sportCollectionView.delegate = self
    
            if let winters = WinterDefaults.getWinterModels() {
                winterList = winters
            } else {
                let winters = getWinterList()
                winterList = winters
                WinterDefaults.saveWinterModels(with: winters)
            }
    
        }
    
        func getWinterList() -> [WinterModel] {
            return [
                WinterModel(id: 0, sportName: "Luge", new: true),
                WinterModel(id: 1, sportName: "Curling", new: false),
                WinterModel(id: 2, sportName: "Skeleton", new: false),
                WinterModel(id: 3, sportName: "Speed Skating", new: false),
                WinterModel(id: 4, sportName: "Bobsleigh", new: false)
            ]
        }
    
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return winterList?.count ?? 0
        }
    
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
            guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ID", for: indexPath as IndexPath) as? WinterSportCell else {
                return UICollectionViewCell()
            }
    
            if let winter = winterList?[indexPath.row] {
                cell.sport = winter
            }
    
            return cell
    
        }
    
        func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
            if winterList != nil {
                winterList![indexPath.row].new = false
                sportCollectionView.reloadData()
                WinterDefaults.saveWinterModels(with: winterList!)
            }
        }
    
    }
    
    class WinterSportCell: UICollectionViewCell {
        @IBOutlet weak var sportNameLabel: UILabel!
        @IBOutlet weak var newOutlet: UILabel!
        var sport: WinterModel! {
            didSet {
                sportNameLabel.text = sport.sportName
                newOutlet.isHidden = sport.new
            }
        }
    }
    

    【讨论】:

    • 您在 didSelectItemAt 中引用了 winter.new = false。那应该是 allWinterModels.new 吗?我不确定您要将所有代码放在//using 的哪里。您在哪里将模型保存到 WinterDefaults?您能否在答案中添加更多 cmets 以帮助我理解?谢谢!
    • @Joe 我刷新了我的代码。请检查一下。我希望你能理解,如果你不明白,请写信给我,我总是很乐意提供帮助。另外,别忘了点击“接受这个问题的答案”。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-05-31
    • 1970-01-01
    • 1970-01-01
    • 2021-05-24
    • 2018-03-18
    • 1970-01-01
    • 2012-04-29
    相关资源
    最近更新 更多