键值编码合规性

时间:2012-07-30 18:29:21

标签: objective-c ios5 xcode4.3 key-value

我是愚蠢的,没有按照我的编程不断测试,所以现在我不确定错误在哪里悄悄进入。我正在研究可编程计算器。当我跑步时,它会在显示任何内容之前崩溃并给我这样的信息:

*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<CalculatorViewController 0x6a405a0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key description.'

我会使用NSLog来查找错误,但是在崩溃发生之前我不知道在哪里尝试它。关于我做错了什么的想法?

这是CalculatorViewController.m,为未完成的注释掉的代码添加了一些额外的属性声明,我省略了:

#import "CalculatorViewController.h"
#import "CalculatorBrain.h"

@interface CalculatorViewController ()
@property (nonatomic) BOOL userIsEnteringNumber;
@property (nonatomic) BOOL numberIsNegative;
@property (nonatomic,strong) CalculatorBrain *brain;
@end

@implementation CalculatorViewController
@synthesize display = _display;
@synthesize descriptionLabel = _descriptionLabel;
@synthesize userIsEnteringNumber = _userIsEnteringNumber;
@synthesize numberIsNegative;
@synthesize brain = _brain;


-(CalculatorBrain *)brain
{
if (!_brain) _brain = [[CalculatorBrain alloc] init];
return _brain;
}


//This adds a pressed digit to the display label.

- (IBAction)digitPressed:(UIButton *)sender 
{
NSString *digit = sender.currentTitle;

//Enter digit if it wouldn't create a two-decimal-point case.
NSRange range = [self.display.text rangeOfString:@"."];
if (range.location==NSNotFound || (![digit isEqualToString:@"."]))
    if (self.userIsEnteringNumber)
    {
        self.display.text = [self.display.text stringByAppendingString:digit];
        self.descriptionLabel.text = [self.display.text stringByAppendingString:@" "];
    }
    else 
    {
        self.descriptionLabel.text = [self.descriptionLabel.text stringByAppendingString:digit];
        self.descriptionLabel.text = [self.descriptionLabel.text stringByAppendingString:@" "];
        if (![sender.currentTitle isEqualToString:@"."])
        {
            self.display.text = digit;
        }
        else 
        {
            self.display.text = @"0.";
        }
        self.userIsEnteringNumber = YES;
    }
}


//This sets up an operation.

- (IBAction)operationPressed:(UIButton *)sender 
{
if (self.userIsEnteringNumber) [self enterPressed];
NSString *operation = sender.currentTitle;
double result = [self.brain performOperation:operation];
self.display.text = [NSString stringWithFormat:@"%g",result];
{
    NSString *descr = [self.brain description];
    self.descriptionLabel.text = descr;
}
}


- (IBAction)enterPressed 
{
NSCharacterSet *set = [NSCharacterSet decimalDigitCharacterSet];
NSRange range = [self.display.text rangeOfCharacterFromSet:set];
if (range.location==NSNotFound)
{
    [self.brain pushOperandAsVariable:self.display.text];
}
else 
{
    [self.brain pushOperand:[self.display.text doubleValue]];        
}

self.userIsEnteringNumber = NO;
}

@end

这里是CalculatorBrain.m:

#import "CalculatorBrain.h"

@interface CalculatorBrain()
@property (nonatomic, strong) NSMutableArray *programStack;
@property (nonatomic,strong)NSDictionary *variableValues;
@end

@implementation CalculatorBrain

@synthesize programStack = _programStack;
@synthesize variableValues = _variableValues;

- (NSMutableArray *)programStack
{
if (!_programStack) _programStack = [[NSMutableArray alloc] init];
return _programStack;
}

- (id)program
{
return [self.programStack copy];
}


//Here are the two types of pushes that the ViewController can implement.  First, operand pushes . . . 

- (void)pushOperand:(double)operand
{
[self.programStack addObject:[NSNumber numberWithDouble:operand]];
}


//. . . and then variable pushes.

- (void) pushOperandAsVariable:(NSString *)variable
{
//Create dictionary
//Move this later on to ViewController but for now leave where it is....
NSMutableArray *variablesUsed = [[NSMutableArray alloc] init];
NSArray *objects = [[NSArray alloc] initWithObjects:[NSNumber numberWithDouble:3],[NSNumber numberWithDouble:4.1],[NSNumber numberWithDouble:-6],[NSNumber numberWithDouble:4.5298], [NSNumber numberWithDouble:3.14159], nil];
NSArray *keys = [[NSArray alloc] initWithObjects:@"x",@"y",@"z",@"foo", @"π", nil];
NSDictionary *variableValues = [[NSDictionary alloc] initWithObjects:objects forKeys:keys];

//Check program for keys
    NSNumber *operand;
for (int i=0; i<keys.count; i++)
{
    if ([[keys objectAtIndex:i] isEqual:variable])
        [variablesUsed addObject:variable];
    operand = [variableValues objectForKey:variable];
}
[self.programStack addObject:operand];
}

- (double)performOperation:(NSString *)operation
{
[self.programStack addObject:operation];
return [[self class] runProgram:self.program];
}

+ (double)popOffStack:(NSMutableArray *)stack
{
double result = 0;
id topOfStack = [stack lastObject];
if (topOfStack) [stack removeLastObject];
if ([topOfStack isKindOfClass:[NSNumber class]])
{
    result = [topOfStack doubleValue];
}

//Here are the results for various operations.

else if ([topOfStack isKindOfClass:[NSString class]])
{
    NSString *operation = topOfStack;
    if ([operation isEqualToString:@"+"]) 
    {
        result = [self popOffStack:stack] +
        [self popOffStack:stack];
    } 
    else if ([@"*" isEqualToString:operation]) 
    {
        result = [self popOffStack:stack] *
        [self popOffStack:stack];
    } 
    else if ([operation isEqualToString:@"-"]) 
    {
        double subtrahend = [self popOffStack:stack];
        result = [self popOffStack:stack] - subtrahend;
    } 
    else if ([operation isEqualToString:@"/"]) 
    {
        double divisor = [self popOffStack:stack];
        if (divisor) result = [self popOffStack:stack] / divisor;
    }
    else if ([operation isEqualToString:@"sin"])
    {
        result = sin([self popOffStack:stack]);
    }
    else if ([operation isEqualToString:@"cos"])
    {
        result = cos([self popOffStack:stack]);
    }
    else if ([operation isEqualToString:@"√"])
    {
        result = sqrt([self popOffStack:stack]);
    }
    else if ([operation isEqualToString:@"π"])
    {
        result = M_PI;
    }
}
return result;
}

+ (double)runProgram:(id)program
{
//Run program.
NSMutableArray *mutableCopyOfProgram;
if ([program isKindOfClass:[NSArray class]]) 
{
    mutableCopyOfProgram = [program mutableCopy];

return [self popOffStack:mutableCopyOfProgram];
}
else return 0;
}

@end

一如既往,感谢您的帮助。

1 个答案:

答案 0 :(得分:3)

最常见的原因是您在故事板或xib文件中定义了CalculatorViewController对象,并且图形界面中的某些内容具有指向其上名为“description”的插座的链接。同时,您在该类的代码中不再有description个插座。

这通常可以通过在界面构建器中跟踪杂散引用并删除它来解决。