[英]where to implement Core Data?
我對核心數據編程完全陌生。 我只是想找出實現核心數據代碼的最佳位置。 我已經完成了蘋果教程 Locations 並且效果很好。 現在我嘗試將其轉移到我當前的項目中,這有點復雜。
Locations 教程展示了一個 RootViewController,包括一個以編程方式生成的 tableView。 我的項目基於 tabView 模板。 它擁有一個 MainWindow.xib,包括 TabBarController,其中包括三個 ViewController(MapView、ListView、SettingsView),其中每個視圖都有自己的 navigationController 和 xib 文件。
第一個絆腳石是更改它將使用 xib 為 tableView 運行的代碼,而不是以編程方式創建它。 我已經做到了,但仍然有一個錯誤。 我無法將 appDelegate 中的 managedObjectContext 連接到 listViewController。 我已經嘗試了這里論壇中針對該問題的示例和建議。 但它仍然不起作用。
在查看 CoreDataBooks 示例項目后,我發現核心數據代碼也在 RootViewController 中實現。 似乎在 ListViewController 中實現它是錯誤的方法。 但我的項目中沒有 RootViewController。 在 AppDelegate 中,我直接將 tabBarController 作為 rootViewController 傳遞。 因此我不知道如何訪問 listViewController 來設置上下文,就像在 Locations 示例中所做的那樣。
由於 MapView 是第一個視圖,我無法在 appDelegate 中設置上下文。 在使用 managedObjectContext 掙扎了很長時間之后,我想知道是否最好發明一個 RootViewController 以便能夠在那里放置額外的代碼。 model 應該可以被所有三個視圖訪問,並且似乎 RootViewController 是正確的位置。
但是我如何將它與包含另外三個基於 xib 文件的 viewControllers 的 tabBarController 結合起來呢? 有人可以推薦我示例或教程,包括基於標簽欄應用程序的核心數據嗎?
請閱讀 Marcus Zarra 的以下文章: 在 iOS 上傳遞 NSManagedObjectContext 。 這應該讓你知道如何解決你的問題。
通常,您應該向所有 ViewController 添加一個 NSManagedObjectContext 屬性,並在通過pushViewController:animated:
將它們添加到視圖堆棧之前傳遞上下文。 您不應該從您的應用委托中獲取上下文。
如果將單個 NSManagedObject 傳遞給 ViewController,例如呈現一種詳細視圖,則可以從該 object 訪問上下文,因為每個 NSManagedObject 都知道它“生活”在其中的 NSManagedObjectContext。
如果您是注冊的 iOS 開發人員,我還推薦 WWDC 2010 和 2011 視頻。 有一些關於掌握核心數據的課程。
好的,現在我有正確的解決方案。 花了一些時間來理解,但現在它可以使用從應用程序委托到視圖控制器(listViewController)的依賴注入。
我的問題是我不知道如何引用我的視圖控制器,因為它們嵌套在專用的導航控制器和一個 tabBarController 中。
在這里閱讀了很多帖子后,我了解到我必須在 appDelegate.h 中聲明我的視圖控制器並在 appDelegate.m 中合成它們,然后將它們連接到 IB 中的適當項目。 理解后快速輕松地完成了:-)
不需要 rootViewController。
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:
#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
#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
列表視圖控制器.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;
}
...
前段時間我編寫了一個類似的應用程序。 我解決它的方法是我制作了一個 singleton ,它有一個像 Apple 文檔中一樣的persistentStoreCoordinator
屬性來保存對數據庫的訪問(所以我不必每次都寫它)。 然后在每個標簽欄視圖 controller 我已經啟動了它自己的 NSManagedObjectContext。
NSPersistentStoreCoordinator *coordinator = [[Singleton sharedSingleton] persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator: coordinator];
}
這樣,如果您理解我的意思,每個 controller 都會使用自己的上下文來處理數據庫。
請注意,如果您的任何視圖控制器具有詳細視圖 controller,請采用標准方法將托管 object 上下文傳遞給它,就像在示例代碼(書籍、位置、食譜)中一樣。
我剛剛修復了這個錯誤。 我錯過了 appDelegate 中一些必要的方法。 如果我將以下代碼放入 ListViewController 的 viewDidLoad 中,它現在可以工作
if (managedObjectContext == nil) {
NSLog(@"managedObjectContext is nil");
managedObjectContext = [(IntraAppAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
關於正確的 MVC 模式規則可以嗎? 在我的例子中,ViewController 現在從 appDelegate 獲取上下文。
嘗試使用類似的方式在 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;
如何在應用程序啟動后收集由 tabBarController 控制且不是 topView/superView 的其他 viewControllers 的引用? 第一個視圖是 MapView。 我必須在 appDelegate 中實例化或聲明 listViewController 嗎? 它必須如何編碼才能引用由 tabBarController 控制的 listViewController?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.