web-dev-qa-db-fra.com

+ entityForName: nil n'est pas un paramètre légal de NSManagedObjectContext recherchant le nom d'entité 'Compte' '

J'ai essayé beaucoup d'options, mais je ne trouve pas la solution à ce problème. J'ai créé un fichier de données principal et nommé l'entité Compte, Créé un attribut de chaîne appelé nom d'utilisateur. Puis modifié la classe de l'entité en NSManagedObject, ne sachant pas si cela est correct. Maintenant, le code suivant est dans mon LoginViewController:

- (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]);

}

J'ai suivi Ce tutoriel et mes fichiers de code ressemblent à ceci:

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

Compte.h

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

@interface Account : AccountBase

@property (nonatomic, assign) NSString *password;

@end

Compte.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

Porte-clésHelper.h

#import <Foundation/Foundation.h>

@interface KeychainHelper : NSObject

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

@end

Porte-clés.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

Toute aide appréciée. Merci.

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

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

        managedObjectContext = [[NSManagedObjectContext alloc] init];
        [managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return managedObjectContext;
}
  • Vous n'avez pas fourni d'implémentation de chargement paresseux de persistentStoreCoordinator
  • alors coordinator sera toujours nil
  • donc vous retournerez toujours nil de cette méthode
  • ce qui signifie que vous aurez toujours l'erreur ci-dessus.

Pour expliquer l'erreur:

+ entityForName: nil n'est pas un paramètre légal de NSManagedObjectContext recherchant le nom d'entité 'Compte'

Ce n’est pas immédiatement évident de le lire, mais cela signifie que nil n’est pas une chose légale à passer pour le contexte de l’objet géré. En première lecture, on dirait que vous utilisez entityForName:nil mais ce n'est pas le cas. 

Pour résoudre le problème, vous devez fournir un coordinateur de magasin persistant valide. J'ai un petit article ici qui explique à quel point il vous faut peu de code pour configurer une pile de données principale, cela peut vous aider. 

37
jrturton

J'ai rencontré cette erreur entityForName: nil, mais cela a fini par être un peu un fil rouge qui ne s'est manifesté que lors de l'exécution de tests unitaires sur mon CI. Lors des tests, l'application rencontrait des conditions de threads étranges causées par L'importateur HTML de NSAttributedString . Une répartition asynchrone sur la file principale pour interagir avec Core Data se produisait au moment même où la variable NSAttributedString était créée à partir de HTML.

Il suffit de poster mon expérience ici au cas où cela aiderait quelqu'un d'autre. :)

0
tylermilner

Dans mon cas, j'utilise plusieurs contextes (parent/enfant) avec différents types de concurrence pour améliorer les performances. J'ai trois contextes:

  1. storeContext qui est le seul contexte pour lequel persistentStoreCoordinator a été défini.
  2. viewContext dont le parent est storeContext
  3. backgroundContext dont le parent aurait dû être viewContext mais J'ai oublié de définir backgroundContext.parent = viewContext

L'enregistrement d'une entité sur la backgroundContext a produit la même erreur ...

+ entityForName: nil n'est pas un paramètre légal de NSManagedObjectContext recherchant un nom d'entité ...

... parce que backgroundContext ne faisait pas partie de la chaîne de contexte parent/enfant. 

Définir backgroundContext 's parent sur viewContext a établi la chaîne de nouveau au coordinateur de magasin persistant et a corrigé l'erreur.

0
Clay Ellis