无法正确获取对象 CoreData
Cannot fetch object CoreData correctly
我正在练习使用 CoreData 存储数据和获取数据。
但是我遇到了一些让我困惑了几个小时的问题。
我存储了一组从索引 0 到 107 的对象,一共是 108 个。它完美地工作。
存储的一些数据的NSLog:
2015-03-04 16:39:29.825 Colo[32365:1884749] <NSManagedObject: 0x7f83d06a7240> (entity: Color; id: 0xd000000000300000 <x-coredata://3DC5B29F-DA7C-4D7C-9D59-738A28A957C1/Color/p12> ; data: {
colorArray = nil;
fifthColor = "#5A3431";
firstColor = "#F2EDDA";
fourthColor = "#A65F4B";
hexString = nil;
index = 106;
secondColor = "#BEAC94";
star = 12;
thirdColor = "#DA896E";
title = "wm102\n \n ";
})
2015-03-04 16:39:29.826 Colo[32365:1884749] 107
2015-03-04 16:39:29.826 Colo[32365:1884749] <NSManagedObject: 0x7f83d06a7330> (entity: Color; id: 0xd000000000980000 <x-coredata://3DC5B29F-DA7C-4D7C-9D59-738A28A957C1/Color/p38> ; data: {
colorArray = nil;
fifthColor = "#242613";
firstColor = "#100C17";
fourthColor = "#FFE8B4";
hexString = nil;
index = 107;
secondColor = "#604325";
star = 12;
thirdColor = "#D0A17D";
title = "Create Now 2014 \U4f1a\U5834\n \n ";
})
但是当我尝试获取我存储到 CoreData 的这些对象时。
- (void)fetchDataFromCoreData
{
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [delegate managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Color"
inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (!objects){
NSLog(@"There was an error.");
}
for (NSManagedObject *oneObject in objects){
NSString *title = [oneObject valueForKey:@"title"];
NSString *star = [oneObject valueForKey:@"star"];
NSString *index = [oneObject valueForKey:@"index"];
NSString *firstColor = [oneObject valueForKey:@"firstColor"];
NSString *secondColor = [oneObject valueForKey:@"secondColor"];
NSString *thirdColor = [oneObject valueForKey:@"thirdColor"];
NSString *fourthColor = [oneObject valueForKey:@"fourthColor"];
NSString *fifthColor = [oneObject valueForKey:@"fifthColor"];
int i = [index intValue];
NSIndexPath *path = [NSIndexPath indexPathForRow:i inSection:0];
ColorCell *cell = (ColorCell *)[self.tableView cellForRowAtIndexPath:path];
UIColor *first = [Parser translateStringToColor:firstColor];
UIColor *second = [Parser translateStringToColor:secondColor];
UIColor *third = [Parser translateStringToColor:thirdColor];
UIColor *fourth = [Parser translateStringToColor:fourthColor];
UIColor *fifth = [Parser translateStringToColor:fifthColor];
cell.firstColor.backgroundColor = first;
cell.secondColor.backgroundColor = second;
cell.thirdColor.backgroundColor = third;
cell.fourthColor.backgroundColor = fourth;
cell.fifthColor.backgroundColor = fifth;
}
}
不幸的是,cellForRowAtIndexPath
中的cell
以一种奇怪的方式重复使用,一些单元格是空白的,只出现一个单元格。我在
下了两个断点
int i = [index intValue];
NSIndexPath *path = [NSIndexPath indexPathForRow:i inSection:0];
而且我注意到索引是 break,82 应该是 81 的下一个。
任何想法都会受到欢迎。
这是我的第一次 CoreData 实践。请帮助我变得更好。
编辑:子类NSManagedObject
:
.h:
@interface ColorManagerObject : NSManagedObject
@property (nonatomic) UIColor *firstColor;
@property (nonatomic) UIColor *secondColor;
@property (nonatomic) UIColor *thirdColor;
@property (nonatomic) UIColor *fourthColor;
@property (nonatomic) UIColor *fifthColor;
@end
.m:
- (void)setFirstColor:(UIColor *)firstColor
{
[self setValue:firstColor forKey:@"firstColor"];
}
- (UIColor *)firstColor
{
NSString *string = [self valueForKey:@"firstColor"];
return [Parser translateStringToColor:string];
}
- 您的 fetchRequest 没有 sortDescriptors,因此对象未按特定顺序返回。
- 这不是 tableView 的工作方式。
我们先解决第一个问题,简单的添加一个NSSortDescriptor。
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
NSSortDescriptor *indexSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"index" ascending:YES];
request.sortDescriptors = @[indexSortDescriptor];
第二个问题解释起来比较复杂。 TableView 使用数据源模式。它向您的数据源询问对象,您不将对象发送到 tableView。您应该将获取的结果存储在一个 NSArray 中,并将该数组用作您的数据源。然后实现三个基本的 UITableViewDataSource 方法。
例如:
@property (strong, nonatomic) NSArray *objects;
- (void)fetchDataFromCoreData {
// ...
self.objects = [context executeFetchRequest:request error:&error];
[self.tableView reloadData]; // reload tableView so it contains all the new objects
// ...
}
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.objects count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
}
NSManagedObject *object = self.objects[indexPath.row];
cell.textLabel.text = [object valueForKey:@"title"];
return cell;
}
一旦成功,您可能想阅读有关 NSFetchedResultsController
的内容,它基本上是为由 Core Data 支持的 UITableViews 制作的。它提供了一个很好的委托,当从 CoreData 中插入或删除对象时,它将插入和删除单元格。
您可能还想查看 NSManagedObject 的子类,这样您就不必使用 [object valueForKey:@"title"]
,而是可以使用 object.title
。
我正在练习使用 CoreData 存储数据和获取数据。 但是我遇到了一些让我困惑了几个小时的问题。 我存储了一组从索引 0 到 107 的对象,一共是 108 个。它完美地工作。
存储的一些数据的NSLog:
2015-03-04 16:39:29.825 Colo[32365:1884749] <NSManagedObject: 0x7f83d06a7240> (entity: Color; id: 0xd000000000300000 <x-coredata://3DC5B29F-DA7C-4D7C-9D59-738A28A957C1/Color/p12> ; data: {
colorArray = nil;
fifthColor = "#5A3431";
firstColor = "#F2EDDA";
fourthColor = "#A65F4B";
hexString = nil;
index = 106;
secondColor = "#BEAC94";
star = 12;
thirdColor = "#DA896E";
title = "wm102\n \n ";
})
2015-03-04 16:39:29.826 Colo[32365:1884749] 107
2015-03-04 16:39:29.826 Colo[32365:1884749] <NSManagedObject: 0x7f83d06a7330> (entity: Color; id: 0xd000000000980000 <x-coredata://3DC5B29F-DA7C-4D7C-9D59-738A28A957C1/Color/p38> ; data: {
colorArray = nil;
fifthColor = "#242613";
firstColor = "#100C17";
fourthColor = "#FFE8B4";
hexString = nil;
index = 107;
secondColor = "#604325";
star = 12;
thirdColor = "#D0A17D";
title = "Create Now 2014 \U4f1a\U5834\n \n ";
})
但是当我尝试获取我存储到 CoreData 的这些对象时。
- (void)fetchDataFromCoreData
{
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
NSManagedObjectContext *context = [delegate managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"Color"
inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
NSError *error;
NSArray *objects = [context executeFetchRequest:request error:&error];
if (!objects){
NSLog(@"There was an error.");
}
for (NSManagedObject *oneObject in objects){
NSString *title = [oneObject valueForKey:@"title"];
NSString *star = [oneObject valueForKey:@"star"];
NSString *index = [oneObject valueForKey:@"index"];
NSString *firstColor = [oneObject valueForKey:@"firstColor"];
NSString *secondColor = [oneObject valueForKey:@"secondColor"];
NSString *thirdColor = [oneObject valueForKey:@"thirdColor"];
NSString *fourthColor = [oneObject valueForKey:@"fourthColor"];
NSString *fifthColor = [oneObject valueForKey:@"fifthColor"];
int i = [index intValue];
NSIndexPath *path = [NSIndexPath indexPathForRow:i inSection:0];
ColorCell *cell = (ColorCell *)[self.tableView cellForRowAtIndexPath:path];
UIColor *first = [Parser translateStringToColor:firstColor];
UIColor *second = [Parser translateStringToColor:secondColor];
UIColor *third = [Parser translateStringToColor:thirdColor];
UIColor *fourth = [Parser translateStringToColor:fourthColor];
UIColor *fifth = [Parser translateStringToColor:fifthColor];
cell.firstColor.backgroundColor = first;
cell.secondColor.backgroundColor = second;
cell.thirdColor.backgroundColor = third;
cell.fourthColor.backgroundColor = fourth;
cell.fifthColor.backgroundColor = fifth;
}
}
不幸的是,cellForRowAtIndexPath
中的cell
以一种奇怪的方式重复使用,一些单元格是空白的,只出现一个单元格。我在
int i = [index intValue];
NSIndexPath *path = [NSIndexPath indexPathForRow:i inSection:0];
而且我注意到索引是 break,82 应该是 81 的下一个。
任何想法都会受到欢迎。
这是我的第一次 CoreData 实践。请帮助我变得更好。
编辑:子类NSManagedObject
:
.h:
@interface ColorManagerObject : NSManagedObject
@property (nonatomic) UIColor *firstColor;
@property (nonatomic) UIColor *secondColor;
@property (nonatomic) UIColor *thirdColor;
@property (nonatomic) UIColor *fourthColor;
@property (nonatomic) UIColor *fifthColor;
@end
.m:
- (void)setFirstColor:(UIColor *)firstColor
{
[self setValue:firstColor forKey:@"firstColor"];
}
- (UIColor *)firstColor
{
NSString *string = [self valueForKey:@"firstColor"];
return [Parser translateStringToColor:string];
}
- 您的 fetchRequest 没有 sortDescriptors,因此对象未按特定顺序返回。
- 这不是 tableView 的工作方式。
我们先解决第一个问题,简单的添加一个NSSortDescriptor。
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:entityDescription];
NSSortDescriptor *indexSortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"index" ascending:YES];
request.sortDescriptors = @[indexSortDescriptor];
第二个问题解释起来比较复杂。 TableView 使用数据源模式。它向您的数据源询问对象,您不将对象发送到 tableView。您应该将获取的结果存储在一个 NSArray 中,并将该数组用作您的数据源。然后实现三个基本的 UITableViewDataSource 方法。
例如:
@property (strong, nonatomic) NSArray *objects;
- (void)fetchDataFromCoreData {
// ...
self.objects = [context executeFetchRequest:request error:&error];
[self.tableView reloadData]; // reload tableView so it contains all the new objects
// ...
}
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.objects count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];
}
NSManagedObject *object = self.objects[indexPath.row];
cell.textLabel.text = [object valueForKey:@"title"];
return cell;
}
一旦成功,您可能想阅读有关 NSFetchedResultsController
的内容,它基本上是为由 Core Data 支持的 UITableViews 制作的。它提供了一个很好的委托,当从 CoreData 中插入或删除对象时,它将插入和删除单元格。
您可能还想查看 NSManagedObject 的子类,这样您就不必使用 [object valueForKey:@"title"]
,而是可以使用 object.title
。