2013-02-08 16 views
7

मैं अपने डिप्लोमा परियोजना है, जो एक कोर डाटा डेटाबेस और एक रूबी ऑन रेल्स सर्वर के साथ एक iOS ग्राहक भी शामिल है पर काम कर रहा हूँ में नहीं के बराबर है। मैं उनके बीच संचार के लिए RestKit का उपयोग कर रहा हूँ। वर्तमान में मैं एक बड़ा मुद्दा पूरी व्यवस्था हो रही है काम करने के लिए हो रही है: के रूप में मैं सर्वर से वस्तुओं के लिए एक प्रतिक्रिया मैप करने के लिए प्रयास करते हैं, मैं निम्न अपवाद:RestKit दुर्घटनाओं क्योंकि NSManagedObjectContext RKResponseMapperOperation

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 

उपयोगकर्ता वर्ग बिल्कुल स्पष्ट है, स्वत: जनरेट 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 विधि से पालन किया है।मीटर फ़ाइल है, जो, में विधि रिटर्न से पहले, RKObjectManager वर्ग के गुणों इस तरह हैं: http://imgur.com/LM5ZU9m

जैसा कि मैंने डीबग है, मैं पता लगाया है कि समस्या सर्वर साइड या के संचार के साथ नहीं है ऐप - मैं जेएसओएन को एक सरणी में प्राप्त और deserialized देख सकते हैं, लेकिन जिस क्षण यह अगली विधि को पास किया गया है जिसे कोर डेटा में सहेजना है, पूरा ऐप प्रबंधित ऑब्जेक्ट संदर्भ के एनएसएएसएसर्ट की वजह से कबाम चला जाता है।

किसी भी मदद की बहुत सराहना की जाती है!

उत्तर

4

डिबगिंग के कुछ दिनों के बाद, मुझे अंत में पता चला कि क्या गलत हुआ: ऐसा लगता है कि मुझे अपने स्थानीय दृढ़ता स्टोर में पथ भी सेट करना था और प्रबंधित ऑब्जेक्ट स्टोर के लिए प्रबंधित ऑब्जेक्ट संदर्भ उत्पन्न करना था।

यहाँ है जहाँ मैं समाधान नहीं मिला: https://github.com/RestKit/RestKit/issues/1221#issuecomment-13327693

मैं सिर्फ अपने सर्वर init विधि की कुछ पंक्तियों में जोड़ दिया है: इस समारोह RKApplicationDataDirectory() का उपयोग कर आवेदन प्राप्त करने के लिए

NSError *error = nil; 
NSString *pathToPSC = [[AppDataModel sharedDataModel] pathToLocalStore]; 

_objectManager.managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:[[AppDataModel sharedDataModel] managedObjectModel]]; 
[_objectManager.managedObjectStore addSQLitePersistentStoreAtPath:pathToPSC fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error]; 

if (error != nil) { 
    NSLog(@"\nSerious object store error!\n"); 
    return; 
} else { 
    [_objectManager.managedObjectStore createManagedObjectContexts]; 
} 
2

मैं यह कर में कामयाब निर्देशिका और मेरा डेटाबेस पथ सेट करें।

// Initialize HTTPClient 
NSURL *baseURL = [NSURL URLWithString:@"http://myapiaddress.com"]; 
AFHTTPClient* client = [[AFHTTPClient alloc] initWithBaseURL:baseURL]; 
//we want to work with JSON-Data 
[client setDefaultHeader:@"Accept" value:RKMIMETypeJSON]; 

// Initialize RestKit 
RKObjectManager *objectManager = [[RKObjectManager alloc] initWithHTTPClient:client]; 
NSURL *modelURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"NameOfMyCoreDataModel" ofType:@"momd"]]; 

//Iniitalize CoreData with RestKit 
NSManagedObjectModel *managedObjectModel = [[[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL] mutableCopy]; 
RKManagedObjectStore *managedObjectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:managedObjectModel]; 
NSError *error = nil; 

NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"nameOfDB.sqlite"]; 

objectManager.managedObjectStore = managedObjectStore; 

[objectManager.managedObjectStore addSQLitePersistentStoreAtPath:path fromSeedDatabaseAtPath:nil withConfiguration:nil options:nil error:&error]; 

[objectManager.managedObjectStore createManagedObjectContexts];