6.UIView與CALayer有什么區(qū)別
UIView管理繪制與事件處理(尤其是觸摸事件).CALayer完全關(guān)乎繪制.事實(shí)上,UIView依靠CALayer來管理繪制.CALayer不處理用戶的交互
每個(gè)UIView都有一個(gè)CALayer用于繪制.而且每個(gè)CALayer都可以擁有子圖層
7.iOS怎么做數(shù)據(jù)的持久化
沙箱目錄
iOS應(yīng)用程序只能訪問自己的目錄,這個(gè)目錄稱為沙箱目錄,應(yīng)用程序間禁止數(shù)據(jù)的共享和訪問
1>Documents目錄:用于存儲(chǔ)非常大的文件或需要頻繁更新的數(shù)據(jù),能夠進(jìn)行iTunes或iCloud備份.
// documentDirectory是只有一個(gè)元素的數(shù)組
NSArray *documentDirectory = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *myDocPath = [documentDirectory objectAtIndex:0];
或
NSString *myDocPath = [documentDirectory lastObject];
2>Library目錄:下有Preferences(用于存放應(yīng)用程序的設(shè)置數(shù)據(jù))和Caches目錄(存儲(chǔ)緩存文件)
3>tmp目錄:臨時(shí)文件目錄,用戶可以訪問它.不能進(jìn)行iTunes和iCloud的備份
NSString *tmpDirectory = NSTemporaryDirectory();
持久化方式:屬性列表,對(duì)象歸檔,SQLite數(shù)據(jù)庫,Core Data
屬性列表:集合對(duì)象可以讀寫到屬性列表文件中
NSArray類的方法(NSDictionary的方法類似):
- arrayWithContentsOfFile
- initWithContentOfFile
-
writeToFile:atomically 該方法把NSArray對(duì)象寫入到屬性列表文件中,第一個(gè)參數(shù)是文件名,第二個(gè)參數(shù)為是否使用輔助文件,如果為YES,則先寫入一個(gè)輔助文件,然后輔助文件再重新命名為目標(biāo)文件,如果為NO,則直接寫入到目標(biāo)文件
屏幕快照 2016-07-30 下午7.07.12.png
// NoteDAO.h
#import <Foundation/Foundation.h>
#import "Note.h"
@interface NoteDAO : NSObject
+ (NoteDAO *)sharedManager;
- (NSString *)applicationDocumentsDirectoryFile;
- (void)createEditableCopyOfDatabaseIfNeeded;
// 插入備忘錄的方法
- (int)create:(Note *)model;
// 刪除備忘錄的方法
- (int)remove:(Note *)model;
// 修改備忘錄的方法
- (int)modify:(Note *)model;
// 查詢所有數(shù)據(jù)方法
- (NSMutableArray *)findAll;
// 按照主鍵查詢數(shù)據(jù)方法
- (Note *)findById:(Note *)model;
@end
// NoteDAO.m
#import "NoteDAO.h"
@implementation NoteDAO
static NoteDAO *sharedManager = nil;
- (void)createEditableCopyOfDatabaseIfNeeded {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *writableDBPath = [self applicationDocumentsDirectoryFile];
BOOL dbexits = [fileManager fileExistsAtPath:writableDBPath];
if (!dbexits) {
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"NotesList.plist"];
NSError *error;
BOOL success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success) {
NSAssert1(0, @"錯(cuò)誤寫入文件:'%@'.", [error localizedDescription]);
}
}
}
- (NSString *)applicationDocumentsDirectoryFile {
NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [documentDirectory stringByAppendingPathComponent:@"NotesList.plist"];
return path;
}
+ (NoteDAO *)sharedManager {
static dispatch_once_t once;
dispatch_once(&once, ^{
sharedManager = [[self alloc] init];
[sharedManager createEditableCopyOfDatabaseIfNeeded];
});
return sharedManager;
}
- (int)create:(Note *)model {
NSString *path = [self applicationDocumentsDirectoryFile];
NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:path];
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDictionary *dict = [NSDictionary dictionaryWithObjects:@[[dateFormat stringFromDate:model.date], model.content] forKeys:@[@"date", @"content"]];
[array addObject:dict];
[array writeToFile:path atomically:YES];
return 0;
}
- (int)remove:(Note *)model {
NSString *path = [self applicationDocumentsDirectoryFile];
NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:path];
for (NSDictionary *dict in array) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *date = [dateFormatter dateFromString:[dict objectForKey:@"date"]];
// 比較日期主鍵是否相等
if ([date isEqualToDate:model.date]) {
[array removeObject:dict];
[array writeToFile:path atomically:YES];
break;
}
}
return 0;
}
- (int)modify:(Note *)model {
NSString *path = [self applicationDocumentsDirectoryFile];
NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:path];
for (NSDictionary *dict in array) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *date = [dateFormatter dateFromString:[dict objectForKey:@"date"]];
NSString *content = [dict objectForKey:@"content"];
if ([date isEqualToDate:model.date]) {
[dict setValue:content forKey:@"content"];
[array writeToFile:path atomically:YES];
break;
}
}
return 0;
}
- (NSMutableArray *)findAll {
NSString *path = [self applicationDocumentsDirectoryFile];
NSMutableArray *listData = [[NSMutableArray alloc] init];
NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:path];
for (NSDictionary *dict in array) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
Note *note = [[Note alloc] init];
note.date = [dateFormatter dateFromString:[dict objectForKey:@"date"]];
note.content = [dict objectForKey:@"content"];
[listData addObject:note];
}
return listData;
}
- (Note *)findById:(Note *)model {
NSString *path = [self applicationDocumentsDirectoryFile];
NSMutableArray *array = [[NSMutableArray alloc] initWithContentsOfFile:path];
for (NSDictionary *dict in array) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
Note *note = [[Note alloc] init];
note.date = [dateFormatter dateFromString:[dict objectForKey:@"date"]];
note.content = [dict objectForKey:@"content"];
if ([note.date isEqualToDate:model.date]) {
return note;
}
}
return nil;
}
@end
對(duì)象歸檔:對(duì)象歸檔是一種序列化方式,首先將歸檔對(duì)象序列化為一個(gè)文件,然后在通過反歸檔將數(shù)據(jù)恢復(fù)到對(duì)象中.但是不適用于大量數(shù)據(jù)和頻繁讀寫的情況.
使用要求:該對(duì)象的類必須實(shí)現(xiàn)NSCoding協(xié)議,而且每個(gè)成員變量應(yīng)該是基本數(shù)據(jù)類型或都是實(shí)現(xiàn)NSCoding協(xié)議的某個(gè)類的實(shí)例
// NoteDAO_Archive.h
#import <Foundation/Foundation.h>
#import "Note.h"
// 歸檔文件名
#define FILE_NAME @"NotesList.archive"
// 歸檔數(shù)據(jù)的鍵
#define ARCHIVE_KEY @"NotesList"
@interface NoteDAO_Archive : NSObject
+ (NoteDAO_Archive *)sharedManager;
- (NSString *)applicationDocumentsDirectoryFile;
- (void)createEditableCopyOfDatabaseIfNeeded;
// 插入備忘錄的方法
- (int)create:(Note *)model;
// 刪除備忘錄的方法
- (int)remove:(Note *)model;
// 修改備忘錄的方法
- (int)modify:(Note *)model;
// 查詢所有數(shù)據(jù)方法
- (NSMutableArray *)findAll;
// 按照主鍵查詢數(shù)據(jù)方法
- (Note *)findById:(Note *)model;
@end
// NoteDAO_Archive.m
#import "NoteDAO_Archive.h"
@implementation NoteDAO_Archive
static NoteDAO_Archive *sharedManager = nil;
- (void)createEditableCopyOfDatabaseIfNeeded {
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *writableDBPath = [self applicationDocumentsDirectoryFile];
BOOL dbexits = [fileManager fileExistsAtPath:writableDBPath];
if (!dbexits) {
NSString *path = [self applicationDocumentsDirectoryFile];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSDate *date1 = [dateFormatter dateFromString:@"2010-08-04 16:01:03"];
Note *note1 = [[Note alloc] init];
note1.date = date1;
note1.content = @"Welcome to MyNotes.";
NSDate *date2 = [dateFormatter dateFromString:@"2011-12-04 16:01:03"];
Note *note2 = [[Note alloc] init];
note2.date = date2;
note2.content = @"歡迎使用MyNotes.";
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:note1];
[array addObject:note2];
NSMutableData *theData = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:theData];
// 歸檔數(shù)據(jù)是放置在NSArray對(duì)象中的,將NSArray對(duì)象進(jìn)行歸檔,NSArray對(duì)象內(nèi)部沒喲個(gè)元素都是Note對(duì)象,而Note對(duì)象也必須是能夠被歸檔的,所以Note類實(shí)現(xiàn)了NSCoding協(xié)議
[archiver encodeObject:array forKey:ARCHIVE_KEY];
[archiver finishEncoding];
[theData writeToFile:path atomically:YES];
}
}
- (NSString *)applicationDocumentsDirectoryFile {
NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [documentDirectory stringByAppendingPathComponent:@"NotesList.plist"];
return path;
}
+ (NoteDAO_Archive *)sharedManager {
static dispatch_once_t once;
dispatch_once(&once, ^{
sharedManager = [[self alloc] init];
[sharedManager createEditableCopyOfDatabaseIfNeeded];
});
return sharedManager;
}
- (int)create:(Note *)model {
NSString *path = [self applicationDocumentsDirectoryFile];
NSMutableArray *array = [self findAll];
[array addObject:model];
/**
* 首先實(shí)例化NSMutableData對(duì)象theData
* 然后把theData作為參數(shù),再實(shí)例化NSKeyedArchiver對(duì)象archiver
* archiver對(duì)象的encodeObject:方法可以鍵對(duì)實(shí)現(xiàn)NSCoding協(xié)議的對(duì)象進(jìn)行歸檔
* [archiver finishEncoding]發(fā)出歸檔完成消息
*/
NSMutableData *theData = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:theData];
[archiver encodeObject:array forKey:ARCHIVE_KEY];
[archiver finishEncoding];
[theData writeToFile:path atomically:YES];
return 0;
}
- (int)remove:(Note *)model {
NSString *path = [self applicationDocumentsDirectoryFile];
NSMutableArray *array = [self findAll];
for (Note *note in array) {
// 比較日期主鍵是否相等
if ([note.date isEqualToDate:model.date]) {
[array removeObject:note];
NSMutableData *theData = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:theData];
[archiver encodeObject:array forKey:ARCHIVE_KEY];
[archiver finishEncoding];
[theData writeToFile:path atomically:YES];
break;
}
}
return 0;
}
- (int)modify:(Note *)model {
NSString *path = [self applicationDocumentsDirectoryFile];
NSMutableArray *array = [self findAll];
for (Note *note in array) {
// 比較日期主鍵是否相等
if ([note.date isEqualToDate:model.date]) {
note.content = model.content;
NSMutableData *theData = [NSMutableData data];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:theData];
[archiver encodeObject:array forKey:ARCHIVE_KEY];
[archiver finishEncoding];
[theData writeToFile:path atomically:YES];
break;
}
}
return 0;
}
- (NSMutableArray *)findAll {
NSString *path = [self applicationDocumentsDirectoryFile];
NSMutableArray *listData = [[NSMutableArray alloc] init];
NSData *theData = [NSData dataWithContentsOfFile:path];
if (theData.length > 0) {
NSKeyedUnarchiver *archiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];
listData = [archiver decodeObjectForKey:ARCHIVE_KEY];
[archiver finishDecoding];
}
return listData;
}
- (Note *)findById:(Note *)model {
NSString *path = [self applicationDocumentsDirectoryFile];
NSMutableArray *listData = [[NSMutableArray alloc] init];
NSData *theData = [NSData dataWithContentsOfFile:path];
if (theData.length > 0) {
NSKeyedUnarchiver *archiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];
listData = [archiver decodeObjectForKey:ARCHIVE_KEY];
[archiver finishDecoding];
for (Note *note in listData) {
// 比較日期主鍵是否相等
if ([note.date isEqualToDate:model.date]) {
return note;
}
}
}
return nil;
}
@end
SQLite數(shù)據(jù)庫:關(guān)系數(shù)據(jù)庫SQLite采用C語言編寫,具有可移植性強(qiáng),可靠性高,小而容易使用的特點(diǎn).
運(yùn)行時(shí)與它的應(yīng)用程序之間共用相同的進(jìn)程空間,而不是單獨(dú)的兩個(gè)進(jìn)程.支持多表,索引,事務(wù),視圖和觸發(fā)是無數(shù)據(jù)類型的數(shù)據(jù)庫.
雖然SQLite可以忽略數(shù)據(jù)類型,但從編程規(guī)范上講,應(yīng)該在Create Table語句中指定數(shù)據(jù)類型
INTEGER
有符號(hào)的整數(shù)類型
REAL
浮點(diǎn)類型
TEXT
字符串類型
BLOB
二進(jìn)制大對(duì)象類型,能夠存放任何二進(jìn)制數(shù)據(jù)
// NoteDAO_SQLite.h
#import <Foundation/Foundation.h>
#import "Note.h"
#import "sqlite3.h"
#define DBFILE_NAME @"NotesList.sqlite3"
@interface NoteDAO_SQLite : NSObject
{
sqlite3 *db;
}
+ (NoteDAO_SQLite *)sharedManager;
- (NSString *)applicationDocumentsDirectoryFile;
- (void)createEditableCopyOfDatabaseIfNeeded;
// 插入備忘錄的方法
- (int)create:(Note *)model;
// 刪除備忘錄的方法
- (int)remove:(Note *)model;
// 修改備忘錄的方法
- (int)modify:(Note *)model;
// 查詢所有數(shù)據(jù)方法
- (NSMutableArray *)findAll;
// 按照主鍵查詢數(shù)據(jù)方法
- (Note *)findById:(Note *)model;
@end
// NoteDAO_SQLite.m
#import "NoteDAO_SQLite.h"
@implementation NoteDAO_SQLite
static NoteDAO_SQLite *sharedManager = nil;
- (void)createEditableCopyOfDatabaseIfNeeded {
NSString *writableDBPath = [self applicationDocumentsDirectoryFile];
if (sqlite3_open([writableDBPath UTF8String], &db) != SQLITE_OK) {
sqlite3_close(db);
NSAssert(NO, @"數(shù)據(jù)庫打開失敗");
} else {
char *err;
NSString *createSQL = [NSString stringWithFormat:@"create table if not exists Note (cdate text primary key, content text);"];
if (sqlite3_exec(db, [createSQL UTF8String], NULL, NULL, &err) != SQLITE_OK) {
sqlite3_close(db);
NSAssert1(NO, @"建表失敗, %s", err);
}
sqlite3_close(db);
}
}
- (NSString *)applicationDocumentsDirectoryFile {
NSString *documentDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [documentDirectory stringByAppendingPathComponent:@"NotesList.plist"];
return path;
}
+ (NoteDAO_SQLite *)sharedManager {
static dispatch_once_t once;
dispatch_once(&once, ^{
sharedManager = [[self alloc] init];
[sharedManager createEditableCopyOfDatabaseIfNeeded];
});
return sharedManager;
}
- (int)create:(Note *)model {
NSString *path = [self applicationDocumentsDirectoryFile];
if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) {
sqlite3_close(db);
NSAssert(NO, @"數(shù)據(jù)庫打開失敗");
} else {
NSString *sqlStr = @"insert or replace into note (cdate,content) values (?,?)";
sqlite3_stmt *statement;
// 預(yù)處理過程
if (sqlite3_prepare_v2(db, [sqlStr UTF8String], -1, &statement, NULL) == SQLITE_OK) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSString *nsdate = [dateFormatter stringFromDate:model.date];
// 綁定參數(shù)開始
sqlite3_bind_text(statement, 1, [nsdate UTF8String], -1, NULL);
sqlite3_bind_text(statement, 2, [model.content UTF8String], -1, NULL);
// 執(zhí)行插入
if (sqlite3_step(statement) != SQLITE_OK) {
NSAssert(NO, @"插入數(shù)據(jù)失敗");
}
}
sqlite3_finalize(statement);
sqlite3_close(db);
}
return 0;
}
- (int)remove:(Note *)model {
NSString *path = [self applicationDocumentsDirectoryFile];
if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) {
sqlite3_close(db);
NSAssert(NO, @"數(shù)據(jù)庫打開失敗");
} else {
NSString *sqlStr = @"delete from note where cdate = ?";
sqlite3_stmt *statement;
// 預(yù)處理過程
if (sqlite3_prepare_v2(db, [sqlStr UTF8String], -1, &statement, NULL) == SQLITE_OK) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSString *nsdate = [dateFormatter stringFromDate:model.date];
// 綁定參數(shù)開始
sqlite3_bind_text(statement, 1, [nsdate UTF8String], -1, NULL);
// 執(zhí)行插入
if (sqlite3_step(statement) != SQLITE_DONE) {
NSAssert(NO, @"刪除數(shù)據(jù)失敗");
}
}
sqlite3_finalize(statement);
sqlite3_close(db);
}
return 0;
}
- (int)modify:(Note *)model {
NSString *path = [self applicationDocumentsDirectoryFile];
if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) {
sqlite3_close(db);
NSAssert(NO, @"數(shù)據(jù)庫打開失敗");
} else {
NSString *sqlStr = @"update note set content=? where cdate = ?";
sqlite3_stmt *statement;
// 預(yù)處理過程
if (sqlite3_prepare_v2(db, [sqlStr UTF8String], -1, &statement, NULL) == SQLITE_OK) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSString *nsdate = [dateFormatter stringFromDate:model.date];
// 綁定參數(shù)開始
sqlite3_bind_text(statement, 1, [model.content UTF8String], -1, NULL);
sqlite3_bind_text(statement, 2, [nsdate UTF8String], -1, NULL);
// 執(zhí)行插入
if (sqlite3_step(statement) != SQLITE_DONE) {
NSAssert(NO, @"修改數(shù)據(jù)失敗");
}
}
sqlite3_finalize(statement);
sqlite3_close(db);
}
return 0;
}
- (NSMutableArray *)findAll {
NSString *path = [self applicationDocumentsDirectoryFile];
NSMutableArray *listData = [[NSMutableArray alloc] init];
if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) {
sqlite3_close(db);
NSAssert(NO, @"數(shù)據(jù)庫打開失敗");
} else {
NSString *qsql = @"select cdate,content from Note";
sqlite3_stmt *statement;
// 預(yù)處理過程
if (sqlite3_prepare_v2(db, [qsql UTF8String], -1, &statement, NULL) == SQLITE_OK) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
while (sqlite3_step(statement) == SQLITE_ROW) {
char *cdate = (char *)sqlite3_column_text(statement, 0);
NSString *nscdate = [[NSString alloc] initWithUTF8String:cdate];
char *content = (char *)sqlite3_column_text(statement, 1);
NSString *nscontent = [[NSString alloc] initWithUTF8String:content];
Note *note = [[Note alloc] init];
note.date = [dateFormatter dateFromString:nscdate];
note.content = nscontent;
[listData addObject:note];
}
}
sqlite3_finalize(statement);
sqlite3_close(db);
}
return listData;
}
- (Note *)findById:(Note *)model {
NSString *path = [self applicationDocumentsDirectoryFile];
if (sqlite3_open([path UTF8String], &db) != SQLITE_OK) {
sqlite3_close(db);
NSAssert(NO, @"數(shù)據(jù)庫打開失敗");
} else {
NSString *qsql = @"select cdate,content from Note where cdate = ?";
sqlite3_stmt *statement;
// 預(yù)處理過程,將SQL編譯成二進(jìn)制代碼,提高SQL語句的執(zhí)行速度
if (sqlite3_prepare_v2(db, [qsql UTF8String], -1, &statement, NULL) == SQLITE_OK) {
// 準(zhǔn)備參數(shù)
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
NSString *nsdate = [dateFormatter stringFromDate:model.date];
// 綁定參數(shù)開始
sqlite3_bind_text(statement, 1, [nsdate UTF8String], -1, NULL);
// 執(zhí)行
if (sqlite3_step(statement) == SQLITE_ROW) {
char *cdate = (char *)sqlite3_column_text(statement, 0);
NSString *nscdate = [[NSString alloc] initWithUTF8String:cdate];
char *content = (char *)sqlite3_column_text(statement, 1);
NSString *nscontent = [[NSString alloc] initWithUTF8String:content];
Note *note = [[Note alloc] init];
note.date = [dateFormatter dateFromString:nscdate];
note.content = nscontent;
sqlite3_finalize(statement);
sqlite3_close(db);
return note;
}
}
sqlite3_finalize(statement);
sqlite3_close(db);
}
return nil;
}
@end
Core Data:蘋果為Mac OS X和iOS系統(tǒng)應(yīng)用開發(fā)提供的數(shù)據(jù)持久化技術(shù).基于高級(jí)數(shù)據(jù)持久化API,底層最終是SQLite數(shù)據(jù)庫,二進(jìn)制文件和內(nèi)存數(shù)據(jù)保存.
Core Data是一種ORM技術(shù)(對(duì)象關(guān)系映射
)
被管理對(duì)象上下文類(Managed Object Context, MOC)類,在上下文中可以查找,刪除和插入對(duì)象,然后通過棧同步到持久化對(duì)象存儲(chǔ)
被管理對(duì)象模型(Manaaged Object Model, MOM)類,是系統(tǒng)中的"實(shí)體",與數(shù)據(jù)庫中的表等對(duì)象對(duì)應(yīng)
持久化存儲(chǔ)協(xié)調(diào)器(Persistent Store Coordinator, PSC)類,在持久化對(duì)象存儲(chǔ)之上提供了一個(gè)接口,可以把它考慮成為數(shù)據(jù)庫的連接
MOC,MOM,PSC和持久化對(duì)象存儲(chǔ),它們一起構(gòu)成了Core Data堆棧
持久化對(duì)象存儲(chǔ)(Persistent Object Store, POS)執(zhí)行所有底層的從對(duì)象到數(shù)據(jù)的轉(zhuǎn)換,并負(fù)責(zé)打開和關(guān)閉數(shù)據(jù)文件.它有3種持久化實(shí)現(xiàn)方式:SQLite,二進(jìn)制文件和內(nèi)存形式
10.BAD_ACCESS在什么情況下出現(xiàn)?
在訪問一個(gè)已經(jīng)釋放的對(duì)象或向它發(fā)送消息時(shí),EXC_BAD_ACCESS就會(huì)出現(xiàn).造成EXC_BAD_ACCESS最常見的原因是,在初始化方法中初始化變量時(shí)用錯(cuò)了所有權(quán)修飾符,這會(huì)導(dǎo)致對(duì)象被釋放.
例:在viewDidLoad方法中為UITableViewController創(chuàng)建了一個(gè)包含元素的NSMutableArray,卻將該數(shù)組的所有權(quán)修飾符設(shè)成了unsafe_unretained或assign而不是strong.現(xiàn)在在cellForRowAtIndexPath:中,若要訪問已經(jīng)釋放掉的對(duì)象時(shí),就會(huì)得到名為EXC_BAD_ACCESS的崩潰.
通過設(shè)置NSZombieEnabled環(huán)境變量,來調(diào)試EXC_BAD_ACCESS