Determinate Progress Indicator issue... (grrr)

Discussion in 'Mac Programming' started by Some Guy 555, Sep 1, 2009.

  1. Some Guy 555 macrumors regular

    Joined:
    May 26, 2009
    #1
    Have been making the effort in the last few days to learn objective-c and how to use cocoa and x-code.

    Was making this program that simply had the user enter a starting number, an increment number and an ending number which would be used in a for loop.

    Inside the for loop would have code to update a determinate progress indicator to show how close to finishing the looping it was.

    For the life of me and my embarrassment I cannot get this to work. I have looked over it countless times and looked at documentation.

    Here is my code:


    Code:
    -(void)benchmark
    {
    	int i;
    	
    	//Set the progress bar's minimum value to the start number.
    	[progressBar setMinValue:self.startNumber];
    
    	//Set the progress bar's maximum value to the end number.
    	[progressBar setMaxValue:self.endNumber];
    
    	//Increment the progress bar by the incremental value.
    	[progressBar incrementBy:self.incrementNumber];
    	
    	for (i = self.startNumber; i <= self.endNumber; i = i + self.incrementNumber)
    	{
    		//Advance the progress bar to what "i" currently is at.
    		[progressBar setDoubleValue:i];
    
    		//Force the progress bar visual to update immiediately.
    		[progressBar displayIfNeeded];
    	}
    }
    
    @end
    






    When I run the program and start the loop (through a button action which invokes a method that calls another method with this loop in it) the indicator does not move at all. Yet I have tested with printf's to the console and the loop is working (just not the indicator!)

    Any help is greatly appreciated!
     
  2. `lowell` macrumors newbie

    Joined:
    Aug 20, 2009
    Location:
    San Diego
    #2
    your code is fine; i adapted it into an empty project and it works as expected. the problem looks like it might be in IB - how do you have things set up in there?

    Code:
    #import <Cocoa/Cocoa.h>
    
    @interface ProgressionController : NSObject {
    	IBOutlet NSButton *button;
    	IBOutlet NSProgressIndicator *progress;
    }
    
    - (IBAction) buttonClicked: (id) sender;
    
    @end
    
    @implementation ProgressionController
    
    - (IBAction) buttonClicked: (id) sender
    {
    	NSLog(@"-buttonClicked:");
    
    	[progress setMinValue:0];
    	[progress setMaxValue:100];
    	[progress incrementBy:10];
    	
    	for (int i = 0; i <= 100; i = i + 10) {
    		[progress setDoubleValue:i];
    		[progress displayIfNeeded];
    		
    		NSLog(@"%d", i);
    	}
    }
    @end
    

    [​IMG]

    [​IMG]

    [​IMG]
     
  3. Some Guy 555 thread starter macrumors regular

    Joined:
    May 26, 2009
    #3
    Yeah, I know the code is right, there is just some connection problem when accessing the one controller (that moves the progress bar) from the other controller.

    I have rewritten the program to have the main controller just do everything, and it works then... must it be in the original controller?

    Here is the original code:


    I used 2 controllers. Here are the header files and main files for each. All user interface stuff has been done correctly... (I hope?).

    PHP:
    //
    //  Benchmarker.h
    //  SpeedBench
    //
    //  Created by Jordan Johns on 09-09-01.
    //  Copyright 2009 University of Saskatchewan. All rights reserved.
    //

    #import <Cocoa/Cocoa.h>


    @interface Benchmarker NSObject 
    {
        
    float startNumberincrementNumberendNumber;
        
    IBOutlet NSProgressIndicator *progressBar;
        
    IBOutlet NSProgressIndicator *statusBar;
    }

    @
    property(readwritefloat startNumberincrementNumberendNumber;

    - (
    void)benchmark;

    @
    end
    PHP:
    //
    //  Benchmarker.m
    //  SpeedBench
    //
    //  Created by Jordan Johns on 09-09-01.
    //  Copyright 2009 University of Saskatchewan. All rights reserved.
    //

    #import "Benchmarker.h"


    @implementation Benchmarker

    @synthesize startNumberincrementNumberendNumber;

    -(
    void)benchmark
    {
        
    int i;
        
        
    //Set the progress bar's minimum value to the start number.
        
    [progressBar setMinValue:self.startNumber];
        
    //Set the progress bar's maximum value to the end number.
        
    [progressBar setMaxValue:self.endNumber];
        
        for (
    self.startNumberself.endNumberself.incrementNumber)
        {
            
    //Advance the progress bar to what "i" currently is at.
            
    [progressBar setDoubleValue:i];
            
            
    //Force the progress bar visual to update immiediately.
            
    [progressBar displayIfNeeded];
        }
    }

    @
    end
    PHP:

    //
    //  benchmarkController.h
    //  SpeedBench
    //
    //  Created by Jordan Johns on 09-09-01.
    //  Copyright 2009 University of Saskatchewan. All rights reserved.
    //

    #import <Cocoa/Cocoa.h>
    #import "Benchmarker.h"


    @interface benchmarkController NSObject 
    {
        
    /*
         SPECIAL NOTE:  In order to ensure the interface builder
         will recognize all outlets and actions when you add a
         controller, build the code and save all first or they
         may not all appear.
        */
        
    IBOutlet NSTextField *startField;
        
    IBOutlet NSTextField *incrementField;
        
    IBOutlet NSTextField *endField;
        
    IBOutlet NSTextField *statusField;
        
    IBOutlet NSProgressIndicator *progress;
        
        
    Benchmarker *benchmarker;
    }

    - (
    IBAction)startBenchmark:(id)sender;

    @
    end

    PHP:

    //
    //  benchmarkController.m
    //  SpeedBench
    //
    //  Created by Jordan Johns on 09-09-01.
    //  Copyright 2009 University of Saskatchewan. All rights reserved.
    //

    #import "benchmarkController.h"


    @implementation benchmarkController

    - (IBAction)startBenchmark:(id)sender
    {
        
    int i;
        
        
    benchmarker = [[Benchmarker alloc]init];
        
        [
    benchmarker setStartNumber:[startField floatValue]];
        
        [
    benchmarker setIncrementNumber:[incrementField floatValue]];
        
        [
    benchmarker setEndNumber:[endField floatValue]];
        
        
    //Call the method in the benchmarker class to start the benchmark.
        
    [benchmarker benchmark];
        
        
    /*
        [progress setMinValue:0.0];
        [progress setMaxValue:10000];
        
        for (i = 0; i < 10000; i++)
        {
            [progress setDoubleValue:i];
            [progress displayIfNeeded];
        }
        */
        
        //Once the benchmark completes this should display "complete".
        
    [statusField setStringValue:@"Complete"];
         
        
    //Free allocated memory for the instance of benchmarker.
        
    [benchmarker release];
    }
    @
    end

    Thats all the files that I actually added/changed. The "Benchmarker" class (which I treat as a controller just like benchmarkerController) is supposed to make the progress bar move... but it will only move apparently if I put the code in the benchmarkerController class. There has gotta be something simple goin wrong that I just can't see...
     
  4. Krevnik macrumors 68040

    Krevnik

    Joined:
    Sep 8, 2003
    #4
    Okay, I've actually read the code this time, and it is pretty obvious that Benchmarker's 'progressBar' and 'statusField' items are nil.

    You create Benchmarker INSIDE your benchmarkController, so IBOutlets don't get populated (the object has to be created by the NIB to get IBOutlets populated). If you have a Benchmarker in your NIB, benchmarkController should be getting a reference to it, not creating a new object.

    Also, as a side comment, splitting the code like that when you have two controllers is a little wonky. It is dividing code for the sake of dividing it, IMO.
     
  5. Some Guy 555 thread starter macrumors regular

    Joined:
    May 26, 2009
    #5
    Ah, so if I remove the line of code in benchmarkController.h that creates an object of class Benchmarker then Benchmarker will actually be able to make the progress indicator move?

    I think I understand now, thanks. Also, from what you are saying, since both Benchmarker and benchmarkController are both in the NIB then they both have access to each method/attribute in eachother without having to create an object with which to do that work? Sweet.
     
  6. Krevnik macrumors 68040

    Krevnik

    Joined:
    Sep 8, 2003
    #6
    You still need to LINK the two in the NIB for them to see each other. You need to create an IBOutlet in benchmarkController of type Benchmarker, and then link the Benchmarker in the NIB to the benchmarkController using IB.
     
  7. Some Guy 555 thread starter macrumors regular

    Joined:
    May 26, 2009
    #7
    Got it working now, big thanks to your advice :D


    Slowly but surely I will get the hang of using cocoa/objective-c.
     

Share This Page