2013-12-09 7 views
14

Ho provato molte opzioni, ma non riesco a trovare la soluzione per questo problema. Ho creato un file di dati di base e ho chiamato l'account di entità, creato un attributo di stringa chiamato nome utente. Quindi ha modificato la classe dell'entità in NSManagedObject, non è sicuro se ciò è corretto. Ora, il seguente codice è nel mio LoginViewController:+ entityForName: nil non è un parametro NSManagedObjectContext legale che cerca il nome di entità 'Account' '

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    ITAppDelegate *appDelegate = (ITAppDelegate *)[[UIApplication sharedApplication] delegate]; 
    NSManagedObjectContext *context = appDelegate.managedObjectContext; 

    Account *newAccount = [NSEntityDescription insertNewObjectForEntityForName:@"Account" inManagedObjectContext:context]; 
    [newAccount setValue:@"Jorge" forKey:@"username"]; 
    [newAccount setPassword:@"password"]; 

    NSLog(@"username:%@ password: %@", [newAccount username], [newAccount password]); 

} 

ho seguito This Tutorial e il mio file di codice simile a questa:

ITAppDelegate.h

#import <UIKit/UIKit.h> 

@interface ITAppDelegate : UIResponder <UIApplicationDelegate> 

@property (strong, nonatomic) UIWindow *window; 

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

@end 

ITAppDelegate.m

#import "ITAppDelegate.h" 
#import "LoginViewController.h" 

@implementation ITAppDelegate 

@synthesize managedObjectContext = _managedObjectContext; 
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator; 
@synthesize managedObjectModel = _managedObjectModel; 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    // Override point for customization after application launch. 
    return YES; 
} 

#pragma mark - Core Data stack 

- (NSManagedObjectContext *)managedObjectContext 
{ 
if (_managedObjectContext != nil) 
{ 
    return _managedObjectContext; 
} 

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


- (NSManagedObjectModel *)managedObjectModel 
{ 
if (_managedObjectModel != nil) 
{ 
    return _managedObjectModel; 
} 
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Model" withExtension:@"momd"]; 
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 
return _managedObjectModel; 
} 


- (NSPersistentStoreCoordinator *)persistentStoreCoordinator 
{ 
if (_persistentStoreCoordinator != nil) 
{ 
    return _persistentStoreCoordinator; 
} 

    return _persistentStoreCoordinator; 
} 

@end 

AccountBase.h

#import <UIKit/UIKit.h> 
#import <CoreData/CoreData.h> 

@interface AccountBase : NSManagedObject 

@property (nonatomic, retain) NSString *username; 


@end 

AccountBase.m

#import "AccountBase.h" 

@implementation AccountBase 

@dynamic username; 

@end 

Account.h

#import "AccountBase.h" 
#import <CoreData/CoreData.h> 

@interface Account : AccountBase 

@property (nonatomic, assign) NSString *password; 

@end 

Account.m

#import "Account.h" 
#import "KeychainHelper.h" 

@implementation Account 

- (NSString*)password 
{ 
    if (self.username) 
     return [KeychainHelper getPasswordForKey:self.username]; 
    return nil; 
} 

- (void)setPassword:(NSString*)aPassword 
{ 
    if (self.username) 
     [KeychainHelper setPassword:aPassword forKey:self.username]; 
} 

- (void)prepareForDeletion 
{ 
    if (self.username) 
     [KeychainHelper removePasswordForKey:self.username]; 
} 
@end 

KeychainHelper.h

#import <Foundation/Foundation.h> 

@interface KeychainHelper : NSObject 

+ (NSString*)getPasswordForKey:(NSString*)aKey; 
+ (void)setPassword:(NSString*)aPassword forKey:(NSString*)aKey; 
+ (void)removePasswordForKey:(NSString*)aKey; 

@end 

KeychainHelper.m

#import "KeychainHelper.h" 
#import <Security/Security.h> 

@interface KeychainHelper() 
+ (NSMutableDictionary*)dictionaryForKey:(NSString*)aKey; 
@end 

@implementation KeychainHelper 


static const NSString *ironTrainers = @"com.domain.myapplication"; 

+ (NSMutableDictionary*)dictionaryForKey:(NSString*)aKey 
{ 
    NSData *encodedKey = [aKey dataUsingEncoding:NSUTF8StringEncoding]; 

    NSMutableDictionary *searchDictionary = [NSMutableDictionary dictionary]; 

    [searchDictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass]; 
    [searchDictionary setObject:encodedKey forKey:(__bridge id)kSecAttrGeneric]; 
    [searchDictionary setObject:encodedKey forKey:(__bridge id)kSecAttrAccount]; 
    [searchDictionary setObject:ironTrainers forKey:(__bridge id)kSecAttrService]; 

    return searchDictionary; 
} 

+ (NSString*)getPasswordForKey:(NSString*)aKey 
{ 
    NSString *password = nil; 

    NSMutableDictionary *searchDictionary = [self dictionaryForKey:aKey]; 
    [searchDictionary setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit]; 
    [searchDictionary setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData]; 

    CFTypeRef result = NULL; 
    BOOL statusCode = SecItemCopyMatching((__bridge CFDictionaryRef)searchDictionary, &result); 
    if (statusCode == errSecSuccess) { 
     NSData *resultData = CFBridgingRelease(result); 
     password = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding]; 
    } 
    return (__bridge NSString *)(result); 
} 

+ (void)removePasswordForKey:(NSString*)aKey 
{ 
    NSMutableDictionary *keyDictionary = [self dictionaryForKey:aKey]; 
    SecItemDelete((__bridge CFDictionaryRef)keyDictionary); 
} 

+ (void)setPassword:(NSString*)aPassword forKey:(NSString*)aKey 
{ 
    [KeychainHelper removePasswordForKey:aKey]; 

    NSData *encodedPassword = [aPassword dataUsingEncoding:NSUTF8StringEncoding]; 

    NSMutableDictionary *keyDictionary = [self dictionaryForKey:aKey]; 
    [keyDictionary setObject:encodedPassword forKey:(__bridge id)kSecValueData]; 
    SecItemAdd((__bridge CFDictionaryRef)keyDictionary, nil); 
} 

@end 

Qualsiasi aiuto apprezzato. Grazie.

risposta

34
- (NSManagedObjectContext *)managedObjectContext 
{ 
    if (managedObjectContext != nil) return managedObjectContext; 

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
    if (coordinator != nil) { 

     managedObjectContext = [[NSManagedObjectContext alloc] init]; 
     [managedObjectContext setPersistentStoreCoordinator:coordinator]; 
    } 
    return managedObjectContext; 
} 
  • Non hai fornito un'implementazione lazy loading di persistentStoreCoordinator
  • così coordinator sarà sempre nil
  • modo sarete sempre ritornando nil da questo metodo
  • che significa che sarà sempre ottenere l'errore sopra.

Per spiegare l'errore:

+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'Account'

Non è immediatamente evidente dalla lettura, ma questo significa che nil non è una cosa legale di passare per il contesto oggetto gestito. In prima lettura, sembra che tu stia facendo entityForName:nil ma non è questo il caso.

Per risolvere il problema, è necessario fornire un coordinatore di negozio permanente valido. Ho un piccolo articolo here che spiega quanto poco codice è necessario per impostare uno stack di dati di base, questo può aiutare.

+0

Grazie, ha funzionato per il nome utente. Ho cambiato delegato app (vedere sopra), ma ora sto ricevendo l'errore: - [NSManagedObject setPassword:]: selettore non riconosciuto inviato all'istanza – ferrojr

+0

Bene, questa è una domanda completamente diversa. Sembra che tu non abbia definito la sottoclasse appropriata nel tuo modello di dati (c'è una casella "Nome" e "Classe" da compilare) – jrturton

+0

Il mio modello di dati ha un attributo che è un nome utente. E il nome dell'entità è Account, la classe che mostra che c'è NSManagedObject, che ho modificato in precedenza, non è sicuro che sia corretto. – ferrojr

-1

Potrebbe verificarsi a causa della mancata corrispondenza tra il nome dell'entità e il nome della classe. Assicurati che l'entità Account abbia un nome di classe appropriato nel file .xcdatamodeld.

+3

Il messaggio di errore indica che il parametro managedObjectContext è nullo, questo non ha nulla a che fare con il modello – jrturton