版本:iOS13.6
一、简介
NSUserDefaults是一种存储轻量化数据的方案,系统会将存储的内容以plist文件的形式保存在沙盒中,路径为Library/Preferences/xxx.plist,xxx为项目的Bundle Identifier。
可保存的数据类型为NSString NSData NSNumber NSDate NSArray NSDictionary
,若想保存某些model,可使用yyModel
将之转化成json再将其存入。
二、NSUserDefaults API
@interface NSUserDefaults : NSObject
//返回全局实例 只读
@property (class, readonly, strong) NSUserDefaults *standardUserDefaults;
//将存储的数据全部删除
//而且KVO观察者将不会再观察数据的变化
+ (void)resetStandardUserDefaults;
//相当于initWithSuiteName:nil
- (instancetype)init;
//预创建一个新的plist,并返回它的实例,在沙盒中的路径为Library/Preferences/suitename.plist
//但只有向里面存储数据后才会实际创建该plist
//当initWithSuiteName:nil时会返回全局实例
//在该方法返回的实例中保存的数据可在不同的app中共享
//详见第三节
- (nullable instancetype)initWithSuiteName:(nullable NSString *)suitename;
//已弃用
- (nullable id)initWithUser:(NSString *)username API_DEPRECATED(ios(2.0,7.0));
//获取对应密钥的数据
//数据 类型为NSString NSData NSNumber NSDate NSArray NSDictionary
- (nullable id)objectForKey:(NSString *)defaultName;
//为对应密钥存储一个数据
//该数据是异步存储的,可通过synchronize使数据立即同步存储
//数据 类型为NSString NSData NSNumber NSDate NSArray NSDictionary
//若value = nil ,则移除对应密钥保存的数据
- (void)setObject:(nullable id)value forKey:(NSString *)defaultName;
//移除对应密钥保存的数据
//相当于setObject:nil forKey:defaultName
- (void)removeObjectForKey:(NSString *)defaultName;
//获取对应密钥保存的NSString类型数据
//若数据为NSNumber,可自动转换为字符串;若为其他类型,返回nil
- (nullable NSString *)stringForKey:(NSString *)defaultName;
//获取对应密钥保存的NSArray类型数据
//若为其他类型,返回nil
- (nullable NSArray *)arrayForKey:(NSString *)defaultName;
//获取对应密钥保存的NSDictionary类型数据
//若为其他类型,返回nil
- (nullable NSDictionary<NSString *, id> *)dictionaryForKey:(NSString *)defaultName;
//获取对应密钥保存的NSData类型数据
//若为其他类型,返回nil
- (nullable NSData *)dataForKey:(NSString *)defaultName;
//获取对应密钥保存的NSArray<NSString *>类型数据
//若为其他类型,返回nil
//与stringForKey不同的是,若数组中的数据为NSNumber,也将返回nil
- (nullable NSArray<NSString *> *)stringArrayForKey:(NSString *)defaultName;
//获取对应密钥保存的数据,并将其转换成NSInteger
//若为NSNumber,可直接转换成功
//若为NSString,若能转换成功则返回对应的值,否则返回0
//若为布尔值,YES则返回1,NO则返回0
//其他情况则返回0
- (NSInteger)integerForKey:(NSString *)defaultName;
//获取对应密钥保存的数据,并将其转换成float
//与integerForKey类似,不同之处在于当为布尔值时,不会转换
- (float)floatForKey:(NSString *)defaultName;
//获取对应密钥保存的数据,并将其转换成double
//与integerForKey类似,不同之处在于当为布尔值时,不会转换
- (double)doubleForKey:(NSString *)defaultName;
//获取对应密钥保存的数据,并将其转换成BOOL
//若为NSNumber,@(0)则返回NO,其他则返回YES
//若为NSString,1或YES则返回YES,其他则返回NO
//其他情况则返回NO
- (BOOL)boolForKey:(NSString *)defaultName;
//获取对应密钥保存的NSURL类型数据
//若为NSString,则会将该路径转换成NSURL
//若是通过-setURL:forKey:保存的数据,则返回对应的NSURL
//若该值不存在或无法转换为NSURL,则返回nil
- (nullable NSURL *)URLForKey:(NSString *)defaultName;
//为对应密钥存储一个NSInteger数据
//NSIntege通过NSNumber来存储,相当于setObject:@(value) forKey:
- (void)setInteger:(NSInteger)value forKey:(NSString *)defaultName;
//为对应密钥存储一个float数据
//float通过NSNumber来存储,相当于setObject:@(value) forKey:
- (void)setFloat:(float)value forKey:(NSString *)defaultName;
//为对应密钥存储一个double数据
//double通过NSNumber来存储,相当于setObject:@(value) forKey:
- (void)setDouble:(double)value forKey:(NSString *)defaultName;
//为对应密钥存储一个BOOL数据
//double通过NSNumber来存储,相当于setObject:@(value) forKey:
- (void)setBool:(BOOL)value forKey:(NSString *)defaultName;
//为对应密钥存储一个NSURL数据
//NSURL会归档为NSData来存储,可通过URLForKey来获取该NSURL
- (void)setURL:(nullable NSURL *)url forKey:(NSString *)defaultName;
//注册默认值,默认值会保存在搜索列表中的最后一项NSRegistrationDomain域中
//当未查询出对应密钥的数据后,会继续在默认值中查询,若有查询出结果,则使用该默认值返回
//默认值只对该应用程序有效,不会共享。
//详见下面的例1
- (void)registerDefaults:(NSDictionary<NSString *, id> *)registrationDictionary;
//给当前的NSUserDefaults添加一个子搜索列表suiteName
//搜索数据时,会按照 本身的列表--子搜索列表-注册的默认值列表 的顺序搜索
//详见下面的例2
- (void)addSuiteNamed:(NSString *)suiteName;
//从当前的NSUserDefaults移除已添加的子搜索列表suiteName
- (void)removeSuiteNamed:(NSString *)suiteName;
//返回所有已保存数据
//里面有一些系统添加的数据,可以修改,但无法删除
//当对这些数据调用removeObjectForKey时,会使该值变成初始值
//详见下面的例3
- (NSDictionary<NSString *, id> *)dictionaryRepresentation;
//返回易失性域的名字的数组 只读
//易失性域不会添加到任何搜索列表中,也不会持久保存,重启app后数据会重置。
//并且对其他应用程序不可见。不建议使用它们
//详见下面的例4
@property (readonly, copy) NSArray<NSString *> *volatileDomainNames;
//获取对应易失性域的数据
- (NSDictionary<NSString *, id> *)volatileDomainForName:(NSString *)domainName;
//给对应易失性域设置数据
- (void)setVolatileDomain:(NSDictionary<NSString *, id> *)domain forName:(NSString *)domainName;
//移除对应域名的易失性域
- (void)removeVolatileDomainForName:(NSString *)domainName;
//返回持久性域的名字的数组 已废弃
- (NSArray *)persistentDomainNames API_DEPRECATED(ios(2.0,7.0));
//获取对应持久性域的数据
//详见下面的例5
- (nullable NSDictionary<NSString *, id> *)persistentDomainForName:(NSString *)domainName;
//给对应持久性域设置数据
- (void)setPersistentDomain:(NSDictionary<NSString *, id> *)domain forName:(NSString *)domainName;
//移除对应域名的持久性域
- (void)removePersistentDomainForName:(NSString *)domainName;
//立即同步存储数据
//因为数据保存都是异步的,通过该方法将会同步存储
//若要保存的数据量过大时,可能造成卡顿,要慎用。
//不建议使用,该方法将在不久后被弃用。
- (BOOL)synchronize;
//判断某个密钥是否由管理员管理
- (BOOL)objectIsForcedForKey:(NSString *)key;
//判断domain域中某个密钥是否由管理员管理
- (BOOL)objectIsForcedForKey:(NSString *)key inDomain:(NSString *)domain;
@end
- 例1
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
//移除key的数据
[defaults removeObjectForKey:@"key"];
NSString *value = [defaults objectForKey:@"key"];
NSLog(@"value = %@", value);
//注册默认值
[defaults registerDefaults:@{@"key":@"defaults"}];
value = [defaults objectForKey:@"key"];
NSLog(@"value = %@", value);
//为key设置数据
[defaults setObject:@"test" forKey:@"key"];
value = [defaults objectForKey:@"key"];
NSLog(@"value = %@", value);
输出:
value = (null)
value = defaults
value = test
说明:
因为key中保存的数据已经被删除了,所以value = (null)
注册了key的默认值后,因为key中仍没有数据,会使用默认值的数据,所以value = defaults
在为key设置数据后,会使用已设置的数据,所以value = test
- 例2
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSUserDefaults *nameDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"nameDefaults"];
[nameDefaults setObject:@"liu" forKey:@"name"];
NSLog(@"name = %@", [defaults objectForKey:@"name"]);
[defaults addSuiteNamed:@"nameDefaults"];
NSLog(@"name = %@", [defaults objectForKey:@"name"]);
[defaults removeSuiteNamed:@"nameDefaults"];
NSLog(@"name = %@", [defaults objectForKey:@"name"]);
输出:
name = (null)
name = liu
name = (null)
说明:
因为defaults中没有name的数据,所有name = (null)
当defaults添加了子搜索列表nameDefaults后,而nameDefaults中有name的数据,所以name = liu
当defaults移除了nameDefaults后,则会重新name = (null)
- 例3
NSDictionary *dict = [defaults dictionaryRepresentation];
NSLog(@"%@", dict);
//修改AppleLanguages的数据,此方法可以将app的语言变为中文
[defaults setObject:@[@"zh-Hans-CN"] forKey:@"AppleLanguages"];
NSLog(@"%@", [defaults objectForKey:@"AppleLanguages"]);
//移除AppleLanguages的数据,会重置为初始值
[defaults setObject:nil forKey:@"AppleLanguages"];
NSLog(@"%@", [defaults objectForKey:@"AppleLanguages"]);
输出:
{
AKLastIDMSEnvironment = 0;
AddingEmojiKeybordHandled = 1;
AppleITunesStoreItemKinds = (
podcast,
artist,
"itunes-u",
booklet,
document,
movie,
eBook,
software,
"software-update",
"podcast-episode"
);
AppleKeyboards = (
"zh_Hans-Pinyin@sw=Pinyin-Simplified;hw=Automatic",
"en_US@sw=QWERTY;hw=Automatic",
"ja_JP-Kana@sw=Kana;hw=Automatic",
"en_US@sw=QWERTY;hw=Automatic"
);
AppleKeyboardsExpanded = 1;
AppleLanguages = (
"zh-Hans-CN",
"en-CN",
"ja-JP"
);
AppleLanguagesSchemaVersion = 1001;
AppleLocale = "zh_CN";
ApplePasscodeKeyboards = (
"en_US",
emoji
);
CarCapabilities = {
CarCapabilitiesDefaultIdentifier = {
CRCapabilitiesDisabledFeatureKey = 0;
CRCapabilitiesUserInterfaceStyleKey = 2;
CRCapabilitiesVersionKey = "";
CapabilitiesDashboardRoundedCornersKey = "{{13, 0}, {0, 0}}";
CapabilitiesNowPlayingAlbumArtKey = 2;
CapabilitiesViewAreaInsetKey = "{{0, 0}, {0, 0}}";
};
};
NSInterfaceStyle = macintosh;
NSLanguages = (
"zh-Hans-CN",
"en-CN",
"ja-JP",
en
);
PKKeychainVersionKey = 7;
key = test;
}
(
"zh-Hans-CN"
)
(
"zh-Hans-CN",
"en-CN",
"ja-JP"
)
说明:
其中的key = test 为自已设置的数据,其他的都是系统自带的。
可见当使用setObject:forKey:后,成功将AppleLanguages的值改成了("zh-Hans-CN")
当删除AppleLanguages的值后,AppleLanguages的值被重置为
(
"zh-Hans-CN",
"en-CN",
"ja-JP"
)
- 例4
//获取域名的数组
NSArray *array = [defaults volatileDomainNames];
NSLog(@"%@", array);
//获取对应域的数据
NSDictionary *dict0 = [defaults volatileDomainForName:array[0]];
NSDictionary *dict1 = [defaults volatileDomainForName:array[1]];
NSLog(@"dict0 = %@\ndict1 = %@", dict0, dict1);
//为该域设置新的数据
[defaults setVolatileDomain:@{@"volatile":@"111"} forName:array[0]];
dict0 = [defaults volatileDomainForName:array[0]];
NSLog(@"%@", dict0);
[defaults removeVolatileDomainForName:array[0]];
输出:
(
NSRegistrationDomain,
NSArgumentDomain
)
dict0 = {
AppleLanguages = (
"zh-Hans-CN",
"en-CN",
"ja-JP",
en
);
NSInterfaceStyle = macintosh;
NSLanguages = (
"zh-Hans-CN",
"en-CN",
"ja-JP",
en
);
key = defaults;
}
dict1 = {
}
{
volatile = 111;
}
说明:
可看到域名有NSRegistrationDomain和NSArgumentDomain。
NSRegistrationDomain域里保存着初始数据,而NSArgumentDomain域里没有数据。
而且NSRegistrationDomain域中有key = defaults这组数据,这是之前调用registerDefaults注册的默认值。
然后通过setVolatileDomain方法为NSRegistrationDomain域设置新的数据。
NSUserDefaults的三个特殊的系统域:
这个是一个系统级别的全局的域,存储着系统配置信息。
所有应用程序共享该域,不建议修改里面的数据据,可能造成应用程序启动失败。
NSString * const NSGlobalDomain;
这个是在本应用程序内可访问的域,存储着应用程序的信息。
可在Edit Scheme--Arguments--Arguments Passed On Launch添加,格式是 -key value
NSString * const NSArgumentDomain;
这个是存放临时数据的域,通过registerDefaults注册的默认值会存入其中
NSString * const NSRegistrationDomain;
还有两个隐藏的域
应用程序域,通过setObject设置的数据会保存在这里。
Application
国际化语言域,保存着关于多语言的配置。
Languages
通常NSUserDefault的搜索顺序为
NSArgumentDomain->Application->(通过addSuiteNamed添加的Application的子域)->NSGlobalDomain->Languages->NSRegistrationDomain
- 例5
NSArray *arr = [defaults persistentDomainNames];
NSLog(@"%@", arr);
//获取对应域的数据
NSDictionary *dict2 = [defaults persistentDomainForName:arr[0]];
NSDictionary *dict3 = [defaults persistentDomainForName:arr[1]];
NSLog(@"%@", dict2);
//为该域设置新的数据
[defaults setPersistentDomain:@{@"volatile":@"222"} forName:arr[0]];
dict2 = [defaults persistentDomainForName:arr[0]];
NSLog(@"%@", dict2);
[defaults removePersistentDomainForName:arr[0]];
dict2 = [defaults persistentDomainForName:arr[0]];
NSLog(@"%@", dict2);
输出:
(
nameDefaults,
"com.asiainfo.mobile.DEMO111"
)
{
name = liu;
}
{
volatile = 222;
}
(null)
说明:
持久性域中有两个域,分别为com.asiainfo.mobile.DEMO111和nameDefaults。
其中com.asiainfo.mobile.DEMO111为standardUserDefaults创建的plist。
nameDefaults是在例2中通过initWithSuiteName方法创建的。
通过persistentDomainForName获取域nameDefaults的数据,为name = liu。
通过setPersistentDomain为域nameDefaults设置新的数据,为volatile = 222。
通过removePersistentDomainForName移除域nameDefaults中的所有数据
三、使用NSUserDefaults将数据在不同应用程序间共享
![](https://img.haomeiwen.com/i2287567/a973a0a559a9b3c4.png)
先按上面图片添加一个组名
然后在该项目中输入以下代码,存入一个数据
//该plist并不会存入Library/Preferences文件夹中
NSUserDefaults *shareDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.asiainfo.liuxu"];
[shareDefaults setObject:@"abc123" forKey:@"shareId"];
在另一个项目中也照上面图片添加一个相同的组名
输入以下代码
NSUserDefaults *shareDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.asiainfo.liuxu"];
NSLog(@"%@", [shareDefaults objectForKey:@"shareId"]);
会输出abc123,说明数据已经共享。
网友评论