ios +entityForName:nil 不是合法的 NSManagedObjectContext 参数搜索实体名称“Account”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20472465/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'Account''
提问by ferrojr
I have tried a lot of options, but can't find the solution for this problem. I created a Core Data file and named the entity Account, Created an string attribute called username. Then edited the class of the entity to NSManagedObject, not sure if this is right. Now, the following code is in my LoginViewController:
我尝试了很多选择,但找不到解决此问题的方法。我创建了一个 Core Data 文件并将实体命名为 Account,创建了一个名为 username 的字符串属性。然后将实体的类编辑为NSManagedObject,不知道这样对不对。现在,以下代码在我的 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]);
}
I followed This Tutorialand my code files look like this:
我遵循了本教程,我的代码文件如下所示:
ITAppDelegate.h
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
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
账户库.h
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
@interface AccountBase : NSManagedObject
@property (nonatomic, retain) NSString *username;
@end
AccountBase.m
AccountBase.m
#import "AccountBase.h"
@implementation AccountBase
@dynamic username;
@end
Account.h
账户.h
#import "AccountBase.h"
#import <CoreData/CoreData.h>
@interface Account : AccountBase
@property (nonatomic, assign) NSString *password;
@end
Account.m
帐户.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
钥匙串助手.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
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
Any help appreciated. Thanks.
任何帮助表示赞赏。谢谢。
回答by jrturton
- (NSManagedObjectContext *)managedObjectContext
{
if (managedObjectContext != nil) return managedObjectContext;
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
managedObjectContext = [[NSManagedObjectContext alloc] init];
[managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return managedObjectContext;
}
- You haven't provided a lazy loading implementation of
persistentStoreCoordinator
- so
coordinator
will always benil
- so you will always be returning
nil
from this method - which means you will always get the error above.
- 您还没有提供延迟加载实现
persistentStoreCoordinator
- 所以
coordinator
永远都是nil
- 所以你总是会
nil
从这个方法返回 - 这意味着您将始终收到上述错误。
To explain the error:
要解释错误:
+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'Account'
+entityForName:nil 不是合法的 NSManagedObjectContext 参数搜索实体名称“Account”
It's not immediately obvious from reading it, but this means that nil
is not a legal thing to pass for the managed object context. On first reading, it looks like you're doing entityForName:nil
but that isn't the case.
阅读它并不是很明显,但这意味着将nil
其传递给托管对象上下文是不合法的。初读时,您似乎正在这样做,entityForName:nil
但事实并非如此。
To fix the problem, you will need to provide a valid persistent store coordinator. I have a small article herewhich explains just how little code you need to set up a core data stack, this may help you.
要解决此问题,您需要提供有效的持久存储协调器。我在这里有一篇小文章,它解释了设置核心数据堆栈所需的代码很少,这可能会对您有所帮助。
回答by Clay Ellis
In my case, I'm using multiple contexts (parent/child) with different concurrency types to improve performance. I have three contexts:
就我而言,我使用具有不同并发类型的多个上下文(父/子)来提高性能。我有三个上下文:
storeContext
which is the only context whosepersistentStoreCoordinator
had been set.viewContext
whose parent isstoreContext
backgroundContext
whose parent should have beenviewContext
but I forgot to setbackgroundContext.parent = viewContext
.
storeContext
这是唯一persistentStoreCoordinator
已设置的上下文。viewContext
谁的父母是storeContext
backgroundContext
谁的父母应该是,viewContext
但我忘了设置backgroundContext.parent = viewContext
。
Saving an entity on the backgroundContext
produced the same error...
将实体保存在backgroundContext
产生相同的错误上...
+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name...
+entityForName: nil 不是合法的 NSManagedObjectContext 参数搜索实体名称...
...because backgroundContext
wasn't a part of the parent/child context chain.
...因为backgroundContext
不是父/子上下文链的一部分。
Setting backgroundContext
's parent
to viewContext
established the chain back to the persistent store coordinator and resolved the error.
设置backgroundContext
'sparent
以viewContext
建立返回持久存储协调器的链并解决错误。
回答by tylermilner
I encountered this entityForName: nil
error, but it ended up being somewhat of a red herring that only manifested itself when running unit tests on my CI. During testing, the app was encountering some weird threading conditions caused by NSAttributedString's HTML Importer. An asynchronous dispatch onto the main queue to interact with Core Data was happening just as the NSAttributedString
was being created from HTML.
我遇到了这个entityForName: nil
错误,但它最终有点像红鲱鱼,只有在我的 CI 上运行单元测试时才会出现。在测试期间,该应用程序遇到了由NSAttributedString 的 HTML Importer引起的一些奇怪的线程条件。异步调度到主队列以与 Core Data 交互,就像NSAttributedString
从 HTML 创建一样。
Just posting my experience here in case it ends up helping someone else. :)
只是在这里发布我的经验,以防它最终帮助其他人。:)
回答by Gurjinder Singh
I encountered the same error while fetching data from Core Data. The reason was value to context object was not set properly and It was setting to it after fetching the result. So, setting context properly before hitting fetch request makes the work done.
我在从 Core Data 获取数据时遇到了同样的错误。原因是上下文对象的值设置不正确,它在获取结果后设置了它。因此,在点击获取请求之前正确设置上下文可以完成工作。
回答by Zend
It might happens because of mismatch of entity name and its class name. Ensure that your Account entity has an appropriate class name in .xcdatamodeld file.
这可能是由于实体名称与其类名称不匹配而发生的。确保您的 Account 实体在 .xcdatamodeld 文件中具有适当的类名。