将核心数据实现到现有的iPhone项目中。

4
我在将Core Data引入我的iPhone项目时遇到了一些问题。首先我想给你一个更详细的视角:
- 我的某些类是嵌套的:类“Game”有一个包含“Player”类对象的NSArray,而“Player”类又有一个包含“Item”类对象的NSArray。 - 我想做的是保存“uppest”类“Game”的一个实例(例如当我离开我的应用程序时)。
我尝试了一些关于Core Data的教程,但仍然有一些疑问:
- 我是否需要为每个类创建一个实体,还是只需为“Game”创建一个即可? - 如果我必须为每一个类都这样做:我认为我将不得不创建所有类之间的关系,但是如何创建“Game”和“Player”之间的关系(请注意:我在一个NSArray中持有很多玩家)…… - 那么现在改变我已有的项目怎么办?我已经将缺少的方法复制到了我的AppDelegate中,但我将不得不对我的类做些什么,特别是Getter/Setter方法?只需在实现中将“@synthesize”更改为“@dynamic”吗?
希望能解决我的问题,非常感谢!
Mac1988
2个回答

2
我建议的是在Xcode中设置您的数据库模型,然后选择实体并从菜单“文件>新文件”中选择“托管对象类”。在“下一步”之后,选择要保存文件的位置,然后在下一步中,XCode会询问您应该将哪些实体生成到文件中。
完成上述步骤后,您可以将所需的功能实现到您的委托中。我建议保留现有的内容不变,并将核心数据类作为它们自己使用。只需从现有的类/数组中获取所需的数据,并根据需要将其放入数据库中。在检索时,则相反地...从DB中获取它们并将它们添加到您的函数/类中。
以下是我的一个项目示例:
.h文件
@class quicklistSet;

@interface rankedAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {
[...]

    NSMutableArray *_searchHistory;
    NSMutableArray *_quickList;
}

[...]

@property (nonatomic, retain) NSMutableArray *_searchHistory;
@property (nonatomic, retain) NSMutableArray *_quickList;

/* Quicklist functions */
- (void)addToQuicklist:(quicklistSet *)theQuicklistSet;
- (BOOL)checkIfQuicklistExists:(quicklistSet*)theQuicklistSet;
- (NSMutableArray *)getQuicklists;
- (void)deleteQuicklist:(NSNumber*)theAppId;


@end

.m文件

#import "quicklistSet.h"
#import "quicklist.h"

@implementation rankedAppDelegate

@synthesize window;
@synthesize tabBarController;
@synthesize _searchHistory, _quickList;

[...]

/* Quicklist functions */
- (void)addToQuicklist:(quicklistSet *)theQuicklistSet
{
    BOOL exists = [self checkIfQuicklistExists:theQuicklistSet];

    if(!exists)
    {
        quicklist *theQuicklist = (quicklist *)[NSEntityDescription insertNewObjectForEntityForName:@"quicklist"
                                                                                      inManagedObjectContext:self.managedObjectContext];

        [theQuicklist setAppName:[theQuicklistSet _appName]];
        [theQuicklist setAppId:[theQuicklistSet _appId]];
        [theQuicklist setAppImage:[theQuicklistSet _appImage]];
        [theQuicklist setCountryId:[theQuicklistSet _countryId]];
        [theQuicklist setCategoryId:[theQuicklistSet _categoryId]];
        [theQuicklist setLastCheck:[theQuicklistSet _lastCheck]];
        [theQuicklist setLastRank:[theQuicklistSet _lastRank]];

        [_quickList addObject:theQuicklist];

        [self saveAction];
    }
    else {
        NSLog(@"Existing quicklistSet: %@", [theQuicklistSet _appName]);
    }
}

- (BOOL)checkIfQuicklistExists:(quicklistSet*)theQuicklistSet
{
    // Get the categories
    NSMutableArray *quicklistArray = [self getQuicklists];

    BOOL exists = NO;

    for(quicklist *dbQuicklist in quicklistArray)
    {
        if([[dbQuicklist appId] isEqualToNumber:[theQuicklistSet _appId]])
        {
            exists = YES;
            continue;
        }
    }

    return exists;
}

- (NSMutableArray *)getQuicklists
{
    if(_quickList == NULL)
    {
        NSLog(@"Array is null");

        NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

        NSEntityDescription *entity = [NSEntityDescription entityForName:@"quicklist" 
                                                  inManagedObjectContext:self.managedObjectContext];
        [fetchRequest setEntity:entity];

        NSError *error;
        NSArray *items = [[self.managedObjectContext
                           executeFetchRequest:fetchRequest error:&error] retain];

        NSMutableArray *returnArray = [[[NSMutableArray alloc] initWithArray:items] retain];

        _quickList = returnArray;

        [fetchRequest release];
    }
    else {
        NSLog(@"Not null. Count: %d", [_quickList count]);
    }

    return _quickList;
}

- (void)deleteQuicklist:(NSNumber*)theAppId
{
    NSLog(@"Delete row");

    // Create a new managed object context for the new book -- set its persistent store coordinator to the same as that from the fetched results controller's context.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"quicklist" 
                                              inManagedObjectContext:self.managedObjectContext];

    [fetchRequest setEntity:entity];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"appId=%@",theAppId];
    [fetchRequest setPredicate:predicate];

    NSError *error;
    NSArray *items = [self.managedObjectContext
                      executeFetchRequest:fetchRequest error:&error];
    [fetchRequest release];

    if([items count] > 0)
    {
        NSManagedObject *eventToDelete = [items objectAtIndex:0];
        [self.managedObjectContext deleteObject:eventToDelete];

        [self saveAction];
    }
}
/* END Quciklist functions */

[...]

@end

编辑: quicklistSet是我现有的类,quicklist是我的coredata类。


嗨,保罗,感谢你的回答和示例。你的意思是创建一个由Core Data处理的新类“GameData”,并从那里提取和保存我的对象,对吗?我仍然完全不明白如何创建实体:例如一个属性“Player”和一个对现有“Player”类的一对多关系?还是我也必须创建一个新的“Player”类?或者这一切都是错的?;) - Mac1988
我理解你的意思,但我无法直接回答那个问题。我对核心数据还不够熟练。 我知道的是,从每个实体中,核心数据会创建一个带有动态值的类。您还可以将它们彼此关联,但这样做只会向实体添加另一个类。 我认为您也需要创建一个新的玩家类,但也许有更有经验的人能更好地回答您的问题。祝你好运! - Paul Peelen

1
  1. 是的,您需要为您提到的所有类创建一个实体。

  2. 您已经在问题中得到了答案:建立一对多的关系。例如,对于Game的players关系,在数据模型编辑器中点击“To-many relationship”复选框。

  3. 您将希望让您的数据类(Game、Player、Item)从NSManagedObject继承。您可能希望删除与Core Data中添加的属性相对应的所有实例变量。对于一对多关系(players、items),您肯定要摆脱使用的NSArray成员变量。相反,像您所说的那样,为players和items属性创建@dynamic访问器。请注意,您要使用NSSet而不是NSArray来处理players和items。

例如,您的Game类的头文件可能如下所示:

@interface Game : NSManagedObject {

}

@property(nonatomic, retain) NSSet *players
@property(nonatomic, retain) NSString *someOtherProperty;
@property(nonatomic, retain) NSNumber *yetAnotherProperty;

@end

然后你的实现文件可能看起来像这样:

#import "Game.h"

@implementation Game

@dynamic players, someOtherProperty, yetAnotherProperty;

- (void)awakeFromInsert {
    // do initialization here
}

// other methods go here

@end

此外,在修改玩家和物品属性时要小心。Core Data编程指南的使用托管对象部分有很多好的细节,但基本上要将玩家添加到游戏实例中,您需要执行以下操作:
[game addPlayerObject:newPlayer];

要创建新的玩家,您需要执行类似以下的操作:

NSManagedObject *newPlayer = [NSEntityDescription insertNewObjectForEntityForName:@"Player" inManagedObjectContext:context];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接