如何使用魔法记录保存 2 个实体

Posted

技术标签:

【中文标题】如何使用魔法记录保存 2 个实体【英文标题】:How to save 2 entities using Magical Record 【发布时间】:2014-10-04 15:19:26 【问题描述】:

我想使用 Magical Record 一起保存 2 个实体(个人、组)。

//Model
// Person : name (Relationship : group 'To One')
// Group  : groupName (Relationship : person 'To Many')

“person.name”可以保存,但“person.group.groupName”不能保存。

当我签入 NSLog 时,“person.group.groupName”为 nil。

“self.groupName.text”是正确的值。

需要注意的是,“self.groupName.text”是在预先注册好的UIPickerView数据中选择的。因此,不能使用[Group MR_createEntity]。

请告诉我如何解决。谢谢。

SecondViewController.h

#import <UIKit/UIKit.h>
#import "Person.h"
#import "Group.h"

@class Person, Group;

@interface SecondViewController : UIViewController

@property (nonatomic, retain) Person *person;

@end

SecondViewController.m

#import "SecondViewController.h"
#import "AppDelegate.h"
#import "Person.h"
#import "Group.h"
#import "FirstViewController.h"

@interface SecondViewController ()<UIPickerViewDelegate,UIPickerViewDataSource,UITextFieldDelegate,UINavigationControllerDelegate,NSFetchedResultsControllerDelegate>


    BOOL isDispGroupPicker;
    UIPickerView *picker;
    int selectedGroupRow;


@property (weak, nonatomic) IBOutlet UITextField *nameField;
@property (weak, nonatomic) IBOutlet UITextField *groupField;
@property (strong, nonatomic) UIView *accessoryView;
- (IBAction)saveBtn:(id)sender;

@end

@implementation SecondViewController

- (void)viewDidLoad

    [super viewDidLoad];

    self.nameField.delegate = self;
    self.groupField.delegate = self;
    isDispGroupPicker = NO;

    picker = [[UIPickerView alloc] init];
    picker.frame = CGRectMake(0, 550, 320, 180);
    picker.showsSelectionIndicator = YES;
    picker.delegate = self;
    picker.dataSource = self;
    picker.tag = 1;
    [self.view addSubview:picker];


- (void)didReceiveMemoryWarning

    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


#pragma mark - save

- (IBAction)saveBtn:(id)sender

    NSManagedObjectContext *context = [NSManagedObjectContext MR_defaultContext];
    Person *person = [Person MR_createEntity];
    person.name = _nameField.text;
    //person.group.groupName = _groupField.text;

    Group *group = [[self.fetchedResultsController fetchedObjects] objectAtIndex:selectedGroupRow];
    person.group.groupName = group.groupName;

    NSLog(@"%@",group.groupName);       // OK
    NSLog(@"%@",person.group.groupName);// null->NG

    [context MR_saveToPersistentStoreAndWait];


#pragma mark - keyboard

- (BOOL)textFieldShouldReturn:(UITextField *)textField

    [self.view endEditing:YES];
    return NO;


- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField 
    BOOL ret = YES;
    if (textField == _nameField) 
        if(isDispGroupPicker) 
            [self hidePicker];
            [_accessoryView removeFromSuperview];
        

     else if (textField == _groupField) 
        [_nameField resignFirstResponder];
        if(!isDispGroupPicker) 
            picker.frame = CGRectMake(0, 550, 320, 216);
            [self showPicker];
            [self inputPickerClose];
            isDispGroupPicker = YES;
        
        ret = NO;
    
    return ret;


#pragma mark - FetchedResultsController

- (NSFetchedResultsController*)fetchedResultsController

    if(_fetchedResultsController == nil)
        self.fetchedResultsController = [Group MR_fetchAllSortedBy:@"groupName" ascending:YES withPredicate:nil groupBy:nil delegate:self];
    
    return _fetchedResultsController;


#pragma mark - GroupPicker

- (void)showPicker 
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.2];
    [UIView setAnimationDelegate:self];
    picker.frame = CGRectMake(0, 320, 320, 216);
    [UIView commitAnimations];


- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView

    return 1;


- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component

    return [[self.fetchedResultsController fetchedObjects] count];


- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component

    Group *group = [[self.fetchedResultsController fetchedObjects] objectAtIndex:row];
    return group.groupName;


- (void) pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component

    Group *group = [[self.fetchedResultsController fetchedObjects] objectAtIndex:row];
    self.groupField.text = group.groupName;
    selectedGroupRow = row;


- (void)inputPickerClose 
    _accessoryView =[[UIView alloc] initWithFrame:CGRectMake(0,310,320,44)];
    _accessoryView.backgroundColor = [UIColor lightGrayColor];
    [self.view addSubview:_accessoryView];

    UIButton* closeButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    closeButton.frame = CGRectMake(230,10,100,27);
    [closeButton setTitle:@"Done" forState:UIControlStateNormal];
    UIButton* cancelButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    cancelButton.frame = CGRectMake(0,10,100,27);
    [cancelButton setTitle:@"Cancel" forState:UIControlStateNormal];

    [closeButton addTarget:self action:@selector(doneGroup:) forControlEvents:UIControlEventTouchUpInside];
    [cancelButton addTarget:self action:@selector(cancelGroup:) forControlEvents:UIControlEventTouchUpInside];
    [_accessoryView addSubview:closeButton];
    [_accessoryView addSubview:cancelButton];


- (void)doneGroup:(id)sender 
    [self hidePicker];
    [_accessoryView removeFromSuperview];


- (void)cancelGroup:(id)sender 
    [self hidePicker];
    [_accessoryView removeFromSuperview];
    _groupField.text = nil;


- (void)hidePicker 
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationDuration:0.3];
    [UIView setAnimationDelegate:self];
    picker.frame = CGRectMake(0, 600, 320, 216);
    [UIView commitAnimations];
    isDispGroupPicker = NO;


@end

人.h

#import <Foundation/Foundation.h>

@class Group;

@interface Person : NSManagedObject

@property (nonatomic, retain) NSString *name;
@property (nonatomic, retain) NSString *image;
@property (nonatomic, retain) Group *group;

@end

【问题讨论】:

【参考方案1】:

Picker 应该选择 Group(显示名称)而不是 group.name,然后设置 person.group = group。

——更新

现在,在选择器上,您选择组名并尝试将该名称附加到 person.group.name,但此时 person.group 为 nil,因此您的代码什么也不做。因此,您的选择器必须返回一个 Group 对象,而不仅仅是它的名称 - 您可以将所有组加载到 NSArray 并从选择器位置选择它的索引。之后,您将正确选择将附加到 Person 对象 (person.group) 的 Group 对象。

【讨论】:

对不起。我不明白。请告诉我更多信息。 谢谢。我明白你说的意思,但我不知道方法。我是编程初学者,并尝试以我认为您所说的方式解决,但它不起作用。我上传了所有代码。请指出代码? 多试几次解决。非常感谢。

以上是关于如何使用魔法记录保存 2 个实体的主要内容,如果未能解决你的问题,请参考以下文章

如何保存重复记录使用belongsToMany?

魔法记录,无法保存对象:contextDidSave == NO, error = nil

使用魔法记录进行核心数据迁移

如何使实体框架对每条记录使用 1 个更新查询而不是 1 个?

保存在魔法记录中?

在 coredata 中保存实体数组