Archive for the ‘Cocoa开发’ Category.
2010年06月18日, 10:38 下午
XML用处很大… 用得很广… 最简单的来说用PHP和Javascript, JQuery都可以简单解析一个整齐的树结构XML文件
但是我们可爱的佛典网XML为复杂结构, 于是乎xslt帮不上什么忙了……我希望在新版的佛典中能包含所有的佛经, 于是简单并且高效的使用所有中华佛典网上的XML就是我的目标了.
于是,基于事件的XML解析器(Event-Driven XML Parser) NSXMLParser 就是我必须用到的了
继续前面的两篇Mac平台程序设计
Mac:打开一个目录
Mac:得到一个目录内的内容
1, 更改界面, 添加一个”解析一个目录里面的第一个的文件”的按钮

2, 构建XML解析部分
-(void)parseXMLFile:(NSURL *)XMLURL //XMLURL为第一个文件的URL
{
NSXMLParser *eventParser = [[NSXMLParser alloc] initWithContentsOfURL:XMLURL];
[eventParser setDelegate:self]; //设置代理为本地
[eventParser parse]; //开始解析
NSLog(@"end Of parseXMLFile");
}
//2, 解析开始后,所有XML的内容由NSXMLParserDelegate处理
// 所以一定要注意在本地添加<NSXMLParserDelegate>到文件头
//在NSXMLParser读到<p>的时候重写一个<p>标签,原来的是XML中的,无法直接使用
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict
{
if ([elementName isEqualToString:@"p"]) {
[htmlDataString appendFormat:@"<p>"];
needOrNot = YES; //我们需要<p>和</p>中间的内容,其余的在end中设置NO
return;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
if(needOrNot)
{
[htmlDataString appendString:string]; //如上,将需要的字段添加到得到的html结构String中
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
if ([elementName isEqualToString:@"p"]) {
[htmlDataString appendFormat:@"</p>"];
needOrNot = NO; //不需要的内容不允许上面的delegate去读取到htmlDataString中
return;
}
}
- (void)parserDidEndDocument:(NSXMLParser *)parser
{
NSLog(htmlDataString); //在结束后输出得到的html数据结构.
}
这样我就可以对佛典网的复杂结构xml开始分析了, 之后会放出更多对该xml处理的细节
2010年06月17日, 10:49 下午
首先是打开一个目录
然后
1, 使用NSFileManager来得到这个目录的内容
NSArray *contentArray = [[NSFileManager defaultManager]
contentsOfDirectoryAtURL:[[oPanel URLs] objectAtIndex:0]
//oPanel是上个帖子中的NSOpenPanel对象
includingPropertiesForKeys:[NSArray array]
options:0
error:nil];
2, 简单显示这个Array中的内容
for(id innerUrl in contentArray)
{
NSLog([innerUrl absoluteString]);
}
3, 结果
run
[Switching to process 3626]
Running…
2010-06-17 23:32:43.409 XML2HTML[3626:a0f] file://localhost/Users/kingmtn/Downloads/T01/T01n0001.xml
2010-06-17 23:32:43.411 XML2HTML[3626:a0f] file://localhost/Users/kingmtn/Downloads/T01/T01n0002.xml
2010-06-17 23:32:43.411 XML2HTML[3626:a0f] file://localhost/Users/kingmtn/Downloads/T01/T01n0003.xml
2010-06-17 23:32:43.411 XML2HTML[3626:a0f] file://localhost/Users/kingmtn/Downloads/T01/T01n0004.xml
2010-06-17 23:32:43.411 XML2HTML[3626:a0f] file://localhost/Users/kingmtn/Downloads/T01/T01n0005.xml
2010-06-17 23:32:43.411 XML2HTML[3626:a0f] file://localhost/Users/kingmtn/Downloads/T01/T01n0006.xml
2010-06-17 23:32:43.412 XML2HTML[3626:a0f] file://localhost/Users/kingmtn/Downloads/T01/T01n0007.xml
*在简单输出含有空格的URL的String的时候会出现一定乱码, 如果有需要, 我会去分析为什么
2010年06月17日, 10:02 下午
1, 获得一个打开窗口对象 NSOpenPanel
NSOpenPanel *oPanel = [NSOpenPanel openPanel]; //快捷建立方式不用释放, 我还记得, 你呢?
2, 设置这个对象的参数
[oPanel setCanChooseDirectories:YES]; //可以打开目录
[oPanel setCanChooseFiles:NO]; //不能打开文件(我需要处理一个目录内的所有文件)
[oPanel setDirectory:NSHomeDirectory()]; //起始目录为Home
3, 处理得到的数据
if ([oPanel runModal] == NSOKButton) { //如果用户点OK
NSLog([[[oPanel URLs] objectAtIndex:0] absoluteString]);
//我在console输出这个目录的地址
}
4, 结果
[Switching to process 3330]
Running…
2010-06-17 22:49:02.583 XML2HTML[3330:a0f] file://localhost/Users/kingmtn/Music/
5, 简单的界面

只需要一个NSButton,并且将这个NSButton的缺省行为链接到我的对象方法-(IBAction)openDirectoryButtonClick:(id)sender上就可以了
*这是我XML2HTML工程的第一部分
2010年01月4日, 10:58 下午
上传过App Store的人还记得自己需要制作的各种尺寸的图标么?
制作Mac/iPhone的图标的工作就不用Firework/Photoshop了吧…
对!Apple的Developer文件夹不是白给的!(冷静…)
请大家找到Icon Composer,下面是路径~~

打开这个程序,不是很帅的程序,五个方块…

大家可以看到Mac程序中需要的各种尺寸的图标咯,怎么用呢?很简单拉~
拽一个图片进去就自动变成那个尺寸了,顺便说一下:试试png,别用jpg…

我知道这个长方的图标很2,我手头就是这个墙纸了…方格间可以随便拽~~

看到自己喜欢的尺寸了么?文件->保存成icon文件就可以咯!哇啦~~
2009年09月6日, 6:14 下午
我不知道为什么,不过有人搜索makeKeyAndVisible方法。其实我这种懒人一般不会刨根问底,有些方法照打就好,那些白给的方法有些就别动就好了。
我们看看这个每个程序都有的方法吧:
[window makeKeyAndVisible];
由于iPhone是单窗口程序,所以也就只有这么一个Window对象,而且是UIWindow,不是NSWindow。而根据文档上所说:
“这个是便捷方法,去使被使用对象的主窗口显示到屏幕的最前端。你也可以使用hiddenUIView方法隐藏这个窗口”
所以基本上来说,对于编程者的区别仅仅在于在其前添加代码,或在其后添加代码。
2009年09月6日, 12:57 上午
老话,最近闹心的事情多,开心的事情少,但是正事还是要干的。学习得需要,努力的需要,钱的需要… … 天上给我下点儿钞票吧!
言归正传,怎么在iPhone程序中读取PDF的内容呢?答案是,苹果为我们准备了一个很神奇的framework Q2D(Quartz 2D)。Q2D提供了全套的PDF读取API,接下来我们来看看如果简单的使用Q2D来读取PDF文件:
我建立了一个工程叫iPhonePDF, 添加了一个UIScrollView(不知道怎么添加UIScrollView? 添加一个UIView然后把interface上的UIView改成UIScrollView就可以啦…)名为PDFView
看看PDFView里面有什么吧
@interface PDFView : UIScrollView {
NSString *filePath;
CGPDFDocumentRef pdfDocument;
CGPDFPageRef page;
int pageNumber;
}
@property (copy, nonatomic) NSString *filePath;
@property int pageNumber;
-(CGPDFDocumentRef)MyGetPDFDocumentRef;
-(void)reloadView;
-(IBAction)goUpPage:(id)sender;
-(IBAction)goDownPage:(id)sender;
@end
filePath是储存pdf文件的位置的,得到文件位置就是老话题了:[NSBundle mainBundle]… 后面的会写吧… 不记得了在我博客里面搜索吧
CGPDFDocumentRef是PDF文档索引文件,Q2D是Core Foundation的API,所以没看到那个星星~
CGPDFPageRef是PDF页面索引文件
pageNumber是页码
下面的几个函数其实一看就明了了,翻页的,和刷新页面的。第一个是自定义的getter
然后我们看看m文件里面有用的方法:
@implementation PDFView
@synthesize filePath,pageNumber;
- (void)drawRect:(CGRect)rect //只要是UIView都有的绘图函数,基础哟~
{
if(filePath == nil) //如果没被初始化的话,就初始化
{
pageNumber = 10; //这个其实应该由外部函数控制,不过谁让这个程序特别简单呢
filePath = [[NSBundle mainBundle] pathForResource:@"zhaomu" ofType:@"pdf"];
//这里,文件在这里!
pdfDocument = [self MyGetPDFDocumentRef]; //从自定义getter得到文件索引
}
CGContextRef myContext = UIGraphicsGetCurrentContext();
//这个我研究了一段时间呢,不过就照打就可以了
page = CGPDFDocumentGetPage(pdfDocument, pageNumber);
//便捷函数,告诉人家文档,告诉人家页码,就给你页面索引
CGContextDrawPDFPage(myContext, page);
//画!
}
//此getter可以考虑照打... 都是CF函数,我看到就恶心。
//其实不是很难了,得到文件,转换成URL,然后通过
//CGPDFDocumentCreateWithURL(url)得到文件内容索引
//Ta Daaa~~
- (CGPDFDocumentRef)MyGetPDFDocumentRef
{
CFStringRef path;
CFURLRef url;
CGPDFDocumentRef document;
path = CFStringCreateWithCString(NULL, [filePath UTF8String], kCFStringEncodingUTF8);
url = CFURLCreateWithFileSystemPath(NULL, path, kCFURLPOSIXPathStyle, 0);
CFRelease(path);
document = CGPDFDocumentCreateWithURL(url);
CFRelease(url);
return document;
}
-(void)reloadView
{
[self setNeedsDisplay]; //每次需要重画视图了,就call这个
}
-(IBAction)goUpPage:(id)sender
{
pageNumber++;
[self reloadView];
}
-(IBAction)goDownPage:(id)sender
{
pageNumber--;
[self reloadView];
}
@end
我这个是个少半成品的程序呢… 我当时弄了几个PDF测试程序,但是找不到了。不过意思是一样的,剩下的东西由大家来发挥吧,有问题记得留言噢!我有问必答!
2009年09月3日, 8:08 下午
循环使用整个NSArray内的对象是非常常用的了,而且最近我在研究究竟怎么能方便的把NSArray存入Core Data,所以这更是必要了,看看如下的方法吧:
1,Objective-C 2.0法,最应该使用的
NSArray *aArray; //我们的Array,假设他已经初始化有内容了
for(id innerObj in aArray) //id可以由其他对象类型替代
{
//也就是说, 在循环中的参数innerObj就是aArray中的对象
//由于NSArray中只能储存对象,所以我们使用id作为内涵对象的类型,其实就是个指针了
//而且如果NSArray中的内容不一致,id更不会出现冲突
}
2,C的老方法,不推荐,低性能
NSArray *aArray; //我们的Array,假设他已经初始化有内容了
for(int i=0;i<[aArray count]; i++)
{
[[aArray objectAtIndex:i] 然后作你想作的事情]; //做爱 作的事情...
}
3, 用NSEnumerator(不知道怎么翻译阿….)
NSEnumerator* myIterator = [myArray reverseObjectEnumerator];
id anObject;
while( anObject = [myIterator nextObject]) //每次读取“逐读器”的下一个对象
{
//anObject和刚才的innerObj是一个意思,但是看看多了这么多行
}
结语:
就用第一种方法吧….
2009年09月3日, 7:12 下午
1,operationQueue 里边应该可以同时添加多个operation吧?
是的,本来operationQueue的目的就是多线程管理,那多线程,可不只是一个线程。
而且我们可以设置这个队列每次被处理的“操作”数量
NSOperationQueue *aQ = [[NSOperationQueue alloc] init];
[aQ setMaxConcurrentOperationCount:10];
这里的setMaxConcurrentOperationCount就是同时被处理的“操作数”,参数为整数int或NSInteger (两个是一样的,不记得的可以在我的博客里面搜索一下噢~)
2,那main函数应该怎么写?
main函数中其实只需要写你要在另外一个进程里面作的事情。比如对于我来说,我常常只是作一个简单的事情,那我会用NSInvocationOperation,NSOperation的简化版。比如说:
NSInvocationOperation *aOpt = [[NSInvocationOperation alloc]
initWithTarget:self selector:@selector(doSomeThing) object:nil];
- (void)doSomeThing
{
//读取大量大延迟数据等等
//可以使用performSelectorOnMainThread来将得来的数据返回到主线程
}
在doSomeThing函数里面,我可以从网上读取一些东西,但是读取是需要占用时间,而堵塞主线程的。而使用NSOperation这样使用就不会了。
而如果是NSOperation,虽然复杂了一些,又是做一个NSOperation的子类。其实main函数做得事情和doSomeThing是一抹一样的。只不过如果你制作这个子类,你对其操作的内容可以更多,可以制作更复杂的读取,载入操作等等,而且你可以重复使用这个类功能阿。再者,NSOperation也提供了对runtime操作的支持,不过那就太麻烦了,一般不大用的上。
最近麻烦事情真是太多了,而且还都不顺利,死的心都有阿。还好有这么多好朋友支持我,我这个博客也一点儿一点儿的有回复了…大家别那么冷漠,管我写的好还是不好,按东北话来说“吱一声”嘛~唉,我要加油阿!我还有那么多的事情没办到呢,怎么能放弃!他妈的!!!!!阿!!!!!!
2009年09月1日, 2:02 下午
大家都有Snow Leopard和XCode 3.2了吧?会发现XCode变了不少,帅拉!

那我们点击“Create a new Xcode project”来开始我们的Core Data程序工程吧!

在这里,XCode已经给我们准备好了一个几乎可以直接去用的程序模板,直接选择“基于导航的应用程序”,然后记得点选“Use Core Data for storage”

建立好的程序名为XCDtest01,我们尝试编译运行,看看得到的程序是什么样的:

基本上来说,这个程序把什么都给我们弄好了,一个程序,在点击添加按钮之后添加现在的时间标签,如果点击“Edit”编辑按钮,就进入编辑模式,可以删除任意条信息。
如果点开xcdatamodel文件,我们可以看到,其中的实体为Event,有一个参数,名为“时间标签”。也就是说,如果我们想对这个列表视图中的数据作更改,只需要适当更改这个实体的参数,并配置- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 代理条目就可以显示适当的内容了。

这个预置程序与我们之前讨论的程序不同的,在于这个程序中并没有配置一个可变数组(NSMutableArray)来作数据副本,以达到高速存储的目的。因为Core Data在向磁盘和内存操作,NSMutableArray是内存操作,速度上比较有优势。但是我们有的这个小程序太小了,再者苹果有可能认为那种方法是非标准的。所以在这里才没有那么作
NSManagedObject *managedObject = [fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [[managedObject valueForKey:@"timeStamp"] description];
在这个程序的cell配置代理里面,仅仅是从“获取操作控制器”中得到了“被管理对象”,然后再读取其中的内容到cell的text中。
希望大家也使用这个模板,自己创建一个Core Data程序,然后简单的理解一下代码。下次我们聊只使用基于Window的程序模板+Core Data来创建程序
2009年08月27日, 11:59 下午
在我们分析了程序主代理文件(AppDelegate)之后,我们先来看看一对自动生成的文件Event.h/.m
@interface Event : NSManagedObject {}
@property (nonatomic, retain) NSDate *creationDate;
@property (nonatomic, retain) NSNumber *latitude;
@property (nonatomic, retain) NSNumber *longitude;
@end
#import "Event.h"
@implementation Event
@dynamic creationDate;
@dynamic latitude;
@dynamic longitude;
@end
从上面我们能看出来,一个实体Event也就会被生成一个NSManagedObject(被管理对象),然后任何accessor和getter都是被动态生成的,我们其实完全不用操任何的心,只需要在xcdatamodel文件里面配置后,点击添加文件,添加NSManagedObject文件,就会看到自动感知的类对象,然后生成就可以了。
下面是根视图控制器,是一个列表视图(UITableViewController)
#import <CoreLocation/CoreLocation.h>
@interface RootViewController : UITableViewController <CLLocationManagerDelegate> {
//看到是UITableViewController的子类,由于需要使用Core Location,
//所以在后面履行其protocal
NSMutableArray *eventsArray;
NSManagedObjectContext *managedObjectContext;
//这个被管理对象内容器就是我们真正对Core Data数据的操作对象
CLLocationManager *locationManager; //用来得到地理位置的Core Location对象
UIBarButtonItem *addButton; //右上角的添加键
}
@property (nonatomic, retain) NSMutableArray *eventsArray;
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain) CLLocationManager *locationManager;
@property (nonatomic, retain) UIBarButtonItem *addButton;
- (void)addEvent;
@end
#import "RootViewController.h"
#import "LocationsAppDelegate.h"
#import "Event.h"
@implementation RootViewController
@synthesize eventsArray, managedObjectContext, addButton, locationManager;
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"Locations"; //设置列表视图的标题
self.navigationItem.leftBarButtonItem = self.editButtonItem; //导航栏左边的编辑按钮
addButton = [[UIBarButtonItem alloc]
initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
target:self
action:@selector(addEvent)]; //初始化添加按钮,
addButton.enabled = NO; //在Core Location初始化之前将其关闭
self.navigationItem.rightBarButtonItem = addButton;
//把这个添加按钮添加到导航栏右侧
// 启动CLocation
[[self locationManager] startUpdatingLocation];
//初始化一个“获取请求”到我们的实体“Event”
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event"
inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// 将时间以建立时间排序,最新的在最上
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"creationDate" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
[sortDescriptors release];
// 执行“获取”操作,得到一个“可变数组”的拷贝
NSError *error = nil;
NSMutableArray *mutableFetchResults = [[managedObjectContext
executeFetchRequest:request
error:&error] mutableCopy];
if (mutableFetchResults == nil) {
//如果结果为空,在这作错误响应
}
// 将得到的本地数组赋值到本类的全局数组,然后清理无用的对象
[self setEventsArray:mutableFetchResults];
[mutableFetchResults release];
[request release];
}
- (void)viewDidUnload {
// 当视图被卸载后,将以下指针置空
self.eventsArray = nil;
self.locationManager = nil;
self.addButton = nil;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
// 只有一个章节
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// 在数组里面有多少个对象,在列表视图就有多少行
return [eventsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
// 一个“日期格式化器”(凑合明白就好...)用来以特定的格式创建得到的日期
static NSDateFormatter *dateFormatter = nil;
if (dateFormatter == nil) {
dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
}
static NSNumberFormatter *numberFormatter = nil;
if (numberFormatter == nil) {
numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setMaximumFractionDigits:3];
}
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle
reuseIdentifier:CellIdentifier] autorelease];
UITableViewCellStyleSubtitle;
}
// 从数组中得到这个Event对象
Event *event = (Event *)[eventsArray objectAtIndex:indexPath.row];
cell.textLabel.text = [dateFormatter stringFromDate:[event creationDate]];
NSString *string = [NSString stringWithFormat:@"%@, %@",
[numberFormatter stringFromNumber:[event latitude]],
[numberFormatter stringFromNumber:[event longitude]]];
cell.detailTextLabel.text = string;
return cell;
}
- (void)tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete) {
// 删除被惯例对象在索引路径(index path)
NSManagedObject *eventToDelete = [eventsArray objectAtIndex:indexPath.row];
[managedObjectContext deleteObject:eventToDelete];
// 更新数组和列表视图
[eventsArray removeObjectAtIndex:indexPath.row];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:YES];
// 提交更改到Core Data
NSError *error;
if (![managedObjectContext save:&error]) {
// Handle the error.
}
}
}
- (void)addEvent {
//如果得不到位置,就返回.
CLLocation *location = [locationManager location];
if (!location) {
return; }
//建立一个Event实体对象
Event *event = (Event *)[NSEntityDescription
insertNewObjectForEntityForName:@"Event"
inManagedObjectContext:managedObjectContext];
//得到经纬度,然后赋值到event对象去
CLLocationCoordinate2D coordinate = [location coordinate];
[event setLatitude:[NSNumber numberWithDouble:coordinate.latitude]];
[event setLongitude:[NSNumber numberWithDouble:coordinate.longitude]];
// 实例里面并没有使用CL的时间标签,因为在模拟器中会是一样的
// [event setCreationDate:[location timestamp]];
[event setCreationDate:[NSDate date]];
//所以现在使用的是现在的时间,而不是得到位置的时候的时间
// 保存更改
NSError *error;
if (![managedObjectContext save:&error]) {
// Handle the error.
}
// 将新Event放到最上面,所以添加到0的位置
// 然后滚动列表视图到最上面,如果没有那么多的数据是看不出来区别的
[eventsArray insertObject:event atIndex:0];
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]
atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
- (CLLocationManager *)locationManager {
//自定义的CLocation的getter,方便初始化
if (locationManager != nil) {
return locationManager;
}
//初始化CL对象,然后设置精准度,然后将代理对象设为本地
locationManager = [[CLLocationManager alloc] init];
[locationManager setDesiredAccuracy:kCLLocationAccuracyNearestTenMeters];
[locationManager setDelegate:self];
return locationManager;
}
//CLocation的一个代理方法,如果成功就开启右侧添加按钮
- (void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation {
addButton.enabled = YES;
}
//CLocation的一个代理方法,如果失败了就关闭(disable)右侧添加按钮
- (void)locationManager:(CLLocationManager *)manager
didFailWithError:(NSError *)error {
addButton.enabled = NO;
}
- (void)dealloc {
//释放对象
[managedObjectContext release];
[eventsArray release];
[locationManager release];
[addButton release];
[super dealloc];
}
@end
从上面的源代码,我们可以看出,
1,在这里数据并不是每次都由NSManagedContext对象得到,而是由一个数组得出。
2,数组是一个可变数组,由第一次载入的视图的时候从NSManagedContext中得到
3,从NSManagedContext对象中得到数据需要使用NSFetchRequest来初始化一个“获取”
4,每次获得新的数据的时候,同时保存到数组和NSManagedContext中,添加后需要对更改进行提交