objective-c 将 ManagedObjectContext 传递给第二个视图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1074539/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:51:34  来源:igfitidea点击:

Passing a ManagedObjectContext to a second view

iphoneobjective-ccocoa-touchcore-data

提问by amo

I'm writing my first iPhone/Cocoa app. It has two table views inside a navigation view. When you touch a row in the first table view, you are taken to the second table view. I would like the second view to display records from the CoreData entities related to the row you touched in the first view.

我正在编写我的第一个 iPhone/Cocoa 应用程序。它在导航视图中有两个表视图。当您触摸第一个表格视图中的一行时,您将进入第二个表格视图。我希望第二个视图显示来自与您在第一个视图中触摸的行相关的 CoreData 实体的记录。

I have the CoreData data showing up fine in the first table view. You can touch a row and go to the second table view. I'm able to pass info from the selected object from the first to the second view. But I cannot get the second view to do its own CoreData fetching. For the life of me I cannot get the managedObjectContext object to pass to the second view controller. I don't want to do the lookups in the first view and pass a dictionary because I want to be able to use a search field to refine results in the second view, as well as insert new entries to the CoreData data from there.

我在第一个表视图中显示了 CoreData 数据。您可以触摸一行并转到第二个表格视图。我可以将所选对象的信息从第一个视图传递到第二个视图。但是我无法获得第二个视图来执行自己的 CoreData 获取。在我的一生中,我无法将 managedObjectContext 对象传递给第二个视图控制器。我不想在第一个视图中进行查找并传递字典,因为我希望能够使用搜索字段来优化第二个视图中的结果,以及从那里向 CoreData 数据插入新条目。

Here's the function that transitions from the first to the second view.

这是从第一个视图转换到第二个视图的函数。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // Navigation logic may go here -- for example, create and push another view controller.
    NSManagedObject *selectedObject = [[self fetchedResultsController] objectAtIndexPath:indexPath];
    SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:@"SecondView" bundle:nil];

    secondViewController.tName = [[selectedObject valueForKey:@"name"] description];
    secondViewController.managedObjectContext = [self managedObjectContext];

    [self.navigationController pushViewController:secondViewController animated:YES];
    [secondViewController release];
}

And this is the function inside SecondViewController that crashes:

这是 SecondViewController 中崩溃的函数:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.title = tName;

    NSError *error;
    if (![[self fetchedResultsController] performFetch:&error]) { // <-- crashes here
        // Handle the error...
    }
}

- (NSFetchedResultsController *)fetchedResultsController {

    if (fetchedResultsController != nil) {
        return fetchedResultsController;
    }

    /*
     Set up the fetched results controller.    
     */
    // Create the fetch request for the entity.
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    // Edit the entity name as appropriate.
        // **** crashes on the next line because managedObjectContext == 0x0
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"SecondEntity" inManagedObjectContext:managedObjectContext]; 
    [fetchRequest setEntity:entity];

    // <snip> ... more code here from Apple template, never gets executed because of the crashing

    return fetchedResultsController;
}

Any ideas on what I am doing wrong here?

关于我在这里做错了什么的任何想法?

managedObjectContext is a retained property.

managedObjectContext 是一个保留属性。

UPDATE: I inserted a NSLog([[managedObjectContext registeredObjects] description]); in viewDidLoad and it appears managedObjectContext is being passed just fine. Still crashing, though.

更新:我插入了一个 NSLog([[managedObjectContextregisteredObjects] description]); 在 viewDidLoad 中,看起来 managedObjectContext 传递得很好。不过还是会崩溃。

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+entityForName: could not locate an NSManagedObjectModel for entity name 'SecondEntity''

由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“+entityForName:无法找到实体名称“SecondEntity”的 NSManagedObjectModel”

采纳答案by amo

Oh, this is interesting. I spent some quality time with the stack trace and I think I've got it figured out.

哦,这很有趣。我在堆栈跟踪上花了一些时间,我想我已经弄清楚了。

So pushViewController calls viewDidLoad not once, but twice. The first time it calls viewDidLoad, the objects appear to not be instantiated properly. The second time, they are. So the first time this code runs it can't access managedObjectContext and it throws an exception. The second time it runs, everything's fine. No crash.

所以 pushViewController 调用 viewDidLoad 不是一次,而是两次。第一次调用 viewDidLoad 时,对象似乎没有正确实例化。第二次,他们是。因此,此代码第一次运行时无法访问 managedObjectContext 并引发异常。第二次运行,一切正常。没有崩溃。

There are a lot of references to problems with viewDidLoad executing multiple times on Google, so I think the solution is to not do this fetch request initialization in viewDidLoad.

有很多关于viewDidLoad在Google上多次执行的问题的参考,所以我认为解决方案是不要在viewDidLoad中进行这个fetch请求初始化。

回答by Sascha Konietzke

You can suppress the '-managedObjectContext' not found in protocols warning by casting your application delegate first:

您可以通过首先投射您的应用程序委托来抑制协议警告中未找到的“-managedObjectContext”:

if (managedObjectContext == nil) { managedObjectContext = [(MyAppDelegateName *)[[UIApplication sharedApplication] delegate] managedObjectContext]; }

回答by aryeh

I've been struggling with the same issue and I'm still just a newbie. I think I figured out what is going on. Let me know if this makes sense.

我一直在为同样的问题苦苦挣扎,我仍然只是一个新手。我想我知道发生了什么。让我知道这是否有意义。

In short you are trying to fetch an entity from an objectContext that hadn't been set up yet. Your options therefore are to set it up right then or do elsewhere in the app before this view loads.

简而言之,您正在尝试从尚未设置的 objectContext 中获取实体。因此,您的选择是立即设置它或在此视图加载之前在应用程序中的其他地方进行设置。

If your app is setup like the CoreDataBooks app demo from the iphone dev center with a main UIApplicationDelegate also managing the CoreData stack, then you should be able to do the following:

如果您的应用程序的设置类似于 iphone 开发中心的 CoreDataBooks 应用程序演示,并且主 UIApplicationDelegate 也管理 CoreData 堆栈,那么您应该能够执行以下操作:

if (managedObjectContext == nil) { managedObjectContext = [[[UIApplication sharedApplication] delegate] managedObjectContext]; }

if (managedObjectContext == nil) { managedObjectContext = [[[UIApplication sharedApplication] delegate] managedObjectContext]; }

This should do the trick.

这应该可以解决问题。

回答by Weizhi

in your first tableViewController, you can pass the managedObjectContextby : secondTableController.managedObjectContext = [(AppDelegate *) [[UIApplication sharedApplication ] delegate ] managedObjectContext ], maybe it's ok

在你的第一次tableViewController,你可以通过managedObjectContext: secondTableController.managedObjectContext = [(AppDelegate *) [[UIApplication sharedApplication ] delegate ] managedObjectContext ],也许没问题

回答by Chad Celsius

I had this problem and found that my object's init message was accessing the managedObjectContext before the setManagedObjectContext was being called...

我遇到了这个问题,发现在调用 setManagedObjectContext 之前,我的对象的 init 消息正在访问 managedObjectContext ...

Before:

前:

 dataController = [[DataController alloc] init];
 [dataController setManagedObjectContext:[self managedObjectContext]];

After:

后:

 dataController = [DataController alloc];
 [dataController setManagedObjectContext:[self managedObjectContext]];            
 [dataController init];

feh. Rookie error.

呵呵 菜鸟错误。

回答by teliaz

Apple provides a sample project called "iPhoneCoreDataRecipes". There is a very interesting article about passing NSManagedObjectContext hereIf you try to implement this kind of logic that each managedObjectContext is as a island on its own in each UIViewController

Apple 提供了一个名为“iPhoneCoreDataRecipes”的示例项目。有一个关于传递的NSManagedObjectContext很有趣的文章,在这里如果你试图实现这种逻辑,每个managedObjectContext是在每个UIViewController中本身就是一个岛

Try Changing code

尝试更改代码

if (managedObjectContext == nil) { managedObjectContext = [(MyAppDelegateName *)[[UIApplication sharedApplication] delegate] managedObjectContext]; }

With this

有了这个

if (managedObjectContext == nil) { managedObjectContext = self.managedObjectContext }

回答by Daniel Dickison

Are you sure there's an entity called "SecondEntity"? (That would be the straightforward way to interpret the error message.)

你确定有一个名为“SecondEntity”的实体吗?(这将是解释错误消息的直接方法。)

However, if this is a master list -> detail view type interaction, I would suggest passing the selected object directly to the second view controller, rather than giving it just the "tname". This object presumably contains everything you need to populate the second table directly via its properties.

但是,如果这是一个主列表 -> 详细视图类型交互,我建议将所选对象直接传递给第二个视图控制器,而不是只给它“tname”。该对象可能包含您通过其属性直接填充第二个表所需的一切。

That way, you don't actually do any explicit fetching in the second view controller. I.e:

这样,您实际上不会在第二个视图控制器中执行任何显式获取。IE:

@interface SecondViewController : UITableViewController
@property (nonatomic, retain) NSManagedObject *selectedObject;
@end

@implementation SecondViewController
- (void)viewDidLoad
{
    NSMutableArray *stuff = [[[selectedObject valueForKey:@"aToManyRelationship"] allObjects] mutableCopy];
    // sort stuff the way you want to display them, etc.
}
...

回答by mmc

Just for kicks.. try replacing:

只是为了踢..尝试更换:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"SecondEntity" inManagedObjectContext:managedObjectContext]; 

with:

和:

NSEntityDescription *entity = [NSEntityDescription entityForName:@"SecondEntity" inManagedObjectContext:[self managedObjectContext]]; 

You are setting managedObjectContext through a setter, and then trying to access the ivar directly. Depending on how your properties are defined, this may not be correct. [self managedObjectContext] will try to access the value through the getter, rather than directly.

您正在通过 setter 设置 managedObjectContext,然后尝试直接访问 ivar。根据您的属性的定义方式,这可能不正确。[self managedObjectContext] 将尝试通过 getter 而不是直接访问该值。

回答by jasongregori

This might be the problem.

这可能是问题所在。

short answer: delete your app then run it again.

简短回答:删除您的应用程序,然后再次运行它。

long answer:

长答案:

If you build and run your project, CoreData will save your model to wherever you said to (persistent store location).

如果您构建并运行您的项目,CoreData 会将您的模型保存到您所说的任何位置(持久存储位置)。

If you change something in the CoreData model, when you run the app again the new model will not match the saved model giving you that error.

如果您更改 CoreData 模型中的某些内容,当您再次运行该应用程序时,新模型将与保存的模型不匹配,从而出现该错误。

To fix it, delete your app. This will get rid of the saved model and when you run it again, it will recreate your new model.

要修复它,请删除您的应用。这将摆脱保存的模型,当您再次运行它时,它将重新创建您的新模型。

回答by Mr. Cairo

One thing for sure, the line: secondViewController.managedObjectContext = [self managedObjectContext];

可以肯定的是,这一行: secondViewController.managedObjectContext = [self managedObjectContext];

Should be: secondViewController.managedObjectContext = self.managedObjectContext;

应该是: secondViewController.managedObjectContext = self.managedObjectContext;

Unless the current object implements a method called 'managedObjectContext' which returns that variable.

除非当前对象实现了一个名为“managedObjectContext”的方法,该方法返回该变量。