我很愚蠢,没有在编程时不断地测试,所以现在我不确定错误是从哪里出现的。我正在开发一个可编程计算器。当我运行时,它在显示任何内容之前崩溃并给我这个消息:
*** 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
一如既往,感谢您的帮助。