我在我的应用中实现了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()
,viewDidAppear
等viewWillAppear
投掷,但运气不错。
感谢您的阅读。我欢迎你的建议。
答案 0 :(得分:3)
似乎所有的常量都给你带来的是更清晰,更易读的代码。我建议在类中编写私有辅助函数来做同样的事情。读入和读出NSUserDefaults非常快,不应该出现问题。我也同意对其他答案的评论,没有必要同步。通常建议反对。让iOS系统为您处理此问题。它有足够的能力这样做。同步默认值会将它们写入磁盘,它会在准备就绪时执行此操作。否则,它将保留并从内存中读取数据。
我没有看到你的代码中出现任何明显的错误,但我最好的猜测是,在某些时候默认值会更新并且常量已经设置好了。所以基本上,一旦加载了类,它们永远不会再被设置。
要以更简洁,易于输入的方式获取值,请考虑这样的私有函数:
private func getDefaultRounds() -> Int {
return NSUserDefaults.standardUserDefaults().integerForKey("defaultRounds")
}
只需getDefaultRounds()
答案 1 :(得分:0)
我已经接受了凯尔的解决方案,但我尝试了一点学习练习,并且我把它扔掉看看人们的想法:
不是重复输入代码,而是记住我的密钥是什么,它是Int
,Float
还是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
我没有偶然发现任何"陷阱"用这种方法......如果有人就如何改进这方面有任何建议,我全心全意。