如何使用魔法记录保存 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 个实体的主要内容,如果未能解决你的问题,请参考以下文章
魔法记录,无法保存对象:contextDidSave == NO, error = nil