I can not figure out how to resolve SIGABRT error in Xcode - objective-c

I am working on a basic calculator app, following a tutorial for an iTunes U class. I thought I had worked it out perfectly but when I go to run the application in the simulator, I get an unexpected error. The calculator works by entering the number, pressing the enter button, entering the second number, then the enter button and then the operation. It allows me to append digits to form a multi-digit number, but as soon as I press "enter" it quits out and says "Thread 1: Program received signal: "SIGABRT."" I have double and triple checked my code and cannot seem to find anything wrong, so i thought i would post it all on here and see if you guys can figure it out. Thanks in advance!
CalculatorBrain.h
#import <Foundation/Foundation.h>
#interface CalculatorBrain : NSObject
- (void)pushOperand:(double)operand;
- (double)performOperation:(NSString *)operation;
#end
CalculatorBrain.m
#import "CalculatorBrain.h"
#interface CalculatorBrain()
#property (nonatomic, strong) NSMutableArray *operandStack;
#end
#implementation CalculatorBrain
#synthesize operandStack = _operandStack;
- (NSMutableArray *)operandStack
{
if (!_operandStack) {
_operandStack = [[NSMutableArray alloc] init];
}
return _operandStack;
}
- (void)pushOperand:(double)operand
{
NSNumber *operandObject = [NSNumber numberWithDouble:operand];
[self.operandStack addObject:operandObject];
}
- (double)popOperand
{
NSNumber *operandObject = [self.operandStack lastObject];
if (operandObject) [self.operandStack removeLastObject];
return [operandObject doubleValue];
}
- (double)performOperation:(NSString *)operation
{
double result = 0;
if ([operation isEqualToString:#"+"]){
result = [self popOperand] + [self popOperand];
} else if ([#"*" isEqualToString:operation]) {
result = [self popOperand] * [self popOperand];
} else if ([operation isEqualToString:#"-"]) {
double subtrahend = [self popOperand];
result = [self popOperand] - subtrahend;
} else if ([operation isEqualToString:#"/"]) {
double divisor = [self popOperand];
if (divisor) result = [self popOperand] / divisor;
}
[self pushOperand:result];
return result;
}
#end
CalculatorViewController.h
#import <UIKit/UIKit.h>
#interface CalculatorViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *display;
#end
CalculatorViewController.m
#import "CalculatorViewController.h"
#import "CalculatorBrain.h"
#interface CalculatorViewController()
#property (nonatomic) BOOL userIsInTheMiddleOfEnteringANumber;
#property (nonatomic, strong) CalculatorBrain *brain;
#end
#implementation CalculatorViewController
#synthesize display;
#synthesize userIsInTheMiddleOfEnteringANumber;
#synthesize brain = _brain;
- (CalculatorBrain *)brain
{
if(!_brain) _brain = [[CalculatorBrain alloc] init];
return _brain;
}
- (IBAction)digitPressed:(UIButton *)sender {
NSString *digit = [sender currentTitle];
if (self.userIsInTheMiddleOfEnteringANumber) {
self.display.text = [self.display.text stringByAppendingString:digit];
} else {
self.display.text = digit;
self.userIsInTheMiddleOfEnteringANumber = YES;
}
}
- (IBAction)enterPressed
{
[self.brain pushOperand:[self.display.text doubleValue]];
self.userIsInTheMiddleOfEnteringANumber = NO;
}
- (IBAction)operationPressed:(UIButton *)sender
{
if (self.userIsInTheMiddleOfEnteringANumber) {
[self enterPressed];
}
NSString *operation = [sender currentTitle];
double result = [self.brain performOperation:operation];
self.display.text = [NSString stringWithFormat:#"%g", result];
}
#end

Open CalculatorViewController.xib file in Xcode and right-click the "File's Owner".
Check the appearing pop-up if you have any linked properties listed that are not implemented in the CalculatorViewController.h file (according to the above posted code, the only properties linked from .xib to .h should be a UILabel called "display". Delete all invalid linked properties, if any is available (invalid linked properties would be marked with a yellow warning sign).

Expand your project Executable and right click on it. and click on GetInfo->Argument tag aat end of the window you see plus and minus sign button click on + sighn button and write
Name Value
NSZombieEnabled YES
then after execute your project and whenever crash your application click on run munu-> console you see there why your application crash. please try this may be this will help you.

Related

Information in text fields do not get retained objective c

This is a simple program that takes two numbers inputed by the user in two separate text fields and adds them together when the 'Add' button is clicked. The way I have done this is by subclassing NSTextField into a class called MyTextField. I believe my error has something to do with memory leaks, but being an inexperienced programmer, I'm not quite sure how to deal with allocating and deallocating memory.
The problem is: When I click the Add button, it works perfectly. However, when I click it again, it does not show the correct amount. It keeps taking my inputs as nil and outputting 0. I have attached my code.
Note: I know that this is much more complicate than it needs to be! I am simply showing a simpler version of a much more complicated program that displays the exact same error.
MyTextField.h
#import <Cocoa/Cocoa.h>
#interface MyTextField : NSTextField
#property (strong) NSString* number;
#property double dblNum;
-(id)initWithNumber:(NSString *)number;
-(NSString *)getNumber;
-(void)setNumber;
-(double)getDblNum;
-(void)setDblNum;
-(double)calcSum:(MyTextField *)other;
-(NSString *)description;
#end
MyTextField.m
#import "MyTextField.h"
#implementation MyTextField
-(id)initWithNumber:(NSString *)number{
self = [super init];
if (self) {
if ([number length] > 0){
_number = number;
}else{
_number = #"0";
}
[self setDblNum];
}
return self;
}
- (id)init {
return [self initWithNumber:[self getNumber]];
}
-(NSString *)getNumber{
return _number;
}
-(void)setNumber{
_number = [self stringValue];
}
-(double)getDblNum{
return _dblNum;
}
-(void)setDblNum{
_dblNum = [_number doubleValue];
}
-(double)calcSum:(MyTextField *)other{
return [self getDblNum] + [other getDblNum];
}
- (NSString *)description{
return [NSString stringWithFormat: #"Number: %f", _dblNum];
}
#end
ViewController.h
#import <Cocoa/Cocoa.h>
#import "MyTextField.h"
#interface ViewController : NSViewController
#property (strong) IBOutlet MyTextField *valueOne;
#property (strong) IBOutlet MyTextField *valueTwo;
#property (strong) IBOutlet NSTextField *answer;
- (IBAction)btnAdd:(id)sender;
#end
ViewController.m
#import "ViewController.h"
#import "MyTextField.h"
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
}
- (IBAction)btnAdd:(id)sender {
_valueOne = [[MyTextField alloc] initWithNumber:[_valueOne stringValue]];
_valueTwo = [[MyTextField alloc] initWithNumber:[_valueTwo stringValue]];
double ans = [_valueOne calcSum:_valueTwo];
_answer.stringValue = [NSString stringWithFormat:#"%.2f", ans];
}
#end
P.S. Sorry for the annoying amount of code. Thanks!
Your btnAdd: is where the problem is.
- (IBAction)btnAdd:(id)sender {
_valueOne = [[MyTextField alloc] initWithNumber:[_valueOne stringValue]];
_valueTwo = [[MyTextField alloc] initWithNumber:[_valueTwo stringValue]];
double ans = [_valueOne calcSum:_valueTwo];
_answer.stringValue = [NSString stringWithFormat:#"%.2f", ans];
}
Each time the button is tapped, you're recreating both MyTextField instances. Instead, you simply need to get & set the values from your existing valueOne and valueTwo outlets, like:
- (IBAction)btnAdd:(id)sender {
double value1 = [_valueOne.text doubleValue];
double value2 = [_valueTwo.text doubleValue];
double ans = value1 + value2;
_answer.stringValue = [NSString stringWithFormat:#"%.2f", ans];
}
Obviously, you need to check the validity of the valueOne and valueTwo text strings.
You really don't need a MyTextField subclass, because it's not doing anything except converting strings to doubles (and vice versa).

Objective C newbie, one method can change UI elements, others can not

thanks in advance for any input. I have been trying to write a program that interprets a serial command into text change in a label. I can change the label text easily with an Action attached to a button, but for some reason all my attempts at changing the label text outside that button action result in nothing being changed.
// MasterViewController.m
//
// Created by Daniel Payne on 2/28/15.
// Copyright (c) 2015 Daniel Payne. All rights reserved.
//
#import "MasterViewController.h"
#interface MasterViewController ()
#property (strong) IBOutlet NSTextField *score;
#property (nonatomic, strong) ORSSerialPort *serialPort;
#property (nonatomic, strong) MasterViewController *masterView;
#end
static MasterViewController *serialPortHelper = nil;
void connectPort(void) {
ORSSerialPort *serialPort = [ORSSerialPort serialPortWithPath:#"/dev/tty.usbmodem1411"];
serialPortHelper = [[MasterViewController alloc] init];
serialPortHelper.serialPort = serialPort;
serialPort.delegate = serialPortHelper;
serialPort.baudRate = #9600;
NSLog(#"port open");
[serialPort open];
}
int main(int argc, const char * argv[]) {
connectPort();
return NSApplicationMain(argc, argv);
}
#implementation MasterViewController
- (IBAction)pushButton:(id)sender {
[self.score setStringValue:#"1"]; //works
}
- (void)viewDidLoad {
[super viewDidLoad];
}
-(void)awakeFromNib
{
NSLog(#"View controller instance with view: %#", self.view);
}
- (void)serialPort:(ORSSerialPort *)serialPort didReceiveData:(NSData *)data
{
NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if ([string rangeOfString:#"g"].location == NSNotFound) {
NSLog(#"no goal");
} else {
[self.score setStringValue:#"1"]; //does not work
NSLog(#"GOOOOAL");
}
}
- (void)serialPortWasRemovedFromSystem:(ORSSerialPort *)serialPort
{
self.serialPort = nil;
}
- (void)serialPort:(ORSSerialPort *)serialPort didEncounterError:(NSError *)error
{
NSLog(#"%s %# %#", __PRETTY_FUNCTION__, serialPort, error);
}
- (void)serialPortWasOpened:(ORSSerialPort *)serialPort
{
NSLog(#"Serial port %s was opened", [serialPort.name UTF8String]);
}
#end
The instance of MasterViewController that is listening to your serial port is not the same one that you are seeing on screen.
You create a new one and assign it to a static variable - this is not the same one you have loaded from a nib with all its outlets connected.
Log self in both methods to confirm.

Calculator App - strange error: 'unrecognized selector sent to instance' when trying to update display

I'm relatively new to Objective-C, so I'm not 100% about everything I'm coding. However, I'm tackling my errors as they happen, and I am getting a run-time error that I'm not sure how to fix. The error claims that an 'unrecognized selector [was] sent to instance.'
- (IBAction) equalsPressed{
self.userIsInTheMiddleOfTypingANumber = NO;
if (self.brain.operationIsPicked) {
[self.brain pushOperand: [self.display.text doubleValue]];
double result = [self.brain performOperation: self.brain.operation];
// The line below this
self.display.text = [NSString stringWithFormat: #"%g", result];
}
}
I'm doing the Calculator app taught by the Stanford professor whose course is posted in iTunes U. However, I edited it to not include an enterPressed command and instead use an altered and more user-friendly 'equalsPressed.' After equalsPressed is finished (meaning when I click the equals sign on the calculator), the error is displayed. Might anyone know what is causing this problem? I already found someone else who has an error very similar to this one, but occurring in a slightly different place. Here are the other code snippets that could help elucidate the problem.
#import "CalculatorBrain.h"
#interface CalculatorBrain()
#property (nonatomic, strong) NSMutableArray *operandStack;
#end
#implementation CalculatorBrain
#synthesize operandStack = _operandStack;
#synthesize operandStackIsEmpty = _operandStackIsEmpty;
#synthesize operationIsPicked = _operationIsPicked;
#synthesize operation = _operation;
- (NSMutableArray *) operandStack {
if (!_operandStack) {
_operandStack =[[NSMutableArray alloc] init];
_operandStackIsEmpty = YES;
_operationIsPicked = NO;
}
return _operandStack;
}
- (void) resetStack {
[self.operandStack removeAllObjects];
self.operandStackIsEmpty = YES;
self.operationIsPicked = NO;
}
- (void) pushOperand : (double) operand{
[self.operandStack addObject: [NSNumber numberWithDouble:operand]];
self.operandStackIsEmpty = NO;
}
- (double) popOperand {
NSNumber *num = [self.operandStack lastObject];
if (num) {[self.operandStack removeLastObject];}
return [num doubleValue];
}
- (double) performOperation : (NSString *) operation{
double result = 0;
double num2 = [self popOperand];
double num1 = [self popOperand];
if ([operation isEqualToString:#"+"])
result = num2 + num1;
else if ([operation isEqualToString:#"-"])
result = num2 - num1;
else if ([operation isEqualToString:#"*"] || [operation isEqualToString:#"x"])
result = num2 * num1;
else if ([operation isEqualToString:#"/"]){
if (num2 == 0)
[self resetStack];
else
result = num2 / num1;
}
[self pushOperand:result];
self.operationIsPicked = NO;
return result;
}
#end
Also, the debugging NSLog that I had print the display in the console works correctly, BUT the display in the Calculator view doesn't actually update (when I used breakpoints to slow the function down).
#import "CalculatorViewController.h"
#import "CalculatorBrain.h"
#interface CalculatorViewController ()
#property (nonatomic) BOOL userIsInTheMiddleOfTypingANumber;
#property (nonatomic, strong) CalculatorBrain *brain;
#end
#implementation CalculatorViewController
#synthesize userIsInTheMiddleOfTypingANumber = _userIsInTheMiddleOfTypingANumber;
#synthesize brain = _brain;
#synthesize display = _display;
- (CalculatorBrain *) brain {
if (!_brain) {
_brain =[[CalculatorBrain alloc] init];
}
return _brain;
}
- (IBAction) digitPressed: (UIButton *)sender {
NSString *digit = [sender currentTitle];
if (self.userIsInTheMiddleOfTypingANumber)
self.display.text = [self.display.text stringByAppendingString: digit];
else {
self.display.text = digit;
self.userIsInTheMiddleOfTypingANumber = YES;
}
}
- (IBAction) clearPressed {
self.userIsInTheMiddleOfTypingANumber = NO;
self.display.text = #"0";
[self.brain resetStack];
}
- (IBAction) equalsPressed {
self.userIsInTheMiddleOfTypingANumber = NO;
if (self.brain.operationIsPicked) {
[self.brain pushOperand: [self.display.text doubleValue]];
double result = [self.brain performOperation: self.brain.operation];
self.display.text = [NSString stringWithFormat: #"%g", result];
NSLog(#"%#",self.display.text);
}
NSLog(#"%#",self.display.text);
}
- (IBAction) operationPressed:(UIButton *) sender {
if (self.userIsInTheMiddleOfTypingANumber) {
[self.brain pushOperand: [self.display.text doubleValue]];
self.brain.operation = [sender currentTitle];
self.brain.operationIsPicked = YES;
self.userIsInTheMiddleOfTypingANumber = NO;
NSLog(#"%#", sender.currentTitle);
}
}
Thank you!
To quote the answer in the comments:
"The full error said that I sent an invalid argument to "[self.brain equalsPressed:]". In reality, equalsPressed takes no argument, but when I was linking the '=' button in my view to its respective method, I forgot to indicate that the function took no arguments. Hence even though the function as I wrote it has no arguments, I told the compiler (to begin with) that it was supposed to take an argument."

Using a property as a count in Objective C

I am new to Objective C. I was following Stanford lectures 2011-12 fall on iOS development and in assignment 1 it asks to implement a decimal point in a calculator. This is what my implementation looks like:
#import "CalculatorViewController.h"
#import "CalculatorBrain.h"
#interface CalculatorViewController()
#property (nonatomic) BOOL userIsInTheMiddleOfEnteringNumber;
#property (nonatomic,strong) CalculatorBrain *brain;
#property (nonatomic) int userPressedDecimalPoint;
#end
#implementation CalculatorViewController
#synthesize display = _display;
#synthesize userIsInTheMiddleOfEnteringNumber = _userIsInTheMiddleOfEnteringNumber;
#synthesize userPressedDecimalPoint = _userPressedDecimalPoint;
#synthesize brain = _brain;
- (CalculatorBrain *) brain{
if (!_brain) _brain = [[CalculatorBrain alloc] init];
return _brain;
}
- (IBAction)digitpressed:(UIButton *)sender {
NSString *digit = sender.currentTitle;
if (digit == #"."){
self.userIsInTheMiddleOfEnteringNumber = YES;
self.userPressedDecimalPoint++;
}
if (self.userIsInTheMiddleOfEnteringNumber && self.userPressedDecimalPoint< 2){
self.display.text = [self.display.text stringByAppendingString:digit];
NSLog(#"decimal pressed: %d times",self.userPressedDecimalPoint);
}
else{
self.display.text = digit;
self.userIsInTheMiddleOfEnteringNumber = YES;
self.userPressedDecimalPoint = 1;
}
}
So basically I have setup a property userPressedDecimalPoint and i try to use this property as a counter every time the decimal point is pressed. However from the NSLog i see that no matter how many times i press the decimal point it only shows 1 time pressed. Consequently, the output shows multiple decimal points if entered. Any suggestions would be appreciated. Thanks!
Full version of Corrected Code:
#import "CalculatorViewController.h"
#import "CalculatorBrain.h"
#interface CalculatorViewController()
#property (nonatomic) BOOL userIsInTheMiddleOfEnteringNumber;
#property (nonatomic,strong) CalculatorBrain *brain;
#property (nonatomic) int userPressedDecimalPoint;
#end
#implementation CalculatorViewController
#synthesize display = _display;
#synthesize userIsInTheMiddleOfEnteringNumber = _userIsInTheMiddleOfEnteringNumber;
#synthesize userPressedDecimalPoint = _userPressedDecimalPoint;
#synthesize brain = _brain;
- (CalculatorBrain *) brain{
if (!_brain) _brain = [[CalculatorBrain alloc] init];
return _brain;
}
- (IBAction)digitpressed:(UIButton *)sender {
NSString *digit = sender.currentTitle;
if ([digit isEqualToString:#"."]){
self.userIsInTheMiddleOfEnteringNumber = YES;
self.userPressedDecimalPoint++;
}
if (self.userIsInTheMiddleOfEnteringNumber && self.userPressedDecimalPoint< 2){
self.display.text = [self.display.text stringByAppendingString:digit];
// NSLog(#"decimal pressed: %d times",self.userPressedDecimalPoint);
}
else if (![digit isEqualToString:#"."]){
self.display.text = digit;
self.userIsInTheMiddleOfEnteringNumber = YES;
}
}
- (IBAction)operationPressed:(UIButton *)sender {
if (self.userIsInTheMiddleOfEnteringNumber) [self enterPressed];
double result = [self.brain performOperation:sender.currentTitle];
NSString *resultString = [NSString stringWithFormat:#"%g", result];
self.display.text = resultString;
}
- (IBAction)enterPressed {
self.userPressedDecimalPoint = 0;
[self.brain pushOperand:[self.display.text doubleValue]];
self.userIsInTheMiddleOfEnteringNumber = NO;
}
#end
Unless there is something that sets userIsInTheMiddleOfEnteringNumber to NO, any time the number is greater than one, your code will execute self.userPressedDecimalPoint = 1; and set it back to one.

Objective C Calculator Programming Variable

Okay, so I've been working on the Stanford iOS development course that they have posted for free online. I've been working on figuring out how to make a programable variable. It has been working fine so far, aside from the fact that I think the following lines of code are programming the variable to be #"x=" instead of the previous number entered.
The View Controller:
#import "ViewController.h"
#import "CalculatorBrain.h"
#interface ViewController()
#property (nonatomic) BOOL userIsInTheMiddleOfEnteringANumber;
#property (nonatomic) BOOL userPressedSomethingElse;
#property (nonatomic, strong) CalculatorBrain *brain;
#end
#implementation ViewController
#synthesize display;
#synthesize inputHistory;
#synthesize userPressedSomethingElse;
#synthesize userIsInTheMiddleOfEnteringANumber;
#synthesize brain = _brain;
- (CalculatorBrain *)brain
{
if (!_brain) _brain = [[CalculatorBrain alloc] init];
return _brain;
}
NSString *xValue = #"0";
- (IBAction)enterPressed
// A specific action if enter is pressed
{
[self.brain pushOperand:[self.display.text doubleValue]];
self.userIsInTheMiddleOfEnteringANumber = NO;
if (self.userPressedSomethingElse)
{
self.inputHistory.text = [self.inputHistory.text stringByAppendingString:#" "];
}
self.userPressedSomethingElse = NO;
}
- (IBAction)variableChanged:(id)sender
{
if (self.userIsInTheMiddleOfEnteringANumber)
{
[self enterPressed];
}
NSString *operation = [sender currentTitle];
xValue = [self.brain programVariable:operation];
self.inputHistory.text = [self.inputHistory.text stringByAppendingString:#"X="];
self.inputHistory.text = [self.inputHistory.text stringByAppendingString:xValue];
}
The Calculator Brain (the .m one):
#import "CalculatorBrain.h"
#interface CalculatorBrain()
#property (nonatomic,strong) NSMutableArray *operandStack;
#end
#implementation CalculatorBrain
#synthesize operandStack = _operandStack;
- (NSMutableArray *) operandStack
{
if (!_operandStack)
{
_operandStack = [[NSMutableArray alloc] init];
}
return _operandStack;
}
- (void) pushOperand:(double)operand
{
NSNumber *operandObject = [NSNumber numberWithDouble:operand];
[self.operandStack addObject:operandObject];
}
- (double)popOperand
{
NSNumber *operandObject = [self.operandStack lastObject];
if (operandObject) [self.operandStack removeLastObject];
return [operandObject doubleValue];
}
- (NSString *) programVariable: (NSString *) operation
{
double result = [self popOperand];
NSString *resultString = [NSString stringWithFormat:#"%.2d",result];
return resultString;
}
The .h Calculator Brain:
#import <Foundation/Foundation.h>
#interface CalculatorBrain : NSObject
- (void) pushOperand: (double) operand;
- (double) performOperation: (NSString *) operation;
- (NSString *) programVariable: (NSString *) operation;
#end
The button that is pushed says "x=", and because of some tracing statements I added, I have figured out that this is being set to xValue. However, I don't know how to fix it... Any ideas?
In your variableChanged:method, you possibly want if (!self.userIsInTheMiddleOfEnteringANumber) at the beginning. Note the logical negation, which I derive the need from the sense of your variable name. I see no way that variable is set, so I trust you are properly setting it elsewhere in your app.
Also, change the variable xValue to a instance variable on ViewController. It is currently a global static variable. If you have more than one ViewController objects created, you will have problems.