iOS有一套完整的数据安全体系,iOS应用只能访问自己的目录,这个目录被称为沙箱目录,应用程序之间禁止数据的共享和访问。一些特定的应用,如联系人应用,必须通过特定的API来访问。
1、沙箱目录
应用目录下面有Documents、Library、tmp三个子目录。
documents目录
该目录用于存储非常大的文件或需要经常频繁更新的数据,能够进行iTunes或Cloud的备份。获取模具路位置的代码如下
swift代码
// An highlighted block
let documentsDirectory:NSArray=NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)
//documentsDirectory只有一个元素的数组,因此还需要使用下面的代码去除一个路径
let docPath=documentsDirectory[0] as NSString
//let docPath=documentsDirectory.lastObject as NSString
//因为只有一个元素,所以两者效果一样
ObjectiveC代码
// An highlighted block
NSArray *documentsDirectory=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
//documentsDirectory只有一个元素的数组,因此还需要使用下面的代码去除一个路径
NSString *docPath=[documentsDirectory objectAtIndex:0];
//NSString *docPath=[documentsDirectory lastObject];
//因为只有一个元素,所以两者效果一样
Library目录
Library目录下面有Preferences和Caches目录,其中前者用于存放应用程序的设置数据,后者与Documents很类似,可以存放应用程序的数据,用来存储缓存文件。
tmp目录
这是临时文件的目录,它不能进行iTunes或Cloud的备份。要获取该目录位置,如下代码
swift代码
let tmpDirectory=NSTemporaryDirectory()
ObjectiveC代码
NSString *tmpDirectory=NSTemporaryDirectory();
2、持久化方式
(1)属性列表,集合对象可以读写到属性列表文件中。
(2)SQLite数据库,SQLite是一个开源嵌入式关系型数据库。
(3)Core Data,是一种对象关系映射技术(ORM),本质是通过SQLite存储的。
属性列表
属性列表文件是一种XML文件.Foundation框架中的数组和字典等都可以与属性列表文件相互转换。
数组类NSArray和字典类NSDictionary提供了读写属性列表文件的方法,
NSArray类方法如下:
(1)+ arrayWithContentsOfFile:,静态创建工程方法用于从属性列表文件中读取数据,创建NSArray对象。Swift语言没有对应的构造函数。
(2)- initWithContentsOfFile:,构造函数,用于从属性列表文件中读取数据,创建NSArray对象。Swift语言为convenience init?(contentsOfFile aPath:String)。
(3)- writeToFile:atomically:,该方法把NSArray对象切入爽列表文件,然后将辅助文件重新命名为目标文件;如果为false,则直接写入目标文件。
NSDictionary类方法如下:
(1)+ dicctionaryWithContentsOfFile:,静态工厂方法,用于从属性列表文件中读取数据并创建NSDictionary对象,Swift语言没有对应的构造函数。
(2)- initWithContentsOfFile:,构造函数,用于从属性列表中读取数据并创建NSDictionary对象,Swift语言表示成convenience init?(contentsOfFile path:String)。
(3)-wiiteToFile:atomically:,将NSDictionary对象写入属性列表文件,它的第一个参数是文件名,第二个参数表明是否使用辅助文件,如果为true,先写入辅助文件,然后将辅助文件重命名为目标文件;如果为false,则直接写入目标文件。
例:一个简单备忘录的例子
Swift代码
// An highlighted block
//Note.swift文件
import Foundation
class Note{
var date:Date
var content:String
init(date:Date,content:String){
self.date=date
self.content=content
}
init(){
self.date=Date()
self.content=""
}
}
///访问属性文件的DAO是NoteDAO.
public class NoteDAO{
//私有属性
private var dateFormatter=DateFormatter()
private var plistFilePath:String!
public static let sharedInstance:NoteDAO={
let instance=NoteDAO()
//初始化沙箱目录中的属性列表文件路径
instance.plistFilePath=instance.applicationDocumentsDirectoryFile()
instance.dateFormatter.dateFormat="yyyy-MM-dd HH:mm:ss"
//初始化属性列表文件
instance.createEditableCopyOfDatabaseIfNeeded()
return instance
}()
//初始化属性列表文件
private func createEditableCopyOfDatabaseIfNeeded(){
let fileManager=fileManager.default
let dbexits=fileManager.fileExists(atPath:self.plistFilePath)
if(!dbexits){
let frameworkBundle=Bundle(for:NoteDAO.self)
let frameworkBundlePath=frameworkBundle.resourcePath as NSString?
let defaultDBPath=frameworkBundlePath!.appendingPathComporent("NotesList.plist")
do{
try fileManager.copyItem(atPath:defaultDBPath,toPath:self.plistFilePath)
}
catch{
let nserror=error as NSError
NSLog("数据保存错误:%@",nserror.localizedDescription)
assert(false,"错误写入文件")
}
}
}
//初始化沙箱目录中的属性列表文件路径
private func applicationDocumentsDirectoryFile()->String{
let documentDirectory:NSArray=NSSearchPathForDirectoriesInDomains(.documentDirectory,.userDomainMask,true) as NSArray
let path=(documentDirectory[0] as AnyObject).appendingPathComponent("NotesList.plist") as String
return path
}
//插入数据
public func create(_ model:Note)->Int{
let array=NSMutableArray(contentsOfFile:self.plistFilePath)!
let strDate=self.dateFormatter.string(from:model.date as Date)
let dict=NSDictionary(objects:[strDate,model.content],forKeys:["date" as NSCopying,"content" as NSCopying])
array.add(dict)
array.write(toFile:self.plistFilePath,atomically:true)
return 0
}
//删除数据
public func remove(_ model:Note)->Int{
let array=NSMutableArray(contentsOfFile:self.plistFilePath)!
let strDate=self.dateFormatter.string(from:model.date as Date)
let date=dateFormatter.date(from:strDate)
//比较日期是否相等
if date! == model.date as Date{
array.remove(dict)
array.write(toFile:self.plistFilePath,atomically:true)
break
}
}
//修改数据
public func modify(_model:Note)->Int{
let array=NSMutableArray(contentsOfFile:self.plistFilePath)!
for item in array{
let dict=item as! NSDictionary
let strDate=dict["date"] as! String
let date=dateFormatter.date(from:strDate)
//比较日期是否相等
if date! == model.date as Date{
dict.setValue(model.content,forKey:"content")
array.write(toFile:self.plistFilePath,atomically:true)
break
}
}
return 0
}
//查询全部数据
public func findAll()->NSMutableArray{
let array=NSMutableArray(contentOfFile:self.plistFilePath)!
let listData=NSMutableArray()
for item in array{
let dict=item as! NSDictionary
let strDate=dict["date"] as! String
let date=dateFormatter.date(from:strDate)!
let content=dict["content"] as! string
letnote=Note(date:date,content:content)
listData.add(note)
}
return listData
}
//按照日期查询数据
public func findById(_ model:Note)->Note?{
let array=NSMutableArray(contentsOfFile:self.plistFilePath)!
for item in array{
let dict =item as! NSDictionary
let strDate=dict["date"] as! String
let date=dateFormatter.date(from:strDate)!
let content=dict["content"] as! String
if date== model.date as Date{
let note=Note(date:date,content:content)
return note
}
}
return nil
}
}
ObjectiveC代码
// An highlighted block
//Note.h文件
#import <Foundation/Foundation.h>
@interface Note : NSObject
@property(nonatiomic,strong) NSDate* date;
@property(nonatiomic,strong) NSString* content;
//instancetype:返回未知类型
//instancetype解释(转载链接)https://blog.csdn.net/djvc/article/details/80424771
-(instancetype)initWithDate:(NSDate*)date content:(NSString*)content;
-(instancetype)init;
@end
//Note.m文件
#import "Note.h"
@implementation Note
-(instancetype)initWithDate:(NSDate*)date content:(NSString*)content{
self=[super init];
if(self){
self.date=date;
self.content=content;
}
return self;
}
-(instancetype)init{
self=[super init];
if(self){
self.date=[[NSDate alloc] init];
self.content=@"";
}
return self;
}
///访问属性文件的DAO是NoteDAO.
//NoteDAO.h文件
#import "Note.h"
@interface NoteDAO:NSObject
@end
//NoteDAO.m文件
#import "NoteDAO.h"
@interface NoteDAO()
@property(nonatomic,strong) NSDateFormatter *dateFormatter;
@property(nonatomic,strong) NSString *plistFilePath;
@end
@implementation NoteDAO
static NoteDAO *sharedSingletion=nil;
+ (NoteDAO*)sharedInstance{
//dispatch_once_t解释:(转载)https://blog.csdn.net/ldczzzzzz/article/details/74171866
statice dispatch_once_t once;
//dispathch_once转载:https://www.jianshu.com/p/2677f3ad0014
dispathch_once(&once,^{
sharedSingletion=[[self alloc] init];
//初始化沙箱目录中的属性列表文件路径
sharedSingletion.plistFilePath=[sharedSingletion applicationDocumentsDirectoryFile];
//初始化DateFormatter
sharedSingletion.dateFormatter=[[NSDateFormatter alloc] init];
[sharedSingletion.dateFormatter setDateFormat:@"yyy-MM-dd HH:mm:ss"];
//初始化属性列表文件
[sharedSingletion createEditableCopyOfDatabaseIfNeeded];
});
return sharedSingletion;
}
//初始化属性列表文件
-(void)createEditableCopyOfDatabaseIfNeeded{
NSFileManager *fileManager=[NSFileManager defaultManager];
BOOL dbexits =[fileManager fileEistsAtPath:self.plistFilePath];
if(!dbexits)
{
//转载文件操作:https://www.cnblogs.com/guanliyang/p/3906969.html
//NSBundle,可以访问大年程序的资源目录,方法主要有两个,mainBundle:和+ bundleForClass,前者获取主NSBundle对象,即当前运行应用程序的NSBundle对象;后者获得当前类所在的NSBundle对象。
NSBundle *frameworkBundle=[NSBundle bundleForClass:[NoteDAO class]];
NSString *frameworkBundlePath=[frameworkBundle resourcePath];
NSString *defaultDBPath=[frameworkBundlePath stringByAppendingPathComponent:@"NotesList.plist"];
NSError *error;
BOOL success=[fileManager copyItemAtPath:defaultDBPath toPath:self.plistFilePath error:&error];
//在第一个参数weifalse时抛出异常
NSAssert(success,@"错误写入文件");
}
}
//用于获得沙箱Documents目录中NotesList.plist文件的完整路径
-(NSString *)applicationDocumentsDirectoryFile{
NSString *documentDirectory=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES) lastObject];
NSString *path=[documentDirectory stringByAppendingPathComporent:@"NotesList.plist"];
return path;
}
//插入数据
-(int)create:(Note*)model{
//使用NSMutableArray的initWithContentsOfFile:读取属性列表文件内容,并初始化到NSMutableArray对象
NSMutableArray *array=[[NSMutableArray alloc] initWithContentsOfFile:self.plistFilePath];
//NSDate对象转换成为yyyy-MM-dd HH:mm:ss格式的字符串
NSString*strDate=[self.dateFormatter stringFromDate:model.date];
NSDictionary *dict=@{@"date":strDate,@"content":model.content};
[array addObject:dict];
//将日期字符串重新写入到属性列表文件中。
[array writeToFile:self.plistFilePathatomically:YES];
return 0;
}
//删除数据
-(int)remove:(Note*)model{
//使用NSMutableArray的initWithContentsOfFile:读取属性列表文件内容,并初始化到NSMutableArray对象
NSMutableArray *array=[[NSMutableArray alloc] initWithContentsOfFile:self.plistFilePath];
for(NSDictionary *dict in array){
NSString *strDate=dict[@"date"];
NSDate *date=[self.dateFormatter dateFromString:strDate];
//比较日期逐渐是否相等,isEqualToDate用于判断两个日期是否相等
if([date isEqualToDate:model.date]){
[array removeObject:dict];
[array writeToFile:self.plistFilePathatomically:YES];
break;
}
}
return 0;
}
//修改数据
-(int)modify:(Note*)model{
//使用NSMutableArray的initWithContentsOfFile:读取属性列表文件内容,并初始化到NSMutableArray对象
NSMutableArray *array=[[NSMutableArray alloc] initWithContentsOfFile:self.plistFilePath];
for(NSDictionary *dict in array){
NSString *strDate=dict[@"date"];
NSDate *date=[self.dateFormatter dateFromString:strDate];
//比较日期逐渐是否相等,isEqualToDate用于判断两个日期是否相等
if([date isEqualToDate:model.date]){
[dict setValue:model.content forKey:@"content"];
[array writeToFile:self.plistFilePathatomically:YES];
break;
}
}
return 0;
}
//查询所有数据
-(NSMutableArray*)findAll{
//使用NSMutableArray的initWithContentsOfFile:读取属性列表文件内容,并初始化到NSMutableArray对象
NSMutableArray *array=[[NSMutableArray alloc] initWithContentsOfFile:self.plistFilePath];
NSMutableArray *listData=[[NSMutableArray alloc] init];
for(NSDictionary*dict in array){
NSString *strData=dict[@"date"];
NSDate *date=[self.dateFormatter dateFromString:strDate];
NSString *centent=@[@"content"];
Note *note=[[Note alloc] initWithDate:date content:content];
[listData addObject:note];
}
return listData;
}
//按照日期查询数据
-(Note*)findById:(Note*)model{
NSMutableArray *array=[[NSMutableArray alloc] initWithContentsOfFile:self.plistFilePath];
for(NSDictionary *dict inarray){
NSString *strDate=dict[@"date"];
NSDate *date=[self.dateFormatter dateFromString:strDate];
NSString *centent=@[@"content"];
if([date isEqualToDate:model.date]){
Note *note=[[Note alloc] initWithDate:date content:content];
return note;
}
}
return nil;
}
@end
参考资料
《IOS开发指南 从HELLO WORLD到APP STORE上架 第5版》