Don't work subtraction/multiplication/division but work addition - objective-c

Hello!
In my calculator program don't work subtraction/multiplication/division methods but work addition method.
Addition method:
-(IBAction) clickPlus
{
[self processOp: '+'];
}
Subtraction method:
-(IBAction) clickMinus
{
[self processOp: '-'];
}
Process method:
-(void) processOp: (char) theOp
{
NSString *opStr;
op = theOp;
switch (theOp) {
case '+':
opStr = #" + ";
break;
case '-':
opStr = #" – ";
break;
case '*':
opStr = #" * ";
break;
case '/':
opStr = #" ÷ ";
break;
}
[self storeFracPart];
firstOperand = NO;
isNumerator = YES;
[displayString appendString: opStr];
display.text = displayString;
}
In that method 'op' variable is used: "clickEquals"
-(IBAction) clickEquals
{
if ( firstOperand == NO )
{
[self storeFracPart];
[myCalculator performOperation: op];
[displayString appendString: #" = "];
[displayString appendString: [myCalculator.accumulator
convertToString]];
display.text = displayString;
currentNumber = 0;
isNumerator = YES;
firstOperand = YES;
[displayString setString: #""];
}
}
Why do you think that 'op' collect garbage?
If you need more code just let me know.

What is op in clickEquals? Is it supposed to be a class ivar? If so processOp is wrong as it's using a local variable called op and is therefore never assigning the ivar.
You should learn to debug this kind of problems yourself. It's not too hard. If you step through the code execution line by line in the debugger and watch what changes when you should be able to find this sort of problems.

Related

Always returning null in NSString return function

I have the following code where I want to convert decimal odds to fractional odds. However the function findNearestWholeInteger always returns null.
- (NSString *)displayOddWithFormat:(NSString *)decimalOdd {
if ([[NSUserDefaults standardUserDefaults] boolForKey:#"FractionalOdds"] == YES) {
float oddsF = decimalOdd.floatValue;
oddsF = oddsF - 1.0f;
return [self findNearestWholeInteger:oddsF andInitial:oddsF andBottom:1];
} else {
return odd;
}
}
- (NSString *)findNearestWholeInteger:(float)odds andInitial:(float)initial andBottom:(float)bottom {
NSNumber *numberValue = [NSNumber numberWithFloat:odds];
NSString *floatString = [numberValue stringValue];
NSArray *floatStringComps = [floatString componentsSeparatedByString:#"."];
if (floatStringComps.count == 1) {
return [NSString stringWithFormat:#"%.f/%.f", odds, bottom];
} else {
bottom += 1;
odds += initial;
[self findNearestWholeInteger:odds andInitial:initial andBottom:bottom];
return nil;
}
}
Any ideas where I need to adapt my code? Thanks in advance!
Don't you want:
return [self findNearestWholeInteger:odds andInitial:initial andBottom:bottom];
//return nil;
(not that I really understand what the method is doing).

Stop pinwheel of death in infinite loop Objective C

I am writing a simple timer program for myself in objective c for my mac. The timer counts down properly, but I get the spinning pinwheel of death. How can I make the pinwheel go away? I think its because I have an infinite loop but there must be someway to bypass it.
I have an IBAction that triggered on a button click (the button is start). And from there, it calls another function that does the work.
Here is my IBAction:
- (IBAction)timerStart:(id)sender {
self.timerDidPause = NO;
[self timerRunning];
}
And here is timerRunning:
- (void)timerRunning {
for (;;) {
usleep(1000000);
if (self.timerDidPause == YES) {
}
else {
if (self.seconds == 0) {
if (self.minutes == 0) {
[self timerDone];
break;
}
else {
self.seconds = 59;
self.minutes = self.minutes - 1;
[self formatTimerLabel:self.hours :self.minutes :self.seconds];
}
}
else {
self.seconds = self.seconds - 1;
[self formatTimerLabel:self.hours :self.minutes :self.seconds];
}
}
}
}
In this function, the function formatTimerLabel is called so here is that:
- (void)formatTimerLabel:(int)hours
:(int)minutes
:(int)seconds {
NSString *minuteString = [[NSString alloc] init];
NSString *secondString = [[NSString alloc] init];
if (minutes < 10) {
minuteString = [NSString stringWithFormat:#"0%d", minutes];
}
else {
minuteString = [NSString stringWithFormat:#"%d", minutes];
}
if (seconds < 10) {
secondString = [NSString stringWithFormat:#"0%d", seconds];
}
else {
secondString = [NSString stringWithFormat:#"%d", seconds];
}
[self.timerLabel setStringValue:[NSString stringWithFormat:#"%d:%#:%#", hours, minuteString, secondString]];
[self.timerLabel display];
}
You're causing the UI thread to hang with your loop. After a couple of seconds of that, the OS switches the cursor to a pinwheel.
You need to look into NSTimer and the Timer Programming Guide to schedule the timer to run outside of the UI thread.

Compare and go to another view controller

I have this code:
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSDictionary *data = [list1 objectAtIndex:row];
NSNumber *strt = [data objectForKey:#"ab1"];
NSNumber *strt2 = [data objectForKey:#"ab1"];
forlb1 = [NSString stringWithFormat:#"%d", strt.intValue];
forlb2 = [NSString stringWithFormat:#"%d", strt2.intValue];
NSDictionary *xt = [list1 objectAtIndex:row];
NSString *name = [xt objectForKey:#"name"];
NSDictionary *xx = [list1 objectAtIndex:row];
NSString *name2 = [xx objectForKey:#"name"];
switch (component)
{
case 0:
show1 = name;
label1.text = forlb1;
break;
case 1:
show2 = name2;
label2.text = forlb2;
break;
}
}
- (IBAction)goView:(id)sender
{
if (label1.text < labe2.tex)
{
ViewController1 *first = [[ViewController1 alloc]init];
first.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:first animated:YES];
}
else
{
ViewController3 *third = [[ViewController3 alloc]init];
third.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;
[self presentModalViewController:third animated:YES];
}
}
My problem is: I can't get ViewController3 if my label1.text < label2.text
When I select from component 1 of Picker view, one of my labels show the Name, and Another, label1 show me a number, same thing happens with component 2 of Picker view, now is ok, but when I should touch the button, I need to go to viewcontroller 1 or viewcontroller 2, depends of: label1.text < label2.text
Help me please.
You should not be comparing label.text using the less then < operator. Depending on the content of the label, you should either convert the text to number and do a check, or compare strings alphabetically.
This is how to compare strings numerically, assuming that the text represents an integer number:
if ([label1.text intValue] < [labe2.text intValue]) {
....
}
This is how to compare strings alphabetically:
if ([label1.text compare:labe2.text] == NSOrderedAscending) {
....
}

Can't get negative sign in calculator to disappear

I'm working on an iOS 5 calculator that contains the following code:
- (IBAction)digitPressed:(UIButton *)sender
{
//Enter digit, avoiding two-decimal-point case.
NSString *digit = sender.currentTitle;
NSRange range = [self.display.text rangeOfString:#"."];
if (range.location==NSNotFound || (![digit isEqualToString:#"."]))
if (self.userIsEnteringNumber)
{
self.display.text = [self.display.text stringByAppendingString:digit];
}
else
{
if (![sender.currentTitle isEqualToString:#"."])
{
self.display.text = digit;
}
else
{
self.display.text = #"0.";
}
self.userIsEnteringNumber = YES;
}
}
and
- (IBAction)changeSignPressed
{
//Reverse sign from positive to negative or vice versa.
if (self.numberIsNegative) self.numberIsNegative = NO;
if (!(self.numberIsNegative)) self.numberIsNegative = YES;
//Correct display to reflect change in sign.
if (self.numberIsNegative)
{
if (![[self.display.text substringToIndex:1] isEqualToString:#"-"])
{
self.display.text = [#"-" stringByAppendingString:self.display.text];
}
}
if (!self.numberIsNegative)
{
/*This isn't working--why not?
if ([[self.display.text substringToIndex:1] isEqualToString:#"-"])
{
NSLog(#"Okay."); //This doesn't log, so obv. the problem is in the previous line.
self.display.text = [self.display.text substringFromIndex:1];
}
*/
}
}
I can't get the commented-out code in changeSignPressed to work no matter how I fiddle with it. Any ideas about how I can fix this?
It's probably this code:
//Reverse sign from positive to negative or vice versa.
if (self.numberIsNegative) self.numberIsNegative = NO;
if (!(self.numberIsNegative)) self.numberIsNegative = YES;
There is no else so if self.numberIsNegative is initially YES it will become NO; it will then be immediately seen as NO on the following line where it is changed back to YES.
In any case, that code is more complex than it needs to be; you can just say this to invert a flag:
self.numberIsNegative = ! self.numberIsNegative;

Using NSTimer with two intervals

I'm creating an app that converts text to Morse code, and then flash it out using the iPhone's flashlight. I have used string replacement, to convert the content of a NSString to Morse code.
// some of the code :
str = [str stringByReplacingOccurrencesOfString:#"5" withString:n5];
str = [str stringByReplacingOccurrencesOfString:#"6" withString:n6];
str = [str stringByReplacingOccurrencesOfString:#"7" withString:n7];
str = [str stringByReplacingOccurrencesOfString:#"8" withString:n8];
str = [str stringByReplacingOccurrencesOfString:#"9" withString:n9];
str = [str stringByReplacingOccurrencesOfString:#"0" withString:n0];
NSString *morseCode = [[NSString alloc] initWithFormat:str];
self.label.text = morseCode;
I have found a script that turns the iPhone's flashlight on and off, with adjustable intervals using NSTimer. But I can't figure out how to add two different intervals, one for the dot and one for the Morse dash.
- (void)viewDidLoad
{
[super viewDidLoad];
int spaceTime;
spaceTime = 1;
int dashTime;
dashTime = 2;
int dotTime;
dotTime = 0.8;
strobeIsOn = NO;
strobeActivated = NO;
strobeFlashOn = NO;
flashController = [[FlashController alloc] init];
self.strobeTimer = [
NSTimer
scheduledTimerWithTimeInterval:spaceTime
target:self
selector:#selector(strobeTimerCallback:)
userInfo:nil
repeats:YES
];
self.strobeFlashTimer = [
NSTimer scheduledTimerWithTimeInterval:dotTime
target:self
selector:#selector(strobeFlashTimerCallback:)
userInfo:nil
repeats:YES
];
}
- (void)strobeTimerCallback:(id)sender {
if (strobeActivated) {
strobeIsOn = !strobeIsOn;
// ensure that it returns a callback. If no, returns only one flash
strobeFlashOn = YES;
} else {
strobeFlashOn = NO;
}
}
- (void)strobeFlashTimerCallback:(id)sender {
if (strobeFlashOn) {
strobeFlashOn = !strobeFlashOn;
[self startStopStrobe:strobeIsOn];
} else {
[self startStopStrobe:NO];
}
}
Should I use two timers or can I have one with different intervals? Should I put the content of the string in an array?
I'm new in Obj-C ..
I would try to make a recursive function:
parseAndFlash
{
NSString *codeString = #"-.-. --- -.. .";
int currentLetterIndex = 0;
//codeString and currentLetterIndex should be declared outside this function as members or something
double t_space = 2, t_point = 0.5, t_line = 1, t_separator = 0.1;
double symbolDuration = 0;
if(currentLetterIndex >= [codeString length])
return;
char currentLetter = [codeString characterAtIndex:currentLetterIndex];
switch (currentLetter) {
case '-':
symbolDuration = t_line;
[self flashOnFor:t_line];
break;
case '.':
symbolDuration = t_point;
[self flashOnFor:t_point];
break;
case ' ':
symbolDuration = t_space;
[self flashOff];
break;
default:
break;
}
currentLetterIndex ++;
symbolDuration += t_separator;
[self performSelector:#selector(parseAndFlash) withObject:nil afterDelay:symbolDuration];
}
you can try to run code in sequence on background treed and sleep it for as long as you need. It would be much easier code to write and maintain than to use bunch of timers.
// execute in background
[self performSelectorInBackground:#selector(doTheMagic) withObject:nil];
- (void)doTheMagic {
NSLog(#"Turn ON");
[NSThread sleepForTimeInterval:1];
NSLog(#"Turn OFF");
[NSThread sleepForTimeInterval:0.1f];
NSLog(#"Turn ON");
[NSThread sleepForTimeInterval:1.0f];
// ...
}