NSUnknownKeyException 错误原因:在 <ViewController 0x8a45930> 中存在未定义的键值对。setValue:forUndefinedKey:。

5

当我在iPhone模拟器上运行我的第一款“sqlite”应用程序时,出现了以下错误。 xcode没有问题,但是当我点击我的应用程序时,在调试窗口中会抛出错误。 我已经在这里放置了所有必要的代码,请帮助我连接“sqlite”并消除这些错误。

错误如下:

Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<ViewController 0x8a45930> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key departmentbox.'
*** First throw call stack:
(0x2091012 0x119ee7e 0x2119fb1 0xc4b711 0xbccec8 0xbcc9b7 0xbf7428 0x3030cc 0x11b2663 0x208c45a 0x301bcf 0x1c6e37 0x1c7418 0x1c7648 0x1c7882 0x116a25 0x116dbf 0x116f55 0x11ff67 0xe3fcc 0xe4fab 0xf6315 0xf724b 0xe8cf8 0x1fecdf9 0x1fecad0 0x2006bf5 0x2006962 0x2037bb6 0x2036f44 0x2036e1b 0xe47da 0xe665c 0x233d 0x2265)
libc++abi.dylib: terminate called throwing an exception
(lldb) 

DBManager.m:

//
//  DBManager.m
//  sqlite
//
//  Created by Techinfiniti on 14/05/14.
//  Copyright (c) 2014 Techinfiniti. All rights reserved.
//

#import "DBManager.h"
#import <sqlite3.h>

static DBManager *sharedInstance = nil;
static sqlite3 *database = nil;
static sqlite3_stmt *statement = nil;



@implementation DBManager

+(DBManager*)getSharedInstance{

    if(!sharedInstance){
        sharedInstance = [[super allocWithZone:NULL]init];
        [sharedInstance createDB];
    }
    return sharedInstance;
}

-(BOOL)createDB{

    NSString *docsDir;
    NSArray *dirPaths;

        dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
    docsDir = dirPaths[0];
    databasePath = [[NSString alloc] initWithString:[docsDir stringByAppendingPathComponent:@"student.db"]];
    BOOL isSuccess = YES;
    NSFileManager *filemgr = [NSFileManager defaultManager];

    if([filemgr fileExistsAtPath:databasePath]== NO)
    {
        const char *dbpath = [databasePath UTF8String];
        if(sqlite3_open(dbpath,&database)== SQLITE_OK )
        {
            char *errMsg;
            const char *sql_stmt = "create table if not exists studentsDetail (regno integer primary key, name text, department text, year text)";

            if(sqlite3_exec(database,sql_stmt,NULL,NULL,&errMsg)!= SQLITE_OK)
            {

                isSuccess = NO;
                NSLog(@"failed to open create table");
            }
            sqlite3_close(database);
            return isSuccess;
        }
        else{
            isSuccess = NO;
            NSLog(@"Failed to open/create database");
        }
    }return isSuccess;

}

-(BOOL)saveData:(NSString*)registerNumber name:(NSString*)name
     department:(NSString *)department year:(NSString *)year;
{
    const char *dbpath = [databasePath UTF8String];
    if(sqlite3_open(dbpath,&database)== SQLITE_OK )
    {
        NSString *insertSQL = [NSString stringWithFormat:@"insert into studentDetail(regno,name,department,year)values(\"%d\",\"%@\",\"%@\",\"%@\")",[registerNumber integerValue],name,department,year];
        const char *insert_stmt = [insertSQL UTF8String]; sqlite3_prepare_v2(database, insert_stmt,-1,&statement,NULL);



    if(sqlite3_step(statement) == SQLITE_DONE)
{
    return YES;
}
else{
    return NO;
}
sqlite3_reset(statement);
}
return NO;

}

-(NSArray*) findByRegisterNumber:(NSString *)registerNumber
{

    const char *dbpath = [databasePath UTF8String];
    if(sqlite3_open(dbpath,&database)== SQLITE_OK)
    {
        NSString *querySQL = [NSString stringWithFormat:@"select name, department,year from studentDetail where regno=\"%@\"",registerNumber];

        const char *query_stmt = [querySQL UTF8String];
        NSMutableArray *resultArray = [[NSMutableArray alloc]init];
        if(sqlite3_prepare_v2(database,query_stmt,-1,&statement,NULL)== SQLITE_OK)
        {
            if(sqlite3_step(statement) == SQLITE_ROW)
            {
                NSString *name = [[NSString alloc] initWithUTF8String:(const char *) sqlite3_column_text(statement, 0)];
                [resultArray addObject:name];

                NSString *department = [[NSString alloc]initWithUTF8String:(const char*) sqlite3_column_text(statement,1)];
                [resultArray addObject:department];
                return resultArray;

                 NSString *year = [[NSString alloc]initWithUTF8String:(const char*) sqlite3_column_text(statement,2)];
                [resultArray addObject:year];
                return resultArray;


            }
            else{
                NSLog(@"Not Found");
                return nil;
            }
            sqlite3_reset(statement);
        }

    }
    return nil;
}

@end

ViewController.h:

//
//  ViewController.h
//  sqlite
//
//  Created by Techinfiniti on 14/05/14.
//  Copyright (c) 2014 Techinfiniti. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "DBManager.h"

@interface ViewController : UIViewController<UITextFieldDelegate>
{
    IBOutlet UITextField *regNoTextField;
    IBOutlet UITextField *nameTextField;
    IBOutlet UITextField *departmentTextField;
    IBOutlet UITextField *yearTextField;
    IBOutlet UITextField *findByRegisterNumberTextField;
    IBOutlet UIScrollView *myScrollView;
}

-(IBAction)saveData:(id)sender;
-(IBAction)findData:(id)sender;


/*
- (IBAction)find:(id)sender;

- (IBAction)save:(id)sender;


@property (weak, nonatomic) IBOutlet UITextField *findbox;

@property (weak, nonatomic) IBOutlet UITextField *regnobox;

@property (weak, nonatomic) IBOutlet UITextField *namebox;

@property (weak, nonatomic) IBOutlet UITextField *departmentbox;

@property (weak, nonatomic) IBOutlet UITextField *year;
*/

@end

ViewController.m:

//
//  ViewController.m
//  sqlite
//
//  Created by Techinfiniti on 14/05/14.
//  Copyright (c) 2014 Techinfiniti. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{

    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];

    if(self)
    {


    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

/*
- (IBAction)find:(id)sender {
}

- (IBAction)save:(id)sender {
}

 */

-(IBAction)saveData:(id)sender{
    BOOL success = NO;
    NSString *alertString = @"Data Insertion falied";
    if(regNoTextField.text.length>0 && yearTextField.text.length>0 && departmentTextField.text.length>0 && yearTextField.text.length>0)
    {

        success = [[DBManager getSharedInstance]saveData:regNoTextField.text name:nameTextField.text department:departmentTextField.text year:yearTextField.text];
    }
    else
    {
        alertString = @"Enter all fields";
    }

    if(success == NO)
    {

        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:alertString message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
    }

}

-(IBAction)findData:(id)sender{

    NSArray *data = [[DBManager getSharedInstance]findByRegisterNumber:findByRegisterNumberTextField.text];

    if(data == nil)
    {

        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:
                              @"Data Not Found" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        [alert show];
        regNoTextField.text = @"";
        nameTextField.text = @"";
        departmentTextField.text = @"";
        yearTextField.text = @"";

    }
    else{

        regNoTextField.text = findByRegisterNumberTextField.text;
        nameTextField.text = [data objectAtIndex:0];
        departmentTextField.text = [data objectAtIndex:1];
        yearTextField.text = [data objectAtIndex:2];
    }


}


#pragma mark - Text field delegate

-(void)textFieldDidBeginEditing:(UITextField *)textField{

    [myScrollView setFrame:CGRectMake(10,50,300,200)];

}

-(BOOL) textFieldShouldReturn:(UITextField *)textField
{

    [textField resignFirstResponder];
    return YES;
}
@end
5个回答

18

你在 ViewController 中将属性 departmentbox 改为了 departmentTextField,但没有从 storyboard 中删除 departmentbox

前往连接检查器(Connection Inspector)删除未使用的键 department box,然后构建你的应用程序。

enter image description here

在这里,department boxReference Outlet 中显示,只需移除它并构建你的应用程序即可。


先生,请问在哪里可以找到 Inspector 属性? - Akash kumar
谢谢您帮助我,您能推荐一本iPhone开发的书吗? - Akash kumar
如果您需要任何帮助,请发送电子邮件至karthik.saral@gmail.com - Anbu.Karthik

1
你已经在IB中连接了名为“departmentbox”的UITextField。
@property (weak, nonatomic) IBOutlet UITextField *departmentbox;

但是之后你在视图控制器中注释了上述行。

当你尝试运行应用程序时,IB会在视图控制器中寻找“departmentbox”,这会导致崩溃。

断开IB中的“departmentbox”将解决此问题。


0

那是因为您在ViewController中将属性departmentbox重命名为departmentTextField,但显然忘记了更新storyboard。

此外,如果您不需要在.h文件中公开输出,则无需使用ivars来声明私有属性:

在您的.m中声明:

@interface UIViewController ()
@property (nonatomic, weak) IBOutlet UITextField *regNoTextField;
// etc
@end

0

这个错误通常在你的xib文件中关联了一个未知属性时出现。

如果你在xib关联之后重命名了一个属性,就可能会发生这种情况。

在这里,关联的属性是departmentbox,但被重命名为departmentTextField


先生,请建议我更改文件名的位置,我是 iPhone 的新手。 - Akash kumar
这是你的视图控制器关联的xib文件...或者故事板。如果你使用的是.xib,那么它将是ViewController.xib。 如果你使用的是故事板,那么它将是yourApp.storyboard。 - Martin

0
也许您在视图控制器中声明了一个名为“departmentbox”的iVar,创建了与该iVar的连接,并随后删除/重命名了此iVar,但忘记删除在xib文件中创建的连接。您可以检查视图控制器类的xib文件,看看是否有任何与departmentBox的连接。如果您看到这一点(在xib中的出口连接右侧显示一个小警告图标),只需删除该连接即可。

先生,我是Akash Jha,我对iPhone还不熟悉,请通过GML与我联系,我的GML账号是welkinakash5。 - Akash kumar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接