NSUserDefaults - 第二个View Controller中的数组为空

时间:2016-10-17 10:33:32

标签: ios arrays swift nsuserdefaults

我将NSUserDefaults保存的数据保存在“[RiskEntry]”类型的数组中。

让我向您解释一下我在这里保存的内容以及我的代码中加载和保存的过程如何(我使用的代码不相关,我使用 Swift3 ):

Main_ViewController

首先:在类Main_ViewController中,我得到一个从弹出框传输的文本并将其保存在一个数组中,NSUserDefaults在riskEntry中,键为“newTry”(这只是一个临时名称;-)) - > 'func riskText(riskTextTransferred:String)'。

Plan_ViewController

第二:当使用segue到达Plan_ViewController上的表时,该表填充了riskEntry中保存的文本,其中键为“newTry”(cell.riskTitle.text = savedTitles[indexPath.row].title as String)。到目前为止一切正常。

CustomCell Plan_ViewController

第三:当用户在单元格的文本字段中输入值(outcome.text)时,将为riskEntry更新值结果。所以在开始时,数组的后果是一个空字符串。现在,条目已用文本更新。

if let index = savedTitle.index(where: {$0.title.contains(identifier)}) {
            savedTitle[index].consequences = consequencesTranferred

然后使用键“newTry”保存新字符串。这也像预期的那样有效。

Main_ViewController

第四:现在我解雇Plan_ViewController返回Main_ViewController。当我现在尝试使用键“newTry”在viewWillAppear()中加载我的数组时,它是空的。

我做错了什么?如何从Main_ViewController中的Plan_ViewController成功加载更新的数据?

Main_ViewController

class Main_ViewController: UIViewController, UIPopoverPresentationControllerDelegate, UIGestureRecognizerDelegate {
    var riskItemDefaults = UserDefaults.standard
    var riskEntry = [RiskEntry]()

    override func viewWillAppear(_ animated: Bool) {

        if let dataArrayTitle = riskItemDefaults.object(forKey: "newTry") as? [NSData] {  
            var savedTitle = dataArrayTitle.map { RiskEntry(data: $0)! }
            riskItemDefaults.synchronize()

            // CHECKPOINT: all arrays are printed empty...
            print ("savedTitle: ")
            print (savedTitle)
            print ("dataArrayTitle: ")
            print (dataArrayTitle)
        } else {
           print ("nothing")
        }
    }


    // ---------------- delegate function that creates the array items -----------------
    func riskText(riskTextTransferred: String) {

        // CHECKPOINT: Array is saved correctly
        riskEntry = [RiskEntry(title: riskTextTransferred, consequences: "")]
        let encoded = riskEntry.map {$0.encode() }
        riskItemDefaults.set(encoded, forKey: "newTry")
        riskItemDefaults.synchronize()
    }
}

Plan_ViewController

class Plan_VC: UIViewController, UITableViewDelegate, UITableViewDataSource, CustomCellUpdaterDelegate  {
    @IBOutlet weak var tableView: UITableView!
    var riskEntry = [RiskEntry]()
    var riskItemDefaults = UserDefaults.standard

    // ---------------- table settings -----------------
    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        // load saved data and count number of entries for numberOfSections
        let dataArrayTitles = riskItemDefaults.object(forKey: "newTry") as! [NSData]
        let savedTitles = dataArrayTitles.map { RiskEntry(data: $0)! }

        return savedTitles.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = self.tableView!.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! CellCustomized
        cell.delegate = self

            // load saved data and insert title in cell label
            let dataArrayTitles = riskItemDefaults.object(forKey: "newTry") as! [NSData]
            let savedTitles = dataArrayTitles.map { RiskEntry(data: $0)! }
            cell.riskTitle.text = savedTitles[indexPath.row].title as String

        return cell
    }

    // ---------------- delegate function from CustomCell -----------------
    func transferData(consequencesTranferred: String, identifier: String) {

        /// load entry
        let dataArrayTitle = riskItemDefaults.object(forKey: "newTry") as! [NSData]
        var savedTitle = dataArrayTitle.map { RiskEntry(data: $0)! }
        riskItemDefaults.synchronize()

        // CHECKPOINT: The entry is loaded correctly
        print("loaded: ")
        print(savedTitle)

        /// filter entry for title contains identifier and update the empty string for consequences
        if let index = savedTitle.index(where: {$0.title.contains(identifier)}) {
            savedTitle[index].consequences = consequencesTranferred
            let encoded = riskEntry.map { $0.encode() }
            riskItemDefaults.set(encoded, forKey: "newTry")
            riskItemDefaults.synchronize()

            // CHECKPOINT: The entry is updated correctly
            print("After updating for consequences: ")
            print(savedTitle)
        }else {
            print ("No title with value identifier to be filtered")
        }

    }
}

CustomCell

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

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

    var myColorsClass = myColors()
    var myStylesClass = myStyles()

    var delegate: CustomCellUpdaterDelegate?

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

    var nameIdentifier = String()
    var textConsequences = String()


    override func awakeFromNib() {
        super.awakeFromNib()

        // initiate textView delegate
        consequences.delegate = self    

    } // nib end


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

1 个答案:

答案 0 :(得分:0)

由于NSUserDefaults上的时间延迟较小,当您解除Plan_ViewController时,newTry尚未保存(需要一些时间才能写入磁盘我想),但是`Main_ViewController中的viewWillAppear()方法会被立即调用。因此,由于时间延迟,阵列是空的。

为了避免这种情况,您无法消除时间延迟,您可以做的是使用委托将数据传递回您的第一个VC。

因此,您应该直接从委托调用中执行此操作,而不是从NSUserDefaults检索数组。