I want to store NoteObjects
in Core Data. Normally, a NoteObject
has a NSString *mainText
and an NSMutableArray *arrayOfTags
(an array of NSStrings
). I want to now use Core Data, but arrays are a tricky matter with core data. Typically a NoteObject
won't have more than 50 tags in its array. So how should I model this? I have two options:
我想将NoteObjects存储在Core Data中。通常,NoteObject有一个NSString * mainText和一个NSMutableArray * arrayOfTags(一个NSStrings数组)。我现在想要使用核心数据,但是核心数据是一个棘手的问题。通常,NoteObject的数组中不会有超过50个标记。那么我应该如何建模呢?我有两个选择:
- Use a
transformable
property to store the array - Use a to-many relationship, which I've read is the more "legit" way to do it.
使用可转换属性来存储数组
使用to-many关系,我读过这种关系是更“合法”的方式。
Which one should I use and why? And how would I implement a to-many relationship with my simple structure? I can't seem to wrap my fingers around that concept.
我应该使用哪一个?为什么?我将如何与我的简单结构实现多对多关系?我似乎无法用手指围绕这个概念。
3 个解决方案
#1
4
Use to-many relationship. Because it's way better and easier during fetch requests. See the screenshots below. Pay attention to the Relationship manager on the right side, set "To-Many Relationship" from your NoteObject to Tags. Ignore the Player entity.
使用to-many关系。因为在获取请求期间它更好更容易。请参阅下面的屏幕截图。注意右侧的关系管理器,从NoteObject到Tags设置“To-Many Relationship”。忽略玩家实体。
Oh and pay attention to the "Delete Rule". You might want to delete all the tags associated with a given NoteObject. So set it to Cascade in that case.
哦,注意“删除规则”。您可能希望删除与给定NoteObject关联的所有标记。因此,在这种情况下将其设置为Cascade。
NoteObject entity
Tag entity
--Edit:
To add multiple tags you need to first fetch your NoteObject - I assume there will be some sort of ID parameter which you'll use to distinguish NoteObjects. CoreData will automatically generate the add/remove methods for Tags. You'll need to use code similar to the one below:
要添加多个标记,您需要先获取NoteObject - 我假设会有某种ID参数用于区分NoteObject。 CoreData将自动为Tags生成添加/删除方法。您需要使用类似于下面的代码:
- (void)addTags:(NSArray *)tags toNoteObjectWithID:(NSString *)noteID {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"NoteObject"];
NSPredicate *pred = [NSPredicate predicateWithFormat:@"noteID == %@", noteID];
[fetchRequest setPredicate:pred];
NoteObject *noteObject = [[[self managedObjectContext] executeFetchRequest:fetchRequest error:nil] lastObject];
for (NSString *tag in tags) {
Tag *t = [NSEntityDescription insertNewObjectForEntityForName:@"Tag"
inManagedObjectContext:[self managedObjectContext]];
t.body = tag;
t.noteObject = noteObject;
[noteObject addTagsObject:t];
}
[self saveContext];
}
#2
1
You could use a transformable property, but then you need to write the transformer.
您可以使用可转换属性,但是您需要编写转换器。
If you use a toMany relationship, you have to create an additional entity for tags, which presumably has only one attribute - the string value, and a single relationship. Extrapolating a little, I would guess that you have a finite set of values tags can take on, and you might someday want all notes that have tag X - then you would be able to fetch the entity containing the string value for X and then use that to fetch the NSArray of objects that have X in the relationship (whatever you called it).
如果使用toMany关系,则必须为标记创建一个附加实体,该实体可能只有一个属性 - 字符串值和单个关系。稍微推断一下,我猜你有一组有限的值标签可以承担,你可能有一天想要所有带有标签X的注释 - 然后你就可以获取包含X的字符串值的实体然后使用那就是获取关系中具有X的对象的NSArray(无论你怎么称呼它)。
#3
1
Arrays were only tricky in Core Data because they weren't supported prior to iOS 5, so you had to include some attribute (like creation date) by which they could be sorted. If you don't mind requiring iOS 5, you can use ordered relationships. Results are returned in an NSOrderedSet, which is a lot like (and can can be converted to) an array. Or, just re-think the problem -- is the order of the tags on a note important to the note or the user? Would it be okay if you just display the tags in alphabetical order? If so, even better -- just use a plain old (unordered) to-many relationship.
数组只在Core Data中很棘手,因为它们在iOS 5之前不受支持,因此您必须包含一些属性(如创建日期),以便对它们进行排序。如果您不介意要求iOS 5,则可以使用有序关系。结果在NSOrderedSet中返回,它与数组非常相似(并且可以转换为数组)。或者,只是重新思考问题 - 是对笔记或用户重要的笔记上的标签顺序?如果你只是按字母顺序显示标签会没关系吗?如果是这样,那就更好了 - 只需使用普通的(无序的)多对多关系。
#1
4
Use to-many relationship. Because it's way better and easier during fetch requests. See the screenshots below. Pay attention to the Relationship manager on the right side, set "To-Many Relationship" from your NoteObject to Tags. Ignore the Player entity.
使用to-many关系。因为在获取请求期间它更好更容易。请参阅下面的屏幕截图。注意右侧的关系管理器,从NoteObject到Tags设置“To-Many Relationship”。忽略玩家实体。
Oh and pay attention to the "Delete Rule". You might want to delete all the tags associated with a given NoteObject. So set it to Cascade in that case.
哦,注意“删除规则”。您可能希望删除与给定NoteObject关联的所有标记。因此,在这种情况下将其设置为Cascade。
NoteObject entity
Tag entity
--Edit:
To add multiple tags you need to first fetch your NoteObject - I assume there will be some sort of ID parameter which you'll use to distinguish NoteObjects. CoreData will automatically generate the add/remove methods for Tags. You'll need to use code similar to the one below:
要添加多个标记,您需要先获取NoteObject - 我假设会有某种ID参数用于区分NoteObject。 CoreData将自动为Tags生成添加/删除方法。您需要使用类似于下面的代码:
- (void)addTags:(NSArray *)tags toNoteObjectWithID:(NSString *)noteID {
NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"NoteObject"];
NSPredicate *pred = [NSPredicate predicateWithFormat:@"noteID == %@", noteID];
[fetchRequest setPredicate:pred];
NoteObject *noteObject = [[[self managedObjectContext] executeFetchRequest:fetchRequest error:nil] lastObject];
for (NSString *tag in tags) {
Tag *t = [NSEntityDescription insertNewObjectForEntityForName:@"Tag"
inManagedObjectContext:[self managedObjectContext]];
t.body = tag;
t.noteObject = noteObject;
[noteObject addTagsObject:t];
}
[self saveContext];
}
#2
1
You could use a transformable property, but then you need to write the transformer.
您可以使用可转换属性,但是您需要编写转换器。
If you use a toMany relationship, you have to create an additional entity for tags, which presumably has only one attribute - the string value, and a single relationship. Extrapolating a little, I would guess that you have a finite set of values tags can take on, and you might someday want all notes that have tag X - then you would be able to fetch the entity containing the string value for X and then use that to fetch the NSArray of objects that have X in the relationship (whatever you called it).
如果使用toMany关系,则必须为标记创建一个附加实体,该实体可能只有一个属性 - 字符串值和单个关系。稍微推断一下,我猜你有一组有限的值标签可以承担,你可能有一天想要所有带有标签X的注释 - 然后你就可以获取包含X的字符串值的实体然后使用那就是获取关系中具有X的对象的NSArray(无论你怎么称呼它)。
#3
1
Arrays were only tricky in Core Data because they weren't supported prior to iOS 5, so you had to include some attribute (like creation date) by which they could be sorted. If you don't mind requiring iOS 5, you can use ordered relationships. Results are returned in an NSOrderedSet, which is a lot like (and can can be converted to) an array. Or, just re-think the problem -- is the order of the tags on a note important to the note or the user? Would it be okay if you just display the tags in alphabetical order? If so, even better -- just use a plain old (unordered) to-many relationship.
数组只在Core Data中很棘手,因为它们在iOS 5之前不受支持,因此您必须包含一些属性(如创建日期),以便对它们进行排序。如果您不介意要求iOS 5,则可以使用有序关系。结果在NSOrderedSet中返回,它与数组非常相似(并且可以转换为数组)。或者,只是重新思考问题 - 是对笔记或用户重要的笔记上的标签顺序?如果你只是按字母顺序显示标签会没关系吗?如果是这样,那就更好了 - 只需使用普通的(无序的)多对多关系。