Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

Some Guy 555

macrumors regular
Original poster
May 26, 2009
194
0
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!
 
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


Vqgwv.png


gUQWH.png


4hpu8.png
 
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 startNumber, incrementNumber, endNumber;
	IBOutlet NSProgressIndicator *progressBar;
	IBOutlet NSProgressIndicator *statusBar;
}

@property(readwrite) float startNumber, incrementNumber, endNumber;

- (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 startNumber, incrementNumber, endNumber;

-(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 (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

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...
 
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.
 
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.

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.
 
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.
 
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.

Got it working now, big thanks to your advice :D


Slowly but surely I will get the hang of using cocoa/objective-c.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.