2013-12-09 12 views
14

Tôi đã thử rất nhiều tùy chọn, nhưng không thể tìm thấy giải pháp cho vấn đề này. Tôi tạo ra một tập tin dữ liệu cốt lõi và đặt tên là tài khoản thực thể, tạo ra một thuộc tính chuỗi gọi là tên người dùng. Sau đó, chỉnh sửa lớp của thực thể thành NSManagedObject, không chắc chắn nếu điều này là đúng. Bây giờ, các mã sau đây là trong LoginViewController tôi:+ entityForName: nil không phải là tham số hợp pháp NSManagedObjectContext tìm kiếm tên thực thể 'Tài khoản' '

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

} 

Tôi đi theo This Tutorial và các tập tin mã của tôi trông như thế này:

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 

Bất kỳ trợ giúp nào được đánh giá cao. Cảm ơn.

Trả lời

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

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

     managedObjectContext = [[NSManagedObjectContext alloc] init]; 
     [managedObjectContext setPersistentStoreCoordinator:coordinator]; 
    } 
    return managedObjectContext; 
} 
  • Bạn chưa cung cấp thực hiện tải lười biếng của persistentStoreCoordinator
  • nên coordinator sẽ luôn luôn được nil
  • vì vậy bạn sẽ luôn luôn được trở nil từ phương pháp này
  • có nghĩa là bạn sẽ luôn nhận được lỗi ở trên.

Để giải thích các lỗi:

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

Nó không phải ngay lập tức rõ ràng từ việc đọc nó, nhưng điều này có nghĩa rằng nil không phải là một điều hợp pháp để vượt qua đối với bối cảnh đối tượng quản lý. Khi đọc lần đầu, có vẻ như bạn đang thực hiện entityForName:nil nhưng không phải như vậy.

Để khắc phục sự cố, bạn cần cung cấp điều phối viên lưu trữ liên tục hợp lệ. Tôi có một bài viết nhỏ here giải thích bạn chỉ cần ít mã để thiết lập một ngăn xếp dữ liệu lõi, điều này có thể giúp bạn.

+0

Cảm ơn, nó đã hoạt động đối với tên người dùng. Tôi đã thay đổi ủy nhiệm ứng dụng (vui lòng xem ở trên), nhưng bây giờ tôi nhận được lỗi: - [NSManagedObject setPassword:]: bộ chọn không nhận dạng được gửi đến dụ – ferrojr

+0

Vâng, đó là một câu hỏi hoàn toàn khác. Có vẻ như bạn chưa xác định đúng lớp con trong mô hình dữ liệu của mình (có hộp "Tên" và "Lớp" để điền vào) – jrturton

+0

Mô hình dữ liệu của tôi có một thuộc tính là tên người dùng. Và tên thực thể là Tài khoản, lớp hiển thị có NSManagedObject, mà tôi đã chỉnh sửa trước đó, không chắc chắn liệu điều đó có đúng hay không. – ferrojr

-1

Điều này có thể xảy ra do không khớp tên thực thể và tên lớp của nó. Đảm bảo rằng thực thể Tài khoản của bạn có tên lớp thích hợp trong tệp .xcdatamodeld.

+3

Thông báo lỗi cho biết tham số managedObjectContext là không, không liên quan gì đến mô hình – jrturton

Các vấn đề liên quan