Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/39.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 如何正确保存到coredata一对多关系中_Iphone_Ios_Objective C_Core Data - Fatal编程技术网

Iphone 如何正确保存到coredata一对多关系中

Iphone 如何正确保存到coredata一对多关系中,iphone,ios,objective-c,core-data,Iphone,Ios,Objective C,Core Data,我对保存到coreData和使用iOS开发非常陌生 我正在努力实现的目标: 我希望我的数据库中有一个用户,该用户具有唯一标识符/通过idFB提取,并且该用户可以创建和检索他们的训练例程 我走了多远? 我设法(我认为)创建了一个方法,可以从与右用户关联的例程实体中正确地检索routineName。请参阅fetch方法 我的问题: 我认为我没有使用正确的实体关系关联User(usersExercise)>例程(userID)进行保存。换句话说,我认为我的save方法不正确。。。当我将整个用户保存到u

我对保存到coreData和使用iOS开发非常陌生

我正在努力实现的目标:

我希望我的数据库中有一个用户,该用户具有唯一标识符/通过
idFB
提取,并且该用户可以创建和检索他们的训练例程

我走了多远?

我设法(我认为)创建了一个方法,可以从与右
用户关联的
例程实体中正确地检索
routineName
。请参阅
fetch
方法

我的问题:

我认为我没有使用正确的实体关系关联
User(usersExercise)>例程(userID)
进行保存。换句话说,我认为我的
save
方法不正确。。。当我将整个用户保存到userID时,感觉不对吗?主要是因为当它吐出
例程.userID
时,它会提取整个相关的用户,而不是特定的ID?我真的不知道该期待什么

有人能帮我正确地建立这些方法吗?我对coreData保存和建立正确关系的整个过程感到非常困惑

- (void) save {
    Routine *newRoutine = [NSEntityDescription insertNewObjectForEntityForName:@"Routine" inManagedObjectContext:context];

    newRoutine.users = [self getCurrentUser];
    newRoutine.routineName = @"myRoutine Test Name";
    NSError* error;
    [context save:&error ];

    NSLog(@"Saved now try to fetch");
    [self fetch];

}
-(void) fetch {
    NSFetchRequest *fetchRequestItems = [[NSFetchRequest alloc] init];
    NSEntityDescription *entityItem = [NSEntityDescription entityForName:@"Routine" inManagedObjectContext:context];
    [fetchRequestItems setEntity:entityItem];
    User* user = [self getCurrentUser];
    // if i try [[self getCurrentUser] usersRoutine] it shows an error

    [fetchRequestItems setPredicate:[NSPredicate predicateWithFormat:@"users == %@",user]];

    //Sort by last edit ordered
    NSArray *sortDescriptors = [NSArray arrayWithObjects:nil];
    [fetchRequestItems setSortDescriptors:sortDescriptors];
    NSError *error = nil;
    NSArray* Routines = [context executeFetchRequest:fetchRequestItems error:&error];
    NSLog(@"result %@", [(Routine *)Routines[0] users]  );


}
-(User *)getCurrentUser {
    NSEntityDescription *entityDesc = [NSEntityDescription entityForName:@"User" inManagedObjectContext:context];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entityDesc];

    if (_appDelegate.isFB)
    { 
        request.predicate = [NSPredicate predicateWithFormat:@"idFB LIKE %@",_appDelegate.fdID];
        NSError *error = nil;
        NSArray *matches = [[context executeFetchRequest:request error:&error] mutableCopy];

        return (User *)matches[0];
    } else
    {
        NSLog(@"CreateRoutinePOPUP NON FB TO BE TESTED");
        request.predicate = [NSPredicate predicateWithFormat:@"email LIKE %@",_appDelegate.currentUser];
        NSError *error = nil;
        NSArray *matches = [[context executeFetchRequest:request error:&error] mutableCopy];

        return (User *)matches[0];
    }

这是NSLog in fetch正在打印的内容:

2013-04-28 22:33:26.555 iGym[7916:c07] result <User: 0xa480580> (entity: User; id: 0xa495a00 <x-coredata://D87CEBB4-016C-4A1B-802C-2D1117BB3E51/User/p1> ; data: {
    dob = "1986-12-26 00:00:00 +0000";
    email = ".com";
    firstTime = nil;
    gender = male;
    height = nil;
    idFB =3333;
    idUserExternal = 0;
    idUserInternal = 0;
    isPT = nil;
    language = "en_US";
    location = "London, United Kingdom";
    metricSystem = nil;
    name = Joan;
    nickname = nil;
    password = nil;
    surname = Thurft;
    usersExercise = "<relationship fault: 0xa4824a0 'usersExercise'>";
    usersRoutine =     (
        "0xa495f00 <x-coredata://D87CEBB4-016C-4A1B-802C-2D1117BB3E51/Routine/p6>",
        "0xa4877e0 <x-coredata://D87CEBB4-016C-4A1B-802C-2D1117BB3E51/Routine/p1>",
        "0xa4877f0 <x-coredata://D87CEBB4-016C-4A1B-802C-2D1117BB3E51/Routine/p2>",
        "0xa487800 <x-coredata://D87CEBB4-016C-4A1B-802C-2D1117BB3E51/Routine/p3>",
        "0xa487810 <x-coredata://D87CEBB4-016C-4A1B-802C-2D1117BB3E51/Routine/p4>",
        "0xa487820 <x-coredata://D87CEBB4-016C-4A1B-802C-2D1117BB3E51/Routine/p5>"
    );
    weight = nil;
})
2013-04-28 22:33:26.555IGYM[7916:c07]结果(实体:用户;id:0xa495a00;数据:{
dob=“1986-12-26 00:00:00+0000”;
电子邮件=“.com”;
第一次=零;
性别=男性;
高度=零;
idFB=3333;
idUserExternal=0;
idUserInternal=0;
isPT=零;
language=“en_US”;
地点=“英国伦敦”;
度量系统=零;
姓名=琼;
昵称=零;
密码=零;
姓氏=瑟夫特;
usersExercise=“”;
用户路由=(
“0xa495f00”,
“0xa4877e0”,
“0xa4877f0”,
“0xa487800”,
“0xa487810”,
“0xa487820”
);
重量=零;
})
另外,当我添加NSLog(@“获取当前结果%@)”,[(用户*)匹配[0]用户路由];对于getCurrentUser方法,我得到了整个用户的数据,关系表示

usersExercise = "<relationship fault: 0xa464730 'usersExercise'>";
usersExercise=”“;

核心数据与使用标准数据库不同,在标准数据库中,您将一些外键(如
userID
)分配给另一个表,在该表中,您希望与
用户
对象建立关系,然后使用该外键查找关系,如
练习。where('User_ID=?',userID)
。相反,您可以定义实际的关系,并让核心数据在幕后处理一切,以设置任何联接表或外键

而不是你如何设置它,您只需在
用户
实体中有两个
练习
例程
的关系,它们映射到
练习
例程
实体,然后在
练习
例程
上有一个反向关系,如果是拥有并属于许多关系。因此,现在需要将
userseercise
替换为
练习
usersRoutine
替换为
例程
,然后将
用户id
替换为
练习
例程
实体的
用户

即使您实际上不需要这种反向关系,您仍然需要它,因为核心数据将其用于数据完整性目的,如果您不使用它,Xcode将向您发出警告

设置这些关系时,您将调用例程或练习,如
user.exercises
,这将返回该用户的相关练习集。正如您所注意到的,核心数据将返回一个关系的
错误
,该关系将被触发,并且在您实际需要该关系的内容时返回数据。存在错误,因此只返回您所需的信息,而不是对数据集运行不必要的查询

另一件需要注意的事情是,核心数据并不像您所做的那样引用唯一的id,比如
userID
。相反,核心数据中的每个对象都有一个由
[objectName objectID]
找到的唯一ID(只有在保存到数据存储后才是永久的)。除特殊情况外,您确实不需要将唯一ID设置为实体的属性

此外,您确实不需要使用那些唯一的
objectID
,除非您像在后台处理的多线程应用程序中一样传递对象,在这种情况下
NSManagedObjectID
是线程安全的,您可以使用它在后台线程/托管对象上下文中再次查找对象

我真的建议你读一篇关于核心数据的介绍,比如

如果您习惯了正常的数据库设置/体系结构,那么在开始转换为核心数据时可能会有点奇怪,但一旦您习惯了,它实际上会快得多,并为您处理所有幕后的繁重工作


根据评论更新:


您误解了核心数据中的关系概念。在核心数据中,关系不会像典型的数据库连接关系那样返回关联的ID。相反,它返回一个错误,当您需要该关系中的数据时,会触发该错误。因此,它不是返回整个
User
对象,而是将
fault
返回关联的
User
对象,当您执行类似
exercise.User.name


您的代码的工作方式与您保存时的工作方式完全相同,您只是错误地认为它不是。

您需要使用提供的方法在一对多对象中添加“多对象”。在您的例子中,它被称为
addRoutineObject:

尝试此新的保存方法:

- (void) save {

    Routine *newRoutine = [NSEntityDescription insertNewObjectForEntityForName:@"Routine" inManagedObjectContext:context];
    newRoutine.routineName = @"myRoutine Test Name";

    NSEntityDescription *entityDesc = [NSEntityDescription entityForName:@"User" inManagedObjectContext:context];
    NSFetchRequest *request = [[NSFetchRequest alloc] init];
    [request setEntity:entityDesc];


    NSArray *matches;
    NSError *error = nil;
    if (_appDelegate.isFB)
    { 
        request.predicate = [NSPredicate predicateWithFormat:@"idFB LIKE %@",_appDelegate.fdID];
        matches = [[context executeFetchRequest:request error:&error] mutableCopy];

    } else
    {
        NSLog(@"CreateRoutinePOPUP NON FB TO BE TESTED");
        request.predicate = [NSPredicate predicateWithFormat:@"email LIKE %@",_appDelegate.currentUser];
        matches = [[context executeFetchRequest:request error:&error] mutableCopy];
    }

    if (matches.count == 0)
    {
        NSLog(@"no user matched");
    }
    else
    {
        User *aUser = [matches objectAtIndex:0];
        [aUser addRoutineObject:newRoutine];
        if (![context save:&error])
        {
            NSLog(@"couldn't save: %@", [error localizedDescription]);
        }
    }
   }

else循环中的此行:return(User*)匹配;是否应该返回(用户)*