NSUserDefault常量不更新

时间:2015-11-13 03:08:35

标签: ios swift uitableview constants nsuserdefaults

我在我的应用中实现了NSUserDefaults,并且在启动之间保持正确的值,但是在引用常量时,我​​创建的值在会话期间更改默认值时不会更新。

我确定我的问题源于使用常量来引用NSUserDefaults,但我可以看到它拯救了我多少代码,我想坚持这种方法,如果可行/良好做法。我不确定如何更新新NSUserDefault值的常量。我没有崩溃 - 只是陈旧的价值观。

我的设置

AppDelegate.swift

我使用NSUserDefaults在我的应用中存储一些整数值。在AppDelegate.swift我会检查他们是否已设置。这很有效。

PreferencesViewController.swift

我有一个PreferencesVC我已经配置了填充默认值并允许用户更改默认值。我添加了一些print语句,以便在保存时验证新的NSUserDefaults值。这很有效。

MyTableViewController.swift 我声明了常量,所以我可以减少冗长的代码。

// Import Statements
@import UIKit

// Constants I declare here so they're accessible throughout the app.
let kDefaultActiveTime = NSUserDefaults.standardUserDefaults().integerForKey("defaultActiveTime")
let kDefaultBreakTime = NSUserDefaults.standardUserDefaults().integerForKey("defaultBreakTime")
let kDefaultRounds = NSUserDefaults.standardUserDefaults().integerForKey("defaultRounds")

// Class declaration
class MyTableViewController: UITableViewController

在我的cellForRowAtIndexPath中,我使用默认常量来计算时间并为单元格上的标签输出字符串。这是一行:

    // boilerplate cellForRowAtIndexPath omitted
    let customCell = tableView.dequeueReusableCellWithIdentifier("customCell", forIndexPath: indexPath) as! RoutineSelectionTableViewCell

    let routine = fetchedResultsController.objectAtIndexPath(indexPath) as! SavedRoutines

    // ** This doesn't update w/ tableView.reloadData()
    customCell.routineInformationLabel.text = String(format: "Time to complete - %@", formatTimeInSeconds(totalRoutineTime(routine.items! as NSOrderedSet)))

以下是用于为routineInformationLabel.text创建字符串的方法:

// Time computation methods
func totalRoutineTime(routine: NSOrderedSet) -> Int {
    var totalRounds = 0
    for item in routine {
        // get the total of rounds
        totalStretchRounds += (((item as! MyNSManagedObject).sideMultiplier?.integerValue)!) * kDefaultRounds
    }
    let totalActiveTime = totalRounds * kDefaultActiveTime
    let totalBreakTime = (totalRounds - 1) * kDefaultBreakTime // subtract 1 rest period for last item

    return totalActiveTime + totalBreakTime
}

func formatTimeInSeconds(totalSeconds: Int) -> String {
    let seconds = totalSeconds % 60
    let minutes = (totalSeconds / 60) % 60
    let hours = totalSeconds / 3600
    let stringHours = hours > 9 ? String(hours) : "0" + String(hours)
    let stringMinutes = minutes > 9 ? String(minutes) : "0" + String(minutes)
    let stringSeconds = seconds > 9 ? String(seconds) : "0" + String(seconds)

    if hours > 0 {
        return "\(stringHours):\(stringMinutes):\(stringSeconds)"
    }
    else {
        return "\(stringMinutes):\(stringSeconds)"
    }
}

我尝试创建一个观察者,以便在保存NSUserDefaults时重新加载tableView,但这似乎并没有成功。我还尝试在tableView.reloadData()viewDidAppearviewWillAppear投掷,但运气不错。

感谢您的阅读。我欢迎你的建议。

2 个答案:

答案 0 :(得分:3)

似乎所有的常量都给你带来的是更清晰,更易读的代码。我建议在类中编写私有辅助函数来做同样的事情。读入和读出NSUserDefaults非常快,不应该出现问题。我也同意对其他答案的评论,没有必要同步。通常建议反对。让iOS系统为您处理此问题。它有足够的能力这样做。同步默认值会将它们写入磁盘,它会在准备就绪时执行此操作。否则,它将保留并从内存中读取数据。

我没有看到你的代码中出现任何明显的错误,但我最好的猜测是,在某些时候默认值会更新并且常量已经设置好了。所以基本上,一旦加载了类,它们永远不会再被设置。

要以更简洁,易于输入的方式获取值,请考虑这样的私有函数:

private func getDefaultRounds() -> Int {
    return NSUserDefaults.standardUserDefaults().integerForKey("defaultRounds")
}

只需getDefaultRounds()

即可在班级的任何地方访问

答案 1 :(得分:0)

我已经接受了凯尔的解决方案,但我尝试了一点学习练习,并且我把它扔掉看看人们的想法:

不是重复输入代码,而是记住我的密钥是什么,它是IntFloat还是Bool等等,我创建了一个Struct访问值:

struct Defaults {
    let activeTime = NSUserDefaults.standardUserDefaults().integerForKey("defaultActiveTime")
    let breakTime = NSUserDefaults.standardUserDefaults().integerForKey("defaultBreakTime")
    let rounds = NSUserDefaults.standardUserDefaults().integerForKey("defaultRounds")
}

当我需要访问NSUserDefaults值时,它们会动态更新。它似乎宣称它们是一个常数"快照"他们及时,但他们不会更新。

当我需要默认设置但我不想输入时,我输入:

Defaults().rounds
Defaults().activeTime
Defaults().breakTime

我没有偶然发现任何"陷阱"用这种方法......如果有人就如何改进这方面有任何建议,我全心全意。