应用设置和用户默认设置
设置捆绑包
通过设置应用,用户可以输入和更改任何带有设置捆绑包(settings bundle)的应用中的偏好设置。在ios应用中,用户默认设置由NSUserDefaults类实现。NSUserDefaults数据会持久保存在文件系统中,而不是存储在内存的对象实现中。
设置应用的优势之一是不用为偏好设置设计用户界面,系统会自动创建用户界面。
Demo:
设置属性列表:
首先,创建一个新文件,settings.bundle(resource).
这里有几点需要强调:
- Item后面可以选择空间的类型。
- 设置属性列表使用的是键值对的dictionary。所以需要确定key的名称。在后面代码中会用到。
- 还可以为不同的空间设定相应的属性,具体的看Demo。
- Group是一种tableView的类型。
这里Filename定以为more。系统会自动寻找more.plist。即如下文件。
代码实现:
设置完属性列表之后,我们需要用代码实现信息的读取和保存。
AppDelegate
在app开启时需要有默认值的初始化。
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
// 在app开始运行时就会给出默认值。
let defaults = [warpDriveKey: true, warpFactorKey: 5, favoriteAlienKey: "Vulcan"]
NSUserDefaults.standardUserDefaults().registerDefaults(defaults)
return true
}
}
Constrains
用一个文件来保存key,以防后面编写代码时出错。
import Foundation
let officerKey = "officer"
let authorizationCodeKey = "authorizationCode"
let rankKey = "rank"
let warpDriveKey = "warp"
let warpFactorKey = "warpFactor"
let favoriteTeaKey = "favoriteTea"
let favoriteCaptainKey = "favoriteCaptain"
let favoriteGadgetKey = "favoriteGadget"
let favoriteAlienKey = "favoriteAlien"
// 这些常量是我们在属性列表文件中为不同的偏好设置字段使用的键值。
FirstViewController
在第一个视图中,显示相应设置后的信息。
import UIKit
class FirstViewController: UIViewController {
@IBOutlet var officerLabel:UILabel!
@IBOutlet var authorizationCodeLabel:UILabel!
@IBOutlet var rankLabel:UILabel!
@IBOutlet var warpDriveLabel:UILabel!
@IBOutlet var warpFactorLabel:UILabel!
@IBOutlet var favoriteTeaLabel:UILabel!
@IBOutlet var favoriteCaptainLabel:UILabel!
@IBOutlet var favoriteGadgetLabel:UILabel!
@IBOutlet var favoriteAlienLabel:UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func refreshFields() {
// 找到Key对应的相对内容
let defaults = NSUserDefaults.standardUserDefaults()
officerLabel.text = defaults.stringForKey(officerKey)
authorizationCodeLabel.text = defaults.stringForKey(authorizationCodeKey)
rankLabel.text = defaults.stringForKey(rankKey)
warpDriveLabel.text = defaults.boolForKey(warpDriveKey) ? "Engaged" : "Disabled"
warpFactorLabel.text = defaults.objectForKey(warpFactorKey)?.stringValue
favoriteTeaLabel.text = defaults.stringForKey(favoriteTeaKey)
favoriteCaptainLabel.text = defaults.stringForKey(favoriteCaptainKey)
favoriteGadgetLabel.text = defaults.stringForKey(favoriteGadgetKey)
favoriteAlienLabel.text = defaults.stringForKey(favoriteAlienKey)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
// 每次视图出现时都会更新一次。
refreshFields()
// 获得一个对应用实例的引用。
let app = UIApplication.sharedApplication()
// selector:向刚写的applicationWillEnterForeground方法传递一个选择器,告诉通知中心在该通知发出时得到通知。
// UIApplicationWillEnterForegroundNotification接受通知的名称
// object获得通知的来源。如果是nil,只要应用发出UIApplicationWillEnterForegroundNotification的通知
// 我们就会收到通知。
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "applicationWillEnterForeground:",
name: UIApplicationWillEnterForegroundNotification,
object: app)
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
// 因为我们在每个视图控制器里都进行了注册,以使viewWillAppear方法中监听该通知
// 所以我们应该在对应的viewDidDisappear中撤销注册
}
// 应用需要在应用回到前台时刷新它显示的内容。
func applicationWillEnterForeground(notification:NSNotification) {
let defaults = NSUserDefaults.standardUserDefaults()
// 强制用户默认值系统保存尚未保存的修改
// 然后从存储中重新加载所有未修改的偏好设置。
// 实际上,这是在强制它重新读取已保存的偏好设置。
defaults.synchronize()
refreshFields()
}
}
SecondViewController
import UIKit
class SecondViewController: UIViewController {
@IBOutlet var engineSwitch:UISwitch!
@IBOutlet var warpFactorSlider:UISlider!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func engineSwitchTapped(sender: AnyObject) {
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setBool(engineSwitch.on, forKey: warpDriveKey)
// 只要设置修改,我们就调用如下代码。
defaults.synchronize()
}
@IBAction func warpSliderTouched(sender: AnyObject) {
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setFloat(warpFactorSlider.value, forKey: warpFactorKey)
defaults.synchronize()
}
@IBAction func settingsButtonClicked(sender: AnyObject) {
// 进入设置页面。
UIApplication.sharedApplication().openURL(NSURL(string: UIApplicationOpenSettingsURLString)!)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
refreshFields()
let app = UIApplication.sharedApplication()
NSNotificationCenter.defaultCenter().addObserver(self,
selector: "applicationWillEnterForeground:",
name: UIApplicationWillEnterForegroundNotification,
object: app)
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
NSNotificationCenter.defaultCenter().removeObserver(self)
}
func refreshFields() {
let defaults = NSUserDefaults.standardUserDefaults()
engineSwitch.on = defaults.boolForKey(warpDriveKey)
warpFactorSlider.value = defaults.floatForKey(warpFactorKey)
}
func applicationWillEnterForeground(notification:NSNotification) {
let defaults = NSUserDefaults.standardUserDefaults()
defaults.synchronize()
refreshFields()
}
}