iOS开发技术分享(1)— iOS本地数据存储
iOS开发技术分享(1)— iOS本地数据存储
前言:
我本是一名asp.net程序员,后来加入了iOS游戏开发队伍,到现在也有一年多的时间了。这一年来,每天都干到2、3点钟才睡觉,不为别的,只为了学多点东西。这段时间,什么都学,从C#到Objective-C,到C++,慢慢理解了编程真的不论语言,只要熟悉一种语言,想要上手另一门语言,真的是一件很简单的事情,用心者半个月即可上手工作(当然这里说的是可以上手,想要精通肯定是需要一定时间钻研的)。我想说的是,只要你喜欢,程序员真的不是一份很苦逼的工作,反之,我倒是觉得其乐融融,加油吧,程序员朋友们!
工作之余,忙活了一个多月,终于把【美女那些图】做完了,接下来我会陆续写一些技术分享文章,包括服务端和客户端,都分享一下这个项目的核心代码。说得不对的地方,请多多包涵,并帮忙指正,谢谢。
首先先把项目的截图贴出来,好让大家了解这个App是做什么的,本app已经适配了3.5inch和4.0inch的屏幕,如果用像素表示,则是适配了320*480、640*960以及640*1136。这里贴出在iPhone5上的截图。
美女欣赏,绝不包含黄色内容,请放心下载。
这里是下载地址:http://itunes.apple.com/cn/app/id590438908
还请各位朋友捧捧场,给个好评,多谢了。
iOS本地数据存储:
关于iOS本地数据存储方面,常用的方法有好几种,比如plist,xml,NSUserDefaults,keychain等,但是,各自都有各自的特点,下面我就简单的把NSUserDefaults和keychain介绍一下,并给出demo,好让新手快速入门。
1、NSUserDefaults
一般情况下,由于NSUserDefaults存储的数据不够安全,用户可以随意根据自己的需要更改里面的数据,所以NSUserDefaults一般只会被用来存储App的设置数据等,这就好比web中的cookie,同样可以存储数据,但是不够安全。
上代码
Setting.h:

1 #import <Foundation/Foundation.h>
2
3 typedef enum {
4 ST_Music = 100,
5 ST_Volume,
6 ST_Push,
7 ST_Num
8 }SettingType;//各种设置的枚举
9
10 @interface Setting : NSObject
11 //读取getter
12 + (bool)getIsEnableByType:(SettingType)type;
13 //设置setter
14 + (void)setIsEnable:(bool)isEnable byType:(SettingType)type;
15 //清空数据
16 + (void)resetData;
17
18 @end

setting.mm

1 #import "Setting.h"
2
3 #define KEY_SETTING @"BeautyPics_"
4
5 @implementation Setting
6
7 + (void)resetData
8 {
9 for (SettingType type = ST_Music; type < ST_Num; type++) {
10 [Setting setIsEnable:true byType: type];//默认全部为true
11 }
12 }
13
14 + (bool)getIsEnableByType:(SettingType)type
15 {
16 NSString * key = [KEY_SETTING stringByAppendingFormat:@"%d", type];
17 id isEnable = [[NSUserDefaults standardUserDefaults] objectForKey: key];
18 if (isEnable == nil) {
19 [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool: true] forKey:key];
20 [[NSUserDefaults standardUserDefaults] synchronize];
21 return true;
22 }
23 return [isEnable boolValue];
24 }
25
26 + (void)setIsEnable:(bool)isEnable byType:(SettingType)type
27 {
28 NSString * key = [KEY_SETTING stringByAppendingFormat:@"%d", type];
29
30 if ([Setting getIsEnableByType: type] != isEnable) {
31 [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool: isEnable] forKey:key];
32 [[NSUserDefaults standardUserDefaults]synchronize];
33 }
34 }
35
36 @end

以上代码一目了然,需要注意的是,每次设置完数据之后,一定要通过 [[NSUserDefaults standardUserDefaults] synchronize]来同步,否则数据将不会保存起来。
2、keychain
既然NSUserDefaults不够安全,那么有没有一些比较安全的本地数据存储方式呢,答案当然是有的,这就是keychain,keychain只能该App本身访问,其他的App不能访问(当然现在只要通过设置是可以的。但是要通过这种形式:App1同意App2访问,App2才能访问到App1所存储的keychain)。关于keychain的文章很多,我不重复其原理,这里举出其用法,keychain的存储方式同样也是字典,也就是NSMutableDictionary,下面上代码:
(1)保存数据。其中data可以是NSArray、NSSet,NSDictionary等,一般情况下这三种数据结构已经足够用了。service就是要存储的key了。

+ (void)saveData:(NSString *)service data:(id)data
{
//Get search dictionary
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
//Delete old item before add new item
SecItemDelete((CFDictionaryRef)keychainQuery);
//Add new object to search dictionary(Attention:the data format)
[keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
//Add item to keychain with the search dictionary
SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
}

(2)读取数据。直接通过保存数据是使用的key即可读取所存数据。

+ (id)loadData:(NSString *)service
{
id ret = nil;
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
//Configure the search setting
//Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue
[keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
[keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
CFDataRef keyData = NULL;
if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
@try {
ret = [NSKeyedUnarchiver unarchiveObjectWithData:(NSData *)keyData];
} @catch (NSException *e) {
NSLog(@"Unarchive of %@ failed: %@", service, e);
} @finally {
}
}
if (keyData)
CFRelease(keyData);
return ret;
} + (NSMutableDictionary *)getKeychainQuery:(NSString *)service
{
NSMutableDictionary * dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:
(id)kSecClassGenericPassword,(id)kSecClass,
service, (id)kSecAttrService,
service, (id)kSecAttrAccount,
(id)kSecAttrAccessibleAfterFirstUnlock,(id)kSecAttrAccessible,
nil];
return dict;
}

(2)demo。以上已经可以实现使用keychain读取和存储数据了。那么接下来我们来一小段demo。
比如我要存储NSDictionary,用户名为“阿泰”,密码为“123456”,则:
1 NSDictionary * dict = [NSDictionary dictionaryWithObjectsAndKeys:@"阿泰",@"key_username",@"123456",@"key_pwd", nil];
2 [Keychain saveData:KEY_USER_DATA_ALL data: dict];
其中 KEY_USER_DATA_ALL 为所保存的数据的key,可以通过这个key把保存的字典读出来。
读取时,如下:
1 NSDictionary * loadDict = [Keychain loadData: KEY_USER_DATA_ALL];
如此就把刚刚存储的字典dict读出来了,接下来要做的事情当然变得随心所欲。
这里是下载地址:http://itunes.apple.com/cn/app/id590438908
二维码下载:
未完待续。。。下一篇文章,将讲到开源类库 ASIHttpRequest 和 SDWebImage 的使用。
iOS开发技术分享(1)— iOS本地数据存储的更多相关文章
- iOS开发 - OC - 实现本地数据存储的几种方式一
iOS常用的存储方式介绍 在iOS App开发过程中经常需要操作一些需要持续性保留的数据,比如用户对于App的相关设置.需要在本地缓存的数据等等.本文针对OC中经常使用的一下存储方式做了个整理. 常用 ...
- iOS开发 - OC - 实现本地数据存储的几种方式二(直接使用sqlite)
连接上一篇文章http://www.cnblogs.com/FBiOSBlog/p/5819418.html. 上一篇文章介绍了OC内部一些方法进行数据的本地存储,其中包括 NSUser类.Plist ...
- 渐进式web应用开发---使用indexedDB实现ajax本地数据存储(四)
在前几篇文章中,我们使用service worker一步步优化了我们的页面,现在我们学习使用我们之前的indexedDB, 来缓存我们的ajax请求,第一次访问页面的时候,我们请求ajax,当我们继续 ...
- iOS APP之本地数据存储(译)
最近工作中完成了项目的用户信息本地存储,查阅了一些本地存储加密方法等相关资料.期间发现了一个来自印度理工学院(IIT)的信息安全工程师的个人博客,写了大量有关iOS Application secur ...
- iOS开发——数据持久化&使用NSUserDefaults来进行本地数据存储
使用NSUserDefaults来进行本地数据存储 NSUserDefaults适合存储轻量级的本地客户端数据,比如记住密码功能,要保存一个系统的用户名.密码.使用NSUserDefaults是首 ...
- fir.im Weekly - 8 个不能错过的 iOS / Android 技术分享
本期 fir.im Weekly 收集了 2 月下旬新鲜出炉的 iOS /Android 技术分享.源码等,iOS 中图片技术的解压缩.逆向实战.iOS SDK 实践,Android架构思考.Andr ...
- iOS 开发技术体系
iOS 开发技术体系图: - 层级 | 主要框架 - ---------------------|--------------------------------------------------- ...
- 《iOS开发全然上手——使用iOS 7和Xcode 5开发移动与平板应用》之Objective-C新手训练营
编写Hello World应用程序通常被觉得,是学习不论什么编程语言的第一步.在这一章,你将创建iOS版的Hello World应用程序作为起步,高速了解Xcode这个开发iOS应用程序的主要工具. ...
- Windows 8 应用开发 - 本地数据存储
原文:Windows 8 应用开发 - 本地数据存储 在应用中通常会遇到用户主动或被动存储信息的情况,当应用关闭后这些数据仍然会存储在本地设备上,用户下次重新激活应用时会自动加载这些数据.下 ...
随机推荐
- uva 12003 Array Transformer (大规模阵列)
白皮书393页面. 乱搞了原始数组中.其实用另一种阵列块记录. 你不能改变原始数组. 请注意,与原来的阵列和阵列块的良好关系,稍微细心处理边境.这是不难. #include <cstdio> ...
- 私人定制javascript中数组小知识点(Only For Me)
先上笑话,1.刚看到一个游泳的,想起公司组织去三亚旅游,老板跳海里,各种挣扎,捞上来老板第一句话:我记得我会游泳的啊. 2.媳妇说:老公对不起,我把你新买的自行车撞散架了! 老公:没事宝贝,你若安好, ...
- .NET平台机器学习
.NET平台机器学习资源汇总,有你想要的么? 接触机器学习1年多了,由于只会用C#堆代码,所以只关注.NET平台的资源,一边积累,一边收集,一边学习,所以在本站第101篇博客到来之际,分享给大家.部分 ...
- java界面编程(8) ------ 组合框(下拉列表)
本文是自己学习所做笔记,欢迎转载,但请注明出处:http://blog.csdn.net/jesson20121020 与一组单选button的功能类似,组合框(下拉列表)也是强制用户从一组可能的元素 ...
- Linux线程 之 线程 线程组 进程 轻量级进程(LWP)
Thread Local Storage,线程本地存储,大神Ulrich Drepper有篇PDF文档是讲TLS的,我曾经努力过三次尝试搞清楚TLS的原理,均没有彻底搞清楚.这一次是第三次,我沉浸gl ...
- MyReport报表引擎2.7.6.7新功能
新增二维码控件PDF417 设计器新增数据选项卡,可以拖放字段进行绑定 相关链接 MyReport演示.产品站点 相关文章 MyReport专栏
- Codeforces 484B Maximum Value(高效+二分)
题目链接:Codeforces 484B Maximum Value 题目大意:给定一个序列,找到连个数ai和aj,ai%aj尽量大,而且ai≥aj 解题思路:类似于素数筛选法的方式,每次枚举aj,然 ...
- Android学习笔记:Home Screen Widgets(1):大约Widget
什么是Home Screen Widgets Home screen Widget即称为小工具或者中文小工具,是显示在主页上的views,通过后台进程更新view的数据. Android由AppWid ...
- xfire集成spring构建webservice
前言:xfire.spring都是比较流行的技术,这里就不再赘述他们各自的优点:本文着重介绍xfire和spring的整合,不会做太深入的探究. 服务端 1. web.xml配置 spring配置部分 ...
- poj3744高速功率矩阵+可能性DP
Scout YYF I Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 4410 Accepted: 1151 Descr ...