简体   繁体   English

在哪里实施核心数据?

[英]where to implement Core Data?

I´m completely new to core data programming.我对核心数据编程完全陌生。 i just try to find out where the best place for implementing the core data code would be.我只是想找出实现核心数据代码的最佳位置。 i´ve done the apple tutorial Locations and it worked well.我已经完成了苹果教程 Locations 并且效果很好。 now i try to transfer that to my current project what is a bit more complex.现在我尝试将其转移到我当前的项目中,这有点复杂。

the Locations tutorial shows one RootViewController including a programmatically generated tableView. Locations 教程展示了一个 RootViewController,包括一个以编程方式生成的 tableView。 my project is based on a tabView template.我的项目基于 tabView 模板。 it owns a MainWindow.xib including the TabBarController including three ViewController (MapView, ListView, SettingsView) where each view has it´s own navigationController and xib-file.它拥有一个 MainWindow.xib,包括 TabBarController,其中包括三个 ViewController(MapView、ListView、SettingsView),其中每个视图都有自己的 navigationController 和 xib 文件。

The first stumbling block was changing the code that it will run with a xib for the tableView instead of creating it programmatically.第一个绊脚石是更改它将使用 xib 为 tableView 运行的代码,而不是以编程方式创建它。 I´ve managed that but there is still one error.我已经做到了,但仍然有一个错误。 I can´t connect the managedObjectContext from the appDelegate to the listViewController.我无法将 appDelegate 中的 managedObjectContext 连接到 listViewController。 I´ve tried the examples and suggestions for that issue from this forum here.我已经尝试了这里论坛中针对该问题的示例和建议。 but it still doesn´t work.但它仍然不起作用。

after looking at the CoreDataBooks sample project i´ve seen that the core data code was implemented in the RootViewController as well.在查看 CoreDataBooks 示例项目后,我发现核心数据代码也在 RootViewController 中实现。 Seems that it would be the wrong way to implement it in the ListViewController.似乎在 ListViewController 中实现它是错误的方法。 But i don´t have a RootViewController in my project.但我的项目中没有 RootViewController。 In the AppDelegate i directly pass the tabBarController as the rootViewController.在 AppDelegate 中,我直接将 tabBarController 作为 rootViewController 传递。 therefore i don´t know how to reach the listViewController to set the context like it was done in the Locations sample.因此我不知道如何访问 listViewController 来设置上下文,就像在 Locations 示例中所做的那样。

As the MapView is the first view i can´t set the context in the appDelegate.由于 MapView 是第一个视图,我无法在 appDelegate 中设置上下文。 And after struggling a long time with the managedObjectContext i wonder if it would be better to invent a RootViewController to be able to place additional code there.在使用 managedObjectContext 挣扎了很长时间之后,我想知道是否最好发明一个 RootViewController 以便能够在那里放置额外的代码。 the model should be accessible by all three views and it seems that the RootViewController is the right place. model 应该可以被所有三个视图访问,并且似乎 RootViewController 是正确的位置。

But how do i combine that with a tabBarController which includes three more viewControllers based on xib-files?但是我如何将它与包含另外三个基于 xib 文件的 viewControllers 的 tabBarController 结合起来呢? Could somebody recommend me examples or tutrials including core data based on a tab bar app?有人可以推荐我示例或教程,包括基于标签栏应用程序的核心数据吗?

Please read the following article by Marcus Zarra: Passing around a NSManagedObjectContext on iOS .请阅读 Marcus Zarra 的以下文章: 在 iOS 上传递 NSManagedObjectContext That should give you an idea how to solve your problem.这应该让你知道如何解决你的问题。

In general you should add a NSManagedObjectContext property to all of your ViewControllers and pass the context before adding them to the view stack via pushViewController:animated: .通常,您应该向所有 ViewController 添加一个 NSManagedObjectContext 属性,并在通过pushViewController:animated:将它们添加到视图堆栈之前传递上下文。 You should not take the context from your app delegate.您不应该从您的应用委托中获取上下文。

If you pass a single NSManagedObject to a ViewController, eg to present a kind of detail view, you can access the context from that object, as every NSManagedObject knows about the NSManagedObjectContext it is "living" in.如果将单个 NSManagedObject 传递给 ViewController,例如呈现一种详细视图,则可以从该 object 访问上下文,因为每个 NSManagedObject 都知道它“生活”在其中的 NSManagedObjectContext。

If you are a registered iOS developer, I'd also recommend the WWDC 2010 and 2011 videos.如果您是注册的 iOS 开发人员,我还推荐 WWDC 2010 和 2011 视频。 There are some sessions about mastering Core Data.有一些关于掌握核心数据的课程。

ok, now i have the correct solution.好的,现在我有正确的解决方案。 it took a while to understand but now it works with dependency injection from application delegate into the view controllers (listViewController).花了一些时间来理解,但现在它可以使用从应用程序委托到视图控制器(listViewController)的依赖注入。

my problem was that i didn´t know how to reference my view controllers as they are nested into dedicated navControllers and one tabBarController.我的问题是我不知道如何引用我的视图控制器,因为它们嵌套在专用的导航控制器和一个 tabBarController 中。

after reading a lot of postings here i understood i have to declare my view controllers in the appDelegate.h and synthesize them in appDelegate.m and after that connect them to the appropirate item in IB.在这里阅读了很多帖子后,我了解到我必须在 appDelegate.h 中声明我的视图控制器并在 appDelegate.m 中合成它们,然后将它们连接到 IB 中的适当项目。 that was done fast & easy after understanding:-)理解后快速轻松地完成了:-)

there is no rootViewController needed.不需要 rootViewController。

MyAppDelegate.h: MyAppDelegate.h:

#import <UIKit/UIKit.h>
#import "ListViewController.h"

@interface MyAppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate> {

    UIWindow *window;
    UITabBarController *tabBarController;
    IBOutlet ListViewController *listViewController;
}

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
@property (nonatomic, retain) IBOutlet ListViewController *listViewController;

@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;

- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;

@end

MyAppDelegate.m: MyAppDelegate.m:

#import "MyAppDelegate.h"
#import "ListViewController.h"

@implementation MyAppDelegate

@synthesize window=_window;

@synthesize tabBarController=_tabBarController;

@synthesize managedObjectContext=__managedObjectContext;

@synthesize managedObjectModel=__managedObjectModel;

@synthesize persistentStoreCoordinator=__persistentStoreCoordinator;

@synthesize listViewController;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{

    NSManagedObjectContext *context = [self managedObjectContext];

    if (!context) {
        // Handle the error.
    }
    // Pass the managed object context to the view controller.
    listViewController.managedObjectContext = context;

    // Override point for customization after application launch.
    // Add the tab bar controller's current view as a subview of the window
    self.window.rootViewController = self.tabBarController;

    [self.window makeKeyAndVisible];
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleBlackOpaque animated:NO];  
    return YES;
}

...

ListViewController.h ListViewController.h

#import <CoreLocation/CoreLocation.h>


@interface ListViewController : UITableViewController <CLLocationManagerDelegate> {

    UINavigationController *navController;
    NSManagedObjectContext *managedObjectContext;
}

@property (nonatomic, retain) IBOutlet UINavigationController *navController;
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;

-(NSManagedObjectContext *)managedObjectContext;

@end

ListViewController.m列表视图控制器.m

#import "MyAppDelegate.h"
#import "ListViewController.h"


@implementation ListViewController

@synthesize navController;
@synthesize managedObjectContext;

- (void)viewDidLoad {

    [super viewDidLoad];

    NSLog(@"managedObjectContext: %@",[self managedObjectContext]);

    NSError *error = nil;
    if (![managedObjectContext save:&error]) {
        NSLog(@"error: %@",[self managedObjectContext]);
        return;
    }

...

I've coded an app like that some time ago.前段时间我编写了一个类似的应用程序。 The way I've solved it is I made a singleton which had a persistentStoreCoordinator property like the one in Apple documentation to hold the access to the database (so I don't have to write it every time).我解决它的方法是我制作了一个 singleton ,它有一个像 Apple 文档中一样的persistentStoreCoordinator属性来保存对数据库的访问(所以我不必每次都写它)。 Then in every tab bar view controller I've initiated its own NSManagedObjectContext.然后在每个标签栏视图 controller 我已经启动了它自己的 NSManagedObjectContext。

NSPersistentStoreCoordinator *coordinator = [[Singleton sharedSingleton] persistentStoreCoordinator];
        if (coordinator != nil) {
            _managedObjectContext = [[NSManagedObjectContext alloc] init];
            [_managedObjectContext setPersistentStoreCoordinator: coordinator];
        }

That way every controller approaches the database with it's own context, if you understand what I mean.这样,如果您理解我的意思,每个 controller 都会使用自己的上下文来处理数据库。

Please note that if any of your view controllers has a detail view controller, take the standard approach of passing the managed object context to it like in sample code (Books, Locations, Recipes).请注意,如果您的任何视图控制器具有详细视图 controller,请采用标准方法将托管 object 上下文传递给它,就像在示例代码(书籍、位置、食谱)中一样。

i just fixed the bug.我刚刚修复了这个错误。 i missed out some methods necessary in the appDelegate.我错过了 appDelegate 中一些必要的方法。 it works now if i put following code into viewDidLoad of my ListViewController如果我将以下代码放入 ListViewController 的 viewDidLoad 中,它现在可以工作

if (managedObjectContext == nil) { 
    NSLog(@"managedObjectContext is nil");
    managedObjectContext = [(IntraAppAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}

is that OK concerning proper MVC pattern rules?关于正确的 MVC 模式规则可以吗? in my case the ViewController takes the context from the appDelegate now.在我的例子中,ViewController 现在从 appDelegate 获取上下文。

trying to set the context in the appDelegate with something like that throws an error:尝试使用类似的方式在 appDelegate 中设置上下文会引发错误:

 NSManagedObjectContext *context = [self managedObjectContext];

    if (!context) {
        // Handle the error.
    }
    // Pass the managed object context to the view controller.

    self.tabBarController.listViewController.navController.managedObjectContext = context;
    self.window.rootViewController = self.tabBarController;

how can i gather the reference of other viewControllers which are controlled by the tabBarController and are not the topView/superView after app start?如何在应用程序启动后收集由 tabBarController 控制且不是 topView/superView 的其他 viewControllers 的引用? the first view is the MapView.第一个视图是 MapView。 do i have to instantiate or declare the listViewController in appDelegate?我必须在 appDelegate 中实例化或声明 listViewController 吗? how must it be coded that it referes to the listViewController controlled by the tabBarController?它必须如何编码才能引用由 tabBarController 控制的 listViewController?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM