日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[Cocoa]深入浅出 Cocoa 之 Core Data(2)- 手动编写代码

發(fā)布時(shí)間:2024/9/30 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Cocoa]深入浅出 Cocoa 之 Core Data(2)- 手动编写代码 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

深入淺出 Cocoa 之 Core Data(2)- 代碼示例

羅朝輝(http://blog.csdn.net/kesalin)

CC 許可,轉(zhuǎn)載請(qǐng)注明出處

前面 詳細(xì)講解了 Core Data 的框架以及設(shè)計(jì)的類,下面我們來講解一個(gè)完全手動(dòng)編寫代碼使用這些類的示例,這個(gè)例子來自蘋果官方示例。在這個(gè)例子里面,我們打算做這樣一件事情:記錄程序運(yùn)行記錄(時(shí)間與 process id),并保存到xml文件中。我們使用 Core Data 來做這個(gè)事情。

示例代碼下載:點(diǎn)擊這里


一,建立一個(gè)新的 Mac?command-line tool application 工程,命名為 CoreDataTutorial。為支持垃圾主動(dòng)回收機(jī)制,點(diǎn)擊項(xiàng)目名稱,在右邊的 Build Setting 中查找?garbage 關(guān)鍵字,將找到的 Objective-C Garbage Collection 設(shè)置為 Required [-fobj-gc-only]。并將 ?main.m 中 的 main() 方法修改為如下:

[cpp]?view plaincopyprint?
  • int?main?(int?argc,?const?char?*?argv[])??
  • {??
  • ????NSLog(@"?===?Core?Data?Tutorial?===");??
  • ??
  • ????//?Enable?GC??
  • ????//??
  • ????objc_startCollectorThread();??
  • ??????
  • ????return?0;??
  • }??

  • 二,創(chuàng)建并設(shè)置模型類

    在 main() 之前添加如下方法:

    [cpp]?view plaincopyprint?
  • NSManagedObjectModel?*managedObjectModel()??
  • {??
  • ????static?NSManagedObjectModel?*moModel?=?nil;??
  • ??
  • ????if?(moModel?!=?nil)?{??
  • ????????return?moModel;??
  • ????}??
  • ??????
  • ????moModel?=?[[NSManagedObjectModel?alloc]?init];??
  • ??????
  • ????//?Create?the?entity??
  • ????//??
  • ????NSEntityDescription?*runEntity?=?[[NSEntityDescription?alloc]?init];??
  • ????[runEntity?setName:@"Run"];??
  • ????[runEntity?setManagedObjectClassName:@"Run"];??
  • ??????
  • ????[moModel?setEntities:[NSArray?arrayWithObject:runEntity]];??
  • ??????
  • ????//?Add?the?Attributes??
  • ????//??
  • ????NSAttributeDescription?*dateAttribute?=?[[NSAttributeDescription?alloc]?init];??
  • ????[dateAttribute?setName:@"date"];??
  • ????[dateAttribute?setAttributeType:NSDateAttributeType];??
  • ????[dateAttribute?setOptional:NO];??
  • ??????
  • ????NSAttributeDescription?*idAttribute?=?[[NSAttributeDescription?alloc]?init];??
  • ????[idAttribute?setName:@"processID"];??
  • ????[idAttribute?setAttributeType:NSInteger32AttributeType];??
  • ????[idAttribute?setOptional:NO];??
  • ????[idAttribute?setDefaultValue:[NSNumber?numberWithInteger:-1]];??
  • ??
  • ????//?Create?the?validation?predicate?for?the?process?ID.??
  • ????//?The?following?code?is?equivalent?to?validationPredicate?=?[NSPredicate?predicateWithFormat:@"SELF?>?0"]??
  • ????//??
  • ????NSExpression?*lhs?=?[NSExpression?expressionForEvaluatedObject];??
  • ????NSExpression?*rhs?=?[NSExpression?expressionForConstantValue:[NSNumber?numberWithInteger:0]];??
  • ??????
  • ????NSPredicate?*validationPredicate?=?[NSComparisonPredicate??
  • ????????????????????????????????????????predicateWithLeftExpression:lhs??
  • ????????????????????????????????????????rightExpression:rhs??
  • ????????????????????????????????????????modifier:NSDirectPredicateModifier??
  • ????????????????????????????????????????type:NSGreaterThanPredicateOperatorType??
  • ????????????????????????????????????????options:0];??
  • ??????
  • ????NSString?*validationWarning?=?@"Process?ID?<?1";??
  • ????[idAttribute?setValidationPredicates:[NSArray?arrayWithObject:validationPredicate]??
  • ??????????????????withValidationWarnings:[NSArray?arrayWithObject:validationWarning]];??
  • ??????
  • ????//?set?the?properties?for?the?entity.??
  • ????//??
  • ????NSArray?*properties?=?[NSArray?arrayWithObjects:?dateAttribute,?idAttribute,?nil];??
  • ????[runEntity?setProperties:properties];??
  • ??????
  • ????//?Add?a?Localization?Dictionary??
  • ????//??
  • ????NSMutableDictionary?*localizationDictionary?=?[NSMutableDictionary?dictionary];??
  • ????[localizationDictionary?setObject:@"Date"?forKey:@"Property/date/Entity/Run"];??
  • ????[localizationDictionary?setObject:@"Process?ID"?forKey:@"Property/processID/Entity/Run"];??
  • ????[localizationDictionary?setObject:@"Process?ID?must?not?be?less?than?1"?forKey:@"ErrorString/Process?ID?<?1"];??
  • ??????
  • ????[moModel?setLocalizationDictionary:localizationDictionary];??
  • ??????
  • ????return?moModel;??
  • }??

  • 在上面的代碼中:

    1)我們創(chuàng)建了一個(gè)全局模型?moModel;
    2)并在其中創(chuàng)建一個(gè)名為?Run 的 Entity,這個(gè) Entity 對(duì)應(yīng)的?ManagedObject 類名為?Run(很快我們將創(chuàng)建這樣一個(gè)類);
    3)給 Run Entity 添加了兩個(gè)必須的 Property:date 和 processID,分別表示運(yùn)行時(shí)間以及進(jìn)程 ID;并設(shè)置默認(rèn)的進(jìn)程 ID 為 -1;
    4)給 processID 特性設(shè)置檢驗(yàn)條件:必須大于 0;
    5)給模型設(shè)置本地化描述詞典;

    本地化描述提供對(duì) Entity,Property,Error信息等的便于理解的描述,其可用的鍵值對(duì)如下表:

    Key

    Value


    "Entity/NonLocalizedEntityName"

    "LocalizedEntityName"


    "Property/NonLocalizedPropertyName/Entity/EntityName"

    "LocalizedPropertyName"


    "Property/NonLocalizedPropertyName"

    "LocalizedPropertyName"


    "ErrorString/NonLocalizedErrorString"

    "LocalizedErrorString"



    三,創(chuàng)建并設(shè)置運(yùn)行時(shí)類和對(duì)象

    由于要用到存儲(chǔ)功能,所以我們必須定義持久化數(shù)據(jù)的存儲(chǔ)路徑。我們?cè)?main() 之前添加如下方法設(shè)置存儲(chǔ)路徑:

    [cpp]?view plaincopyprint?
  • NSURL?*applicationLogDirectory()??
  • {??
  • ????NSString?*LOG_DIRECTORY?=?@"CoreDataTutorial";??
  • ????static?NSURL?*ald?=?nil;??
  • ??????
  • ????if?(ald?==?nil)??
  • ????{??
  • ????????NSFileManager?*fileManager?=?[[NSFileManager?alloc]?init];??
  • ????????NSError?*error?=?nil;??
  • ????????NSURL?*libraryURL?=?[fileManager?URLForDirectory:NSLibraryDirectory?inDomain:NSUserDomainMask??
  • ???????????????????????????????????????appropriateForURL:nil?create:YES?error:&error];??
  • ????????if?(libraryURL?==?nil)?{??
  • ????????????NSLog(@"Could?not?access?Library?directory\n%@",?[error?localizedDescription]);??
  • ????????}??
  • ????????else??
  • ????????{??
  • ????????????ald?=?[libraryURL?URLByAppendingPathComponent:@"Logs"];??
  • ????????????ald?=?[ald?URLByAppendingPathComponent:LOG_DIRECTORY];??
  • ??????????????
  • ????????????NSLog(@"?>>?log?path?%@",?[ald?path]);??
  • ??????????????
  • ????????????NSDictionary?*properties?=?[ald?resourceValuesForKeys:[NSArray?arrayWithObject:NSURLIsDirectoryKey]?error:&error];??
  • ????????????if?(properties?==?nil)??
  • ????????????{??
  • ????????????????if?(![fileManager?createDirectoryAtPath:[ald?path]?withIntermediateDirectories:YES?attributes:nil?error:&error])??
  • ????????????????{??
  • ????????????????????NSLog(@"Could?not?create?directory?%@\n%@",??
  • ??????????????????????????[ald?path],?[error?localizedDescription]);??
  • ????????????????????ald?=?nil;??
  • ????????????????}??
  • ????????????}??
  • ????????}??
  • ????}??
  • ??????
  • ????return?ald;??
  • }??

  • 在上面的代碼中,我們將持久化數(shù)據(jù)文件保存到路徑: /Users/kesalin/Library/Logs/CoreDataTutorial 下。

    下面,我們來創(chuàng)建運(yùn)行時(shí)對(duì)象:ManagedObjectContext 和 PersistentStoreCoordinator。

    [cpp]?view plaincopyprint?
  • NSManagedObjectContext?*managedObjectContext()??
  • {??
  • ????static?NSManagedObjectContext?*moContext?=?nil;??
  • ????if?(moContext?!=?nil)?{??
  • ????????return?moContext;??
  • ????}??
  • ??????
  • ????moContext?=?[[NSManagedObjectContext?alloc]?init];??
  • ??????
  • ????//?Create?a?persistent?store?coordinator,?then?set?the?coordinator?for?the?context.??
  • ????//??
  • ????NSManagedObjectModel?*moModel?=?managedObjectModel();??
  • ????NSPersistentStoreCoordinator?*coordinator?=?[[NSPersistentStoreCoordinator?alloc]?initWithManagedObjectModel:moModel];??
  • ????[moContext?setPersistentStoreCoordinator:?coordinator];??
  • ??????
  • ????//?Create?a?new?persistent?store?of?the?appropriate?type.???
  • ????//??
  • ????NSString?*STORE_TYPE?=?NSXMLStoreType;??
  • ????NSString?*STORE_FILENAME?=?@"CoreDataTutorial.xml";??
  • ??????
  • ????NSError?*error?=?nil;??
  • ????NSURL?*url?=?[applicationLogDirectory()?URLByAppendingPathComponent:STORE_FILENAME];??
  • ??????
  • ????NSPersistentStore?*newStore?=?[coordinator?addPersistentStoreWithType:STORE_TYPE??
  • ????????????????????????????????????????????????????????????configuration:nil??
  • ??????????????????????????????????????????????????????????????????????URL:url??
  • ??????????????????????????????????????????????????????????????????options:nil??
  • ????????????????????????????????????????????????????????????????????error:&error];??
  • ??????
  • ????if?(newStore?==?nil)?{??
  • ????????NSLog(@"Store?Configuration?Failure\n%@",?([error?localizedDescription]?!=?nil)???[error?localizedDescription]?:?@"Unknown?Error");??
  • ????}??
  • ??
  • ????return?moContext;??
  • }??

  • 在上面的代碼中:
    1)我們創(chuàng)建了一個(gè)全局?ManagedObjectContext 對(duì)象?moContext;
    2)并在設(shè)置其 persistent store coordinator,存儲(chǔ)類型為 xml,保存文件名為:CoreDataTutorial.xml,并將其放到前面定義的存儲(chǔ)路徑下。

    好,至此萬事具備,只欠 ManagedObject 了!下面我們就來定義這個(gè)數(shù)據(jù)對(duì)象類。向工程添加 Core Data->NSManagedObject subclass 的類,名為 Run (模型中 Entity 定義的類名)?。

    Run.h

    [cpp]?view plaincopyprint?
  • #import?<CoreData/NSManagedObject.h>??
  • ??
  • @interface?Run?:?NSManagedObject??
  • {??
  • ????NSInteger?processID;??
  • }??
  • ??
  • @property?(retain)?NSDate?*date;??
  • @property?(retain)?NSDate?*primitiveDate;??
  • @property?NSInteger?processID;??
  • ??
  • @end??

  • Run.m
    [cpp]?view plaincopyprint?
  • //??
  • //??Run.m??
  • //??CoreDataTutorial??
  • //??
  • //??Created?by?kesalin?on?8/29/11.??
  • //??Copyright?2011?kesalin@gmail.com.?All?rights?reserved.??
  • //??
  • ??
  • #import?"Run.h"??
  • ??
  • @implementation?Run??
  • ??
  • @dynamic?date;??
  • @dynamic?primitiveDate;??
  • ??
  • -?(void)?awakeFromInsert??
  • {??
  • ????[super?awakeFromInsert];??
  • ??
  • ????self.primitiveDate?=?[NSDate?date];??
  • }??
  • ??
  • #pragma?mark?-??
  • #pragma?mark?Getter?and?setter??
  • ??
  • -?(NSInteger)processID???
  • {??
  • ????[self?willAccessValueForKey:@"processID"];??
  • ????NSInteger?pid?=?processID;??
  • ????[self?didAccessValueForKey:@"processID"];??
  • ????return?pid;??
  • }??
  • ??
  • -?(void)setProcessID:(NSInteger)newProcessID??
  • {??
  • ????[self?willChangeValueForKey:@"processID"];??
  • ????processID?=?newProcessID;??
  • ????[self?didChangeValueForKey:@"processID"];??
  • }??
  • ??
  • //?Implement?a?setNilValueForKey:?method.?If?the?key?is?“processID”?then?set?processID?to?0.??
  • //??
  • -?(void)setNilValueForKey:(NSString?*)key?{??
  • ??????
  • ????if?([key?isEqualToString:@"processID"])?{??
  • ????????self.processID?=?0;??
  • ????}??
  • ????else?{??
  • ????????[super?setNilValueForKey:key];??
  • ????}??
  • }??
  • ??
  • @end??

  • 注意:
    1)這個(gè)類中的 date 和?primitiveDate 的訪問屬性為?@dynamic,這表明在運(yùn)行期會(huì)動(dòng)態(tài)生成對(duì)應(yīng)的 setter 和 getter;
    2)在這里我們演示了如何正確地手動(dòng)實(shí)現(xiàn) processID 的 setter 和 getter:為了讓 ManagedObjecContext ?能夠檢測(cè) processID的變化,以及自動(dòng)支持 undo/redo,我們需要在訪問和更改數(shù)據(jù)對(duì)象時(shí)告之系統(tǒng),will/didAccessValueForKey 以及?will/didChangeValueForKey 就是起這個(gè)作用的。
    3)當(dāng)我們?cè)O(shè)置 nil 給數(shù)據(jù)對(duì)象 processID?時(shí),我們可以在 setNilValueForKey?捕獲這個(gè)情況,并將 processID ?置 0;
    4)當(dāng)數(shù)據(jù)對(duì)象被插入到 ManagedObjectContext 時(shí),我們?cè)?awakeFromInsert?將時(shí)間設(shè)置為當(dāng)前時(shí)間。

    三,創(chuàng)建或讀取數(shù)據(jù)對(duì)象,設(shè)置其值,保存
    好,至此真正的萬事具備,我們可以創(chuàng)建或從持久化文件中讀取數(shù)據(jù)對(duì)象,設(shè)置其值,并將其保存到持久化文件中。本例中持久化文件為 xml 文件。修改 main() 中代碼如下:

    [cpp]?view plaincopyprint?
  • int?main?(int?argc,?const?char?*?argv[])??
  • {??
  • ????NSLog(@"?===?Core?Data?Tutorial?===");??
  • ??
  • ????//?Enable?GC??
  • ????//??
  • ????objc_startCollectorThread();??
  • ??
  • ????NSError?*error?=?nil;??
  • ??????
  • ????NSManagedObjectModel?*moModel?=?managedObjectModel();??
  • ????NSLog(@"The?managed?object?model?is?defined?as?follows:\n%@",?moModel);??
  • ??????
  • ????if?(applicationLogDirectory()?==?nil)?{??
  • ????????exit(1);??
  • ????}??
  • ??????
  • ????NSManagedObjectContext?*moContext?=?managedObjectContext();??
  • ??????
  • ????//?Create?an?Instance?of?the?Run?Entity??
  • ????//??
  • ????NSEntityDescription?*runEntity?=?[[moModel?entitiesByName]?objectForKey:@"Run"];??
  • ????Run?*run?=?[[Run?alloc]?initWithEntity:runEntity?insertIntoManagedObjectContext:moContext];??
  • ????NSProcessInfo?*processInfo?=?[NSProcessInfo?processInfo];??
  • ????run.processID?=?[processInfo?processIdentifier];??
  • ??????
  • ????if?(![moContext?save:?&error])?{??
  • ????????NSLog(@"Error?while?saving\n%@",?([error?localizedDescription]?!=?nil)???[error?localizedDescription]?:?@"Unknown?Error");??
  • ????????exit(1);??
  • ????}??
  • ??????
  • ????//?Fetching?Run?Objects??
  • ????//??
  • ????NSFetchRequest?*request?=?[[NSFetchRequest?alloc]?init];??
  • ????[request?setEntity:runEntity];??
  • ??
  • ????NSSortDescriptor?*sortDescriptor?=?[[NSSortDescriptor?alloc]?initWithKey:@"date"?ascending:YES];??
  • ????[request?setSortDescriptors:[NSArray?arrayWithObject:sortDescriptor]];??
  • ??????
  • ????error?=?nil;??
  • ????NSArray?*array?=?[moContext?executeFetchRequest:request?error:&error];??
  • ????if?((error?!=?nil)?||?(array?==?nil))??
  • ????{??
  • ????????NSLog(@"Error?while?fetching\n%@",?([error?localizedDescription]?!=?nil)???[error?localizedDescription]?:?@"Unknown?Error");??
  • ????????exit(1);??
  • ????}??
  • ??????
  • ????//?Display?the?Results??
  • ????//??
  • ????NSDateFormatter?*formatter?=?[[NSDateFormatter?alloc]?init];??
  • ????[formatter?setDateStyle:NSDateFormatterMediumStyle];??
  • ????[formatter?setTimeStyle:NSDateFormatterMediumStyle];??
  • ??????
  • ????NSLog(@"%@?run?history:",?[processInfo?processName]);??
  • ??????
  • ????for?(run?in?array)??
  • ????{??
  • ????????NSLog(@"On?%@?as?process?ID?%ld",?[formatter?stringForObjectValue:run.date],?run.processID);??
  • ????}??
  • ??????
  • ????return?0;??
  • }??

  • 在上面的代碼中:
    1)我們先獲得全局的?NSManagedObjectModel 和?NSManagedObjectContext 對(duì)象:moModel 和?moContext;
    2)并創(chuàng)建一個(gè)Run Entity,設(shè)置其 Property?processID 為當(dāng)前進(jìn)程的 ID;
    3)將該數(shù)據(jù)對(duì)象保存到持久化文件中:[moContext? save : &error]。我們無需與?PersistentStoreCoordinator 打交道,只需要給 ManagedObjectContext 發(fā)送 save 消息即可,NSManagedObjectContext 會(huì)透明地在后面處理對(duì)持久化數(shù)據(jù)文件的讀寫;
    4)然后我們創(chuàng)建一個(gè)?FetchRequest 來查詢持久化數(shù)據(jù)文件中保存的數(shù)據(jù)記錄,并將結(jié)果按照日期升序排列。查詢操作也是由 ManagedObjectContext?來處理的:[moContext? executeFetchRequest :request? error :&error];
    5)將查詢結(jié)果打印輸出;

    大功告成!編譯運(yùn)行,我們可以得到如下顯示:

    [cpp]?view plaincopyprint?
  • 2011-09-03?21:42:47.556?CoreDataTutorial[992:903]?CoreDataTutorial?run?history:??
  • 2011-09-03?21:42:47.557?CoreDataTutorial[992:903]?On?2011-9-3?下午09:41:56?as?process?ID?940??
  • 2011-09-03?21:42:47.557?CoreDataTutorial[992:903]?On?2011-9-3?下午09:42:16?as?process?ID?955??
  • 2011-09-03?21:42:47.558?CoreDataTutorial[992:903]?On?2011-9-3?下午09:42:20?as?process?ID?965??
  • 2011-09-03?21:42:47.558?CoreDataTutorial[992:903]?On?2011-9-3?下午09:42:24?as?process?ID?978??
  • 2011-09-03?21:42:47.559?CoreDataTutorial[992:903]?On?2011-9-3?下午09:42:47?as?process?ID?992??

  • 通過這個(gè)例子,我們可以更好理解 Core Data ?的運(yùn)作機(jī)制。在?Core Data 中我們最常用的就是?ManagedObjectContext,它幾乎參與對(duì)數(shù)據(jù)對(duì)象的所有操作,包括對(duì) undo/redo 的支持;而 Entity 對(duì)應(yīng)的運(yùn)行時(shí)類為?ManagedObject,我們可以理解為抽象數(shù)據(jù)結(jié)構(gòu)?Entity?在內(nèi)存中由 ManagedObject 來體現(xiàn),而 Perproty 數(shù)據(jù)類型在內(nèi)存中則由?ManagedObject 類的成員屬性來體現(xiàn)。一般我們不需要與?PersistentStoreCoordinator 打交道,對(duì)數(shù)據(jù)文件的讀寫操作都由?ManagedObjectContext 為我們代勞了。


    總結(jié)

    以上是生活随笔為你收集整理的[Cocoa]深入浅出 Cocoa 之 Core Data(2)- 手动编写代码的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。