私はCore DataデータベースとRuby on Railsサーバーを持つiOSクライアントを含むディプロマプロジェクトに取り組んでいます。私は彼らの間の通信のためにRestKitを使用しています。現在、私は、全体のシステムが動作するようになって大きな問題を抱えている:私は、サーバーからオブジェクトへの応答をマップしようとして、私は次の例外取得:RKResponseMapperOperationでNSManagedObjectContextがnilであるためRestKitがクラッシュする
2013-02-08 22:40:43.947 App[66735:5903] *** Assertion failure in -[RKManagedObjectResponseMapperOperation performMappingWithObject:error:], ~/Repositories/App/RestKit/Code/Network/RKResponseMapperOperation.m:358
2013-02-08 23:04:30.562 App[66735:5903] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Unable to perform mapping: No `managedObjectContext` assigned. (Mapping response.URL = http://localhost:3000/contacts?auth_token=s78UFMq8mCQrr12GZcyx)'
*** First throw call stack:
(0x1de9012 0x1c0ee7e 0x1de8e78 0x16a4f35 0x8f56e 0x8d520 0x1647d23 0x1647a34 0x16d4301 0x23a253f 0x23b4014 0x23a52e8 0x23a5450 0x90ac6e12 0x90aaecca)
libc++abi.dylib: terminate called throwing an exception
を私がロードしようとしていますサーバーからの連絡先のリスト(配列)。これは、コアデータに「ユーザー」として保存する必要があります。
私はこのビデオで見たように、データモデルクラスに私のすべてのコアデータコードを構成しました:http://nsscreencast.com/episodes/11-core-data-basics。ここでは、次のとおりです。
ヘッダファイル:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface AppDataModel : NSObject
+ (id)sharedDataModel;
@property (nonatomic, readonly) NSManagedObjectContext *mainContext;
@property (nonatomic, strong) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, readonly) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (NSString *)modelName;
- (NSString *)pathToModel;
- (NSString *)storeFilename;
- (NSString *)pathToLocalStore;
@end
実装ファイル:
#import "AppDataModel.h"
@interface AppDataModel()
- (NSString *)documentsDirectory;
@end
@implementation AppDataModel
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
@synthesize mainContext = _mainContext;
+ (id)sharedDataModel {
static AppDataModel *__instance = nil;
if (__instance == nil) {
__instance = [[AppDataModel alloc] init];
}
return __instance;
}
- (NSString *)modelName {
return @"AppModels";
}
- (NSString *)pathToModel {
return [[NSBundle mainBundle] pathForResource:[self modelName]
ofType:@"momd"];
}
- (NSString *)storeFilename {
return [[self modelName] stringByAppendingPathExtension:@"sqlite"];
}
- (NSString *)pathToLocalStore {
return [[self documentsDirectory] stringByAppendingPathComponent:[self storeFilename]];
}
- (NSString *)documentsDirectory {
NSString *documentsDirectory = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
documentsDirectory = [paths objectAtIndex:0];
return documentsDirectory;
}
- (NSManagedObjectContext *)mainContext {
if (_mainContext == nil) {
_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_mainContext.persistentStoreCoordinator = [self persistentStoreCoordinator];
}
return _mainContext;
}
- (NSManagedObjectModel *)managedObjectModel {
if (_managedObjectModel == nil) {
NSURL *storeURL = [NSURL fileURLWithPath:[self pathToModel]];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:storeURL];
}
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (_persistentStoreCoordinator == nil) {
NSLog(@"SQLITE STORE PATH: %@", [self pathToLocalStore]);
NSURL *storeURL = [NSURL fileURLWithPath:[self pathToLocalStore]];
NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:[self managedObjectModel]];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
NSError *e = nil;
if (![psc addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeURL
options:options
error:&e]) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:e forKey:NSUnderlyingErrorKey];
NSString *reason = @"Could not create persistent store.";
NSException *exc = [NSException exceptionWithName:NSInternalInconsistencyException
reason:reason
userInfo:userInfo];
@throw exc;
}
_persistentStoreCoordinator = psc;
}
return _persistentStoreCoordinator;
}
@end
UserクラスのXcodeで自動生成された、非常に簡単です。
ヘッダファイル:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface User : NSManagedObject
@property (nonatomic, retain) NSString * email;
@property (nonatomic, retain) NSString * firstName;
@property (nonatomic, retain) NSString * lastName;
@property (nonatomic, retain) NSNumber * userID;
@end
実装ファイル:
#import "User.h"
@implementation User
@dynamic email;
@dynamic firstName;
@dynamic lastName;
@dynamic userID;
@end
だけで、データ・モデル・クラスのように、私は私が通信に使用サーバ・マネージャクラスあります
ヘッダーをファイル:
#import <Foundation/Foundation.h>
#import <RestKit/RestKit.h>
#import "AppServerProtocol.h"
#import "AppDataModel.h"
@interface AppServer : NSObject <AppServerDelegate>
+ (id)sharedInstance;
@property (strong, nonatomic) RKObjectManager *objectManager;
@property (strong, nonatomic) RKEntityMapping *userMapping;
@end
と実装ファイル:
#import "AppServer.h"
#import "User.h"
#import "Device.h"
#import "Ping.h"
#import "AppAppDelegate.h"
@interface AppServer()
@property BOOL initialized;
@end
@implementation AppServer
+ (id)sharedInstance {
static AppServer *__instance = nil;
if (__instance == nil) {
__instance = [[AppServer alloc] init];
__instance.initialized = NO;
}
if (![__instance initialized]) {
[__instance initServer];
}
return __instance;
}
- (void)initServer {
// initialize RestKit
NSURL *baseURL = [NSURL URLWithString:@"http://localhost:3000"];
_objectManager = [RKObjectManager managerWithBaseURL:baseURL];
// enable activity indicator spinner
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
// initialize managed object store
_objectManager.managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:[[AppDataModel sharedDataModel] managedObjectModel]];
_userMapping = [RKEntityMapping mappingForEntityForName:@"User" inManagedObjectStore:_objectManager.managedObjectStore];
[_userMapping addAttributeMappingsFromDictionary:@{
@"email" : @"email",
@"firstName" : @"first_name",
@"lastName" : @"last_name"
}];
[_userMapping setIdentificationAttributes: @[@"userID"]];
RKResponseDescriptor *contactsResponseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:_userMapping pathPattern:@"/contacts" keyPath:nil statusCodes:nil];
[_objectManager addResponseDescriptor:contactsResponseDescriptor];
_initialized = YES;
}
// contacts
- (void)getContactsForCurrentUser {
NSString *authToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppAuthenticationToken"];
[_objectManager getObjectsAtPath:@"/contacts" parameters:@{@"auth_token": authToken} success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
RKLogInfo(@"Load collection of contacts: %@", mappingResult.array);
} failure:^(RKObjectRequestOperation *operation, NSError *error) {
RKLogError(@"Operation failed with error: %@", error);
}];
}
@end
私がフェッチ結果コントローラを使用するように正しく設定されている連絡先のテーブルビューを開くときに(DBのうち、正常引っ張っエンティティ)、私は危険なリフレッシュを持っていますあなただけの上で読んだメソッドを呼び出しボタン、:ここで
- (void)downloadContacts {
[[AppServer sharedInstance] getContactsForCurrentUser];
}
は応答のフォーマットです:
[
{
"created_at":"2013-01-11T14:03:57Z",
"email":"[email protected]",
"first_name":"John",
"id":2,
"last_name":"Doe",
"updated_at":"2013-02-07T10:57:16Z"
},
{
"created_at":"2013-01-11T14:03:57Z",
"email":"[email protected]",
"first_name":"Jane",
"id":3,
"last_name":"Doe",
"updated_at":"2013-02-07T10:57:16Z"
}
]
そして例外コンソールの前に、次の状態:
2013-02-08 22:40:36.892 App[66735:c07] I restkit:RKLog.m:34 RestKit logging initialized...
2013-02-08 22:40:36.994 App[66735:c07] SQLITE STORE PATH: ~/Library/Application Support/iPhone Simulator/6.0/Applications/D735548F-DF42-4E13-A7EF-53DF0C5D8F3B/Documents/AppModels.sqlite
2013-02-08 22:40:37.001 App[66735:c07] Context is ready!
2013-02-08 22:40:43.920 App[66735:c07] I restkit.network:RKHTTPRequestOperation.m:154 GET 'http://localhost:3000/contacts?auth_token=s78UFMq8mCQrr12GZcyx'
2013-02-08 22:40:43.945 App[66735:c07] I restkit.network:RKHTTPRequestOperation.m:181
全体の例外がスローされる前に、失敗したRestKitライブラリの行は、されています
NSAssert(self.managedObjectContext, @"Unable to perform mapping: No `managedObjectContext` assigned. (Mapping response.URL = %@)", self.response.URL);
私はそれをAppServerのinitServerメソッドに戻しました。m個のファイル、その、方法が戻る前に、RKObjectManagerクラスのプロパティは、このようなものです:私は、デバッグしているように、私は、問題はサーバ側または通信のではないことをトレースしてきましたhttp://imgur.com/LM5ZU9m
アプリケーション - JSONが受信され、配列にデシリアライズされたことがわかりますが、それがコアデータに保存されるはずの次のメソッドに渡された瞬間、管理されたオブジェクトコンテキストのNSAssertのためにアプリケーション全体がkaboomになります。
ご協力いただきありがとうございます。