iOS数据持久化1-属性列表

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版》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值