I need another set of eyes

Discussion in 'iOS Programming' started by AlbuquerqueApac, May 15, 2012.

  1. AlbuquerqueApac macrumors member

    Joined:
    Jan 13, 2012
    #1
    Ok, so I have been staring at this code for a couple of days and the nearest I can tell, it;s right (though I know something is off).

    it's a calculator program (I found this part of it online).

    Code:
     
    
    #import "Calculator.h"
    
    @implementation Calculator
    
    {
        float result;
        int currentOperation;
        float currentNumber;
        NSMutableString *CalculatorScreen;
        
        
        
        
    }
    
    
    
    
    -(void)DigitPressed:(int) digit;
    {
        currentNumber = currentNumber * 10 +  (float) digit;
        CalculatorScreen = [NSString stringWithFormat: @"%.2f", currentNumber];
      
        
    }
    
    -(void)OperationPressed:(int) sender {
    	if (currentOperation == 0) result = currentNumber;
    	else {
    		switch (currentOperation) {
    			case 1:
    				result = result + currentNumber;
    				break;
    			case 2:
    				result = result - currentNumber;
    				break;
    			case 3:
    				result = result * currentNumber;
    				break;
    			case 4:
    				result = result / currentNumber;
    				break;
                case 5:
                    break;
    			
    		}
    	}
    	currentNumber = 0;
    	CalculatorScreen = [NSString stringWithFormat:@"%.2f",result];
    	currentOperation = sender;
        
        
    }
    
    -(void) clear
    {
       
        
        [CalculatorScreen setString:@""]; 
        
        
    }
    
    -(NSString *) getDisplay
    {
        return CalculatorScreen;
        
    }
    -(float) getResult
    {
        return result;
        
    }
    -(void) setCurrentOperator
    {
        currentOperation=0;
    }
    
    @end
    
    
    
    

    I think it is something with the switch statement because the calculator behaves as if it is never receiving the initial 0 for CurrentOperator. I went so far as to add a setter method for that specific reason in the viewdidload with no results. and with that, I'm stumped.
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    1. Describe what you did. List the exact actions you performed, what you pressed.

    2. Describe what you expected to happen. Be specific.

    3. Describe what actually happened. List exactly what happened, what shows up on screen, and when.


    If you found part of it online, exactly where online? Post the URL.


    Find all the places where currentOperation is being assigned a value. In which of them are you assigning it a non-zero value?

    If currentOperation is never assigned a value other than zero, how will the program behave?


    You have a bug:
    Code:
        NSMutableString *CalculatorScreen;
    
    Yet you only assign CalculatorScreen values using an NSString method. This is logically inconsistent with the declared type of NSMutableString.


    Read this:
    http://en.wikipedia.org/wiki/Rubber_duck_debugging

    The most important factor: actually making the meticulous explanation. The species of the inanimate object is of much less importance.
     
  3. AlbuquerqueApac, May 15, 2012
    Last edited: May 15, 2012

    AlbuquerqueApac thread starter macrumors member

    Joined:
    Jan 13, 2012
    #3
    (I quoted this so I could answer your questions specifically)

    1. the first thing I do is type a vary simple "press button 1" when I do "1.00" appears (thats ok) and when I press "+" and then 1 or whatever number it appears in the float format. All is good there. When I hit equals I will get something else (I think it is 3). I do know I am getting a zero with my multiplication problems (Thats why I assumed I was gettign a zero valued stored somewhere).

    2. I expect 2.00 to appear for the addition and the correct problem.

    3. see 1.

    URL for the guts of the Calculator.

    http://chris-software.com/index.php/2009/04/25/simple-calculator/


    The NSmutableString error answers another one of my questions.
    I was getting an exception and I was wndering why when I have the string as NSmutable.

    I will fix that bug.

    CurrentOperation SHOULD initially have a zero, but upon completion of the switch, be set to the operation that is sent (I know I didnt post it, but it is being sent as an int derived from a sender.tag in the view implementation).
     
  4. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #4
    The code you supplied in your original post does not match the code from that website. For example:

    Code:
    -(void)OperationPressed:(int) sender {
    vs.

    Code:
    -(IBAction)buttonOperationPressed:(id)sender {
    Why is that?
     
  5. AlbuquerqueApac thread starter macrumors member

    Joined:
    Jan 13, 2012
    #5
    That's because in the program posted on the website, the viewcontroller owns the Calculator class. I wanted to have a different design. The main difference is that I have to use setter and getter methods in my viewcontroller implementation for my Calculator class.
     
  6. dejo, May 15, 2012
    Last edited: May 15, 2012

    dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #6
    What do you mean it "owns" it?
     
  7. AlbuquerqueApac thread starter macrumors member

    Joined:
    Jan 13, 2012
    #7
    http://chris-software.com/wp-content/uploads/2009/04/interfacebuildernoconnection.png

    "Now select File’s Owner and go to the last tab in Inspector (Object Identity). View won’t be shown by itself that is why we already prepared the MyView class that’s going to control the view; under Class Identity in Inspector enter MyView as Class. As you see auto-completion works great (also in Xcode) so just entering m refers to MyView. Now File’s Owner is a type of MyView, not NSObject any longer. That’s not all. One .xib file may consists of many views and even if you have only one right now, you have to set is as a main view of MyView class. Again in File’s Owner’s Inspector in second tab (MyView connections) you have 3 outlets, one of them is called view."

    I didn't bother with any of this. I just changed the code where necessary.

    All this is besides the point. The problem is somewhere in the program. I will post the remainder of the code when I have access to my Mac in the evening.
     
  8. AlbuquerqueApac thread starter macrumors member

    Joined:
    Jan 13, 2012
    #8
    I wonder if I had a default for the switch, might help.
     
  9. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #9
    There is no Calculator class in that tutorial. I guess that's why I was concerned.

    Yes, please do. It is always better to debug with the code and app in front of you rather than try to remember what was happening in some other location at a different time.
     
  10. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #10
    Did you run the original program first, to see if it worked as expected? The project's website has a download with the complete Xcode project, so it should be easy to test that.

    With the original program running correctly, did you set breakpoints, add NSLogs, or do anything to help you understand exactly how that program works? Understanding how something works is usually an important first step before changing it.

    If you didn't do any of those things, I suggest stopping work on your current project in it's current non-working state, and doing those things first. If the original works, then you can study how it works, and that should shed some light on why yours doesn't work. If the original doesn't work, then you know it doesn't work, and you can describe exactly what happens by posting here.

    As an experienced programmer, I would have to be insane not to take advantage of a known-working program, especially if I was trying to learn how that program worked so I could modify it. Modifying it without seeing it work first just seems crazy backwards to me.
     
  11. AlbuquerqueApac thread starter macrumors member

    Joined:
    Jan 13, 2012
    #11
    Ok, I took chowns advice and downloaded the project. The project works fine. The problem is, I still can't see whats going on within my "variant" of this program.

    PROGRAM THAT WORKS:

    AppDelegate
    Code:
    
    #import <UIKit/UIKit.h>
    #import "Calc.h"
    
    @class Calc;
    @interface CalculatorAppDelegate : NSObject <UIApplicationDelegate> {
        UIWindow *window;
    }
    
    @property (nonatomic, retain) IBOutlet UIWindow *window;
    
    @end
    
    
    Calc.h
    Code:
    #import <UIKit/UIKit.h>
    @interface Calc : UIViewController {
    	float result;
    	IBOutlet UILabel *calculatorScreen;
    	int currentOperation;
    	float currentNumber;
    }
    -(IBAction)buttonDigitPressed:(id)sender;
    -(IBAction)buttonOperationPressed:(id)sender;
    -(IBAction)cancelInput;
    -(IBAction)cancelOperation;
    @end
    
    Calc.m
    Code:
    #import "Calc.h"
    
    
    @implementation Calc
    
    -(IBAction)buttonDigitPressed:(id)sender {
    	currentNumber = currentNumber*10 + (float)[sender tag];
    	calculatorScreen.text = [NSString stringWithFormat:@"%.2f",currentNumber];
    }
    -(IBAction)buttonOperationPressed:(id)sender {
    	if (currentOperation == 0) result = currentNumber;
    	else {
    		switch (currentOperation) {
    			case 1:
    				result = result + currentNumber;
    				break;
    			case 2:
    				result = result - currentNumber;
    				break;
    			case 3:
    				result = result * currentNumber;
    				break;
    			case 4:
    				result = result / currentNumber;
    				break;
    			case 5:
    				currentOperation = 0;
    				break;
    		}
    	}
    	currentNumber = 0;
    	calculatorScreen.text = [NSString stringWithFormat:@"%.2f",result];
    	if ([sender tag] == 0) result = 0;
    	currentOperation = [sender tag];
    }
    -(IBAction)cancelInput {
    	currentNumber = 0;
    	calculatorScreen.text = @"0.00";
    }
    -(IBAction)cancelOperation {
    	currentNumber = 0;
    	calculatorScreen.text = @"0.00";
    	currentOperation = 0;
    }
    
    
    
    /*
    // The designated initializer. Override to perform setup that is required before the view is loaded.
    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
        if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
            // Custom initialization
        }
        return self;
    }
    */
    
    /*
    // Implement loadView to create a view hierarchy programmatically, without using a nib.
    - (void)loadView {
    }
    */
    
    /*
    // Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
    - (void)viewDidLoad {
        [super viewDidLoad];
    }
    */
    
    /*
    // Override to allow orientations other than the default portrait orientation.
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
        // Return YES for supported orientations
        return (interfaceOrientation == UIInterfaceOrientationPortrait);
    }
    */
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
        // Release anything that's not essential, such as cached data
    }
    
    
    - (void)dealloc {
        [super dealloc];
    	[calculatorScreen release];
    }
    
    
    @end
    
    AppDelegate.m
    Code:
    #import "CalculatorAppDelegate.h"
    
    @implementation CalculatorAppDelegate
    
    @synthesize window;
    
    
    - (void)applicationDidFinishLaunching:(UIApplication *)application {    
    	Calc *viewController = [[Calc alloc] initWithNibName:@"Calculator" bundle:[NSBundle mainBundle]];
    	[window addSubview:[viewController view]];
        // Override point for customization after application launch
        [window makeKeyAndVisible];
    }
    
    
    - (void)dealloc {
        [window release];
        [super dealloc];
    }
    
    
    @end
    
    HERE IS MY VARIANT (THE BOLD IS TO HELP ME JUMP BACK AND FORTH)

    AppDelegate.h

    Code:
    #import <UIKit/UIKit.h>
    
    @class ViewController;
    
    @interface AppDelegate : UIResponder <UIApplicationDelegate>
    
    @property (strong, nonatomic) UIWindow *window;
    
    @property (strong, nonatomic) ViewController *viewController;
    
    @end
    
    AppDelegate.m
    Code:
    
    #import "AppDelegate.h"
    
    #import "ViewController.h"
    
    @implementation AppDelegate
    
    @synthesize window = _window;
    @synthesize viewController = _viewController;
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        // Override point for customization after application launch.
        self.viewController = [[ViewController alloc] initWithNibName:@"ViewController" bundle:nil];
        self.window.rootViewController = self.viewController;
        [self.window makeKeyAndVisible];
        return YES;
    }
    
    - (void)applicationWillResignActive:(UIApplication *)application
    {
        /*
         Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
         Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
         */
    }
    
    - (void)applicationDidEnterBackground:(UIApplication *)application
    {
        /*
         Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
         If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
         */
    }
    
    - (void)applicationWillEnterForeground:(UIApplication *)application
    {
        /*
         Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
         */
    }
    
    - (void)applicationDidBecomeActive:(UIApplication *)application
    {
        /*
         Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
         */
    }
    
    - (void)applicationWillTerminate:(UIApplication *)application
    {
        /*
         Called when the application is about to terminate.
         Save data if appropriate.
         See also applicationDidEnterBackground:.
         */
    }
    
    @end
    
    viewController.h
    Code:
    #import <UIKit/UIKit.h>
    
    @interface ViewController : UIViewController
    
    @property (strong, nonatomic) IBOutlet UILabel *display;
    
    -(IBAction)clickDigit:(UIButton *)sender;
    -(IBAction)Operation: (UIButton *)sender;
    -(IBAction)ClickEquals:(UIButton *)sender;
    -(IBAction)clickClear:(UIButton *)sender;
    -(IBAction)getCN:(UIButton *)sender;
    
    
    
    
    
    
    @end
    
    ViewController.m
    Code:
    
    #import "ViewController.h"
    #import "Calculator.h"
    
    
    @implementation ViewController
    {
        Calculator *MyCalculator;
        
        
        
    }
    
    @synthesize display;
    
    
    
    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Release any cached data, images, etc that aren't in use.
        
    }
    
    
    
    #pragma mark - View lifecycle
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    	// Do any additional setup after loading the view, typically from a nib.
        MyCalculator=[[Calculator alloc] init];
        //[MyCalculator setCurrentOperator];
        
        
    }
    
    
    -(IBAction)clickDigit:(UIButton *)sender
    {
         
        [MyCalculator DigitPressed: sender.tag];
        display.text=[MyCalculator getDisplay];
        
    }
    
    -(IBAction)Operation:(UIButton *)sender
    {
        int op = [sender tag];
        
        [MyCalculator OperationPressed:op];
        
    }
        
    -(IBAction)ClickEquals:(UIButton *)sender
    {
        display.text=[NSString stringWithFormat:@"%.2f", [MyCalculator getResult]];
        
    }
    
    
    
    
    -(IBAction)clickClear:(UIButton *)sender
    {
        [MyCalculator clear];
       display.text=[NSString stringWithFormat:@"%.2f",[MyCalculator getDisplay]];
        
        
    }
    
    -(IBAction)getCN:(UIButton *)sender
    {
        display.text=[NSString stringWithFormat:@"%.2f", [MyCalculator GetCurrentNumber]];
        
    }
    
    
    - (void)viewDidUnload
    {
        [super viewDidUnload];
        // Release any retained subviews of the main view.
        // e.g. self.myOutlet = nil;
    }
    
    - (void)viewWillAppear:(BOOL)animated
    {
        [super viewWillAppear:animated];
    }
    
    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
    }
    
    - (void)viewWillDisappear:(BOOL)animated
    {
    	[super viewWillDisappear:animated];
    }
    
    - (void)viewDidDisappear:(BOOL)animated
    {
    	[super viewDidDisappear:animated];
    }
    
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    {
        // Return YES for supported orientations
        return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
    }
    
    
    @end
    
    Calculator.h
    Code:
    
    @interface Calculator : NSObject
    {
        
            float result;
            int currentOperation;
            float currentNumber;
            NSMutableString *CalculatorScreen;
            
            
            
            
        
    }
    
    
    
    
    
    -(void)DigitPressed:(int) Digit;
    -(void)OperationPressed:(int)sender;
    -(void) clear;
    -(NSMutableString*) getDisplay;
    -(float) getResult;
    -(void) setCurrentOperator; 
    -(float) GetCurrentNumber;
    

    Calculator.m
    Code:
    
    
    #import "Calculator.h"
    
    @implementation Calculator
    
    
    
    
    -(void)DigitPressed:(int) digit;
    {
        currentNumber = currentNumber*10 +(float)digit;
        CalculatorScreen = [NSMutableString stringWithFormat: @"%.2f", currentNumber];
      
        
    }
    
    -(float) GetCurrentNumber
    
    {
        return currentNumber;
    }
    
    
    
    
    -(IBAction)OperationPressed:(int)sender {
    	if (currentOperation == 0) result = currentNumber;
    	else {
    		switch (currentOperation) {
    			case 1:
    				result = result + currentNumber;
    				break;
    			case 2:
    				result = result - currentNumber;
    				break;
    			case 3:
    				result = result * currentNumber;
    				break;
    			case 4:
    				result = result / currentNumber;
    				break;
    			case 5:
    				currentOperation = 0;
    				break;
    		}
    	}
    	currentNumber = 0;
    	CalculatorScreen = [NSMutableString stringWithFormat:@"%.2f",result];
    	if (sender == 0) result = 0;
    	currentOperation = sender;
    }
    
    
    
    
    -(void) clear
    {
       
        
        [CalculatorScreen setString:@""];
        currentNumber=0;
        result=0;
        
        
        
    }
    
    -(NSString *) getDisplay
    {
        return CalculatorScreen;
        
    }
    -(float) getResult
    {
        return result;
        
    }
    -(void) setCurrentOperator
    {
        currentOperation=0;
    }
    
    

    I'm still not seeing what is making the difference. :(
     
  12. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #12
    Did you follow chown's advice and "set breakpoints, add NSLogs, or do anything to help you understand exactly how that program works?"
     
  13. AlbuquerqueApac thread starter macrumors member

    Joined:
    Jan 13, 2012
    #13
    I sure did! and the debugger in Xcode rocks!

    BUT I found my problem but not sure why it exists.

    Ok, so I set breakpoints in both programs and check the value of all the variables. Everything is one for one a match until I get to the switch statement, .
    For some odd reason, my Result variable is simple having the last digit entered stored in it whereas the original program is actually performing the calculation and assigning it to the result variable. I'm not sure why my program is doing this. All three variables are float datatypes and, from my eyes, look the same.
     
  14. dejo Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #14
    Sounds to me like your currentOperation is always 0. Is that the case?
     

Share This Page