【问题标题】:use NSUserDefaults with array of struct type将 NSUserDefaults 与结构类型的数组一起使用
【发布时间】:2016-10-15 18:41:38
【问题描述】:

我很难弄清楚如何使用 NSUserDefaults 保存“RiskEntry”类型的字符串。我已经浏览了其他一些帖子,但不知何故我仍然没有设法解决这个特定问题。

让我解释一下下面的代码现在做了什么:我在下面的代码 sn-p 中从我的类 CustomCell 中获取了一些数据。在这里,我首先使用“标识符”检查要使用新数组值“结果”更新哪个数组。

一切正常,更新后的数组存储在 riskEntry 中。 但是,我现在无法弄清楚如何使用 NSUserDefaults 存储它。当我尝试使用例如riskItemDefaults.set(riskEntry, forKey: "riskItem")我得到一个异常错误。

知道我在这里做错了什么吗?

SWIFT3(我删除了与此问题无关的所有代码)

class: RiskPlan: UIViewController, UITableViewDelegate, UITableViewDataSource, CustomCellUpdaterDelegate {

 var riskEntry = [RiskEntry]()
 var riskItemDefaults = UserDefaults.standard

// ------ start of delegate function (receiving from CustomCell) ---------
      func transferData(consequencesTranferred: String, identifier: String) {
        if let index = riskEntry.index(where: {$0.title as String == identifier}) {
            riskEntry[index].consequences = consequencesTranferred
    } else {
        print ("nothing")
    }

// save with NSUserDefaults
        riskItemDefaults.set(riskEntry, forKey: "riskItem")
  }
}

这是我的结构:

public struct RiskEntry {
    let title: String
    var consequences: String
}

我的自定义单元格

// ---------------- delegate to transfer entered data to VC -----------------
protocol CustomCellUpdaterDelegate {
    func transferData(consequencesTranferred: String, identifier: String)
}

// ---------------- start of class CellCustomized -----------------
class CustomCell: UITableViewCell, UIPickerViewDataSource, UIPickerViewDelegate, UITextViewDelegate {

    var delegate: CustomCellUpdaterDelegate?

    // text fields, text views and picker views
    @IBOutlet weak var riskTitle: UITextView!
    @IBOutlet weak var consequences: UITextView!

    // ---------------- listener for text view to save input in string when editing is finished -----------------
    func textViewDidEndEditing(_ textView: UITextView) {
        if textView.tag == 1 {
            textConsequences = consequences.text
            nameIdentifier = riskTitle.text
            delegate?.transferData(consequencesTranferred: self.textConsequences, identifier: nameIdentifier)
        } else {
            print ("nothing")
        }
    }
}

【问题讨论】:

  • 您遇到的异常是什么?
  • 我的控制台输出是:libc++abi.dylib: terminating with uncaught exception of type NSException 而我的 AppDelegate.swift 类被选为 Thread 1: signal SIGABRT
  • 这个解决方案做到了!不过,我必须将其转换为 swift 3 并对其进行修改以适合我的用例。我会将其作为答案发布,以防将来对其他人有所帮助:-)

标签: ios arrays swift struct nsuserdefaults


【解决方案1】:

问题是您无法将自定义数组保存在 NSUserDefaults 中。为此,您应该将它们更改为 NSData 然后将其保存在 NSUserDefaults 这是我在项目中使用的代码,它采用 swift 2 语法,我认为将其转换为 swift 3 并不难

let data = NSKeyedArchiver.archivedDataWithRootObject(yourObject);
NSUserDefaults.standardUserDefaults().setObject(data, forKey: "yourKey")
NSUserDefaults.standardUserDefaults().synchronize()

在get部分使用这个组合

if let data = NSUserDefaults.standardUserDefaults().objectForKey("yourKey") as? NSData {
    let myItem = NSKeyedUnarchiver.unarchiveObjectWithData(data) as? yourType
}

希望这会有所帮助

【讨论】:

    【解决方案2】:

    UserDefaults 中保存对象有非常具体的限制:

    set(_:forKey:) reference:

    value 参数只能是属性列表对象:NSData、NSString、NSNumber、NSDate、NSArray 或 NSDictionary。对于 NSArray 和 NSDictionary 对象,它们的内容必须是属性列表对象。

    您需要使用 NSCoding 或作为替代方法使用 JSON 序列化您的模型,以映射到 UserDefaults 支持的值。

    【讨论】:

      【解决方案3】:

      UserDefaults 支持的最接近 Swift 结构的类型可能是 NSDictionary。您可以在保存数据之前将结构元素复制到 Objective C NSDictionary 对象中。

      【讨论】:

        【解决方案4】:

        我能够基于@ahruss (How to save an array of custom struct to NSUserDefault with swift?) 编写解决方案。但是,我为 swift 3 修改了它,它还展示了如何在 UITableView 中实现这个解决方案。我希望它可以帮助将来的人:

        1. 将扩展从下面添加到您的结构中(将其调整为您自己的变量)

        2. 像这样保存所需的数组项:

          让编码 = riskEntry.map { $0.encode() } riskItemDefaults.set(编码,forKey:“后果”) riskItemDefaults.synchronize()

        3. 像这样加载你的项目

          让 dataArray = riskItemDefaults.object(forKey: "consequences") as! [NS数据] 让 savedFoo = dataArray.map { RiskEntry(data: $0)! }

        4. 如果您想在单元格中显示已保存的数组项,请按以下方式进行:

          cell.consequences.text = savedFoo[indexPath.row].consequences as String

        这是完整的代码,为 Swift3

        修改

        结构

        // ---------------- structure for table row content -----------------
        struct RiskEntry {
            let title: String
            var consequences: String
        }
        

        扩展

          extension RiskEntry {
                init?(data: NSData) {
                    if let coding = NSKeyedUnarchiver.unarchiveObject(with: data as Data) as? Encoding {
                        title = coding.title as String
                        consequences = (coding.consequences as String?)!
                    } else {
                        return nil
                    }
                }
        
                func encode() -> NSData {
                    return NSKeyedArchiver.archivedData(withRootObject: Encoding(self)) as NSData
                }
        
                private class Encoding: NSObject, NSCoding {
                    let title : NSString
                    let consequences : NSString?
        
        
                    init(_ RiskEntry: RiskEntry) {
                        title = RiskEntry.title as NSString
                        consequences = RiskEntry.consequences as NSString?
                    }
        
                    public required init?(coder aDecoder: NSCoder) {
                        if let title = aDecoder.decodeObject(forKey: "title") as? NSString {
                            self.title = title
                        } else {
                            return nil
                        }
                        consequences = aDecoder.decodeObject(forKey: "consequences") as? NSString
                    }
        
                    public func encode(with aCoder: NSCoder) {
                        aCoder.encode(title, forKey: "title")
                        aCoder.encode(consequences, forKey: "consequences")
                    }
        
                }
            }
        

        【讨论】:

          猜你喜欢
          • 2011-02-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-01-08
          • 2023-04-10
          • 1970-01-01
          相关资源
          最近更新 更多