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

glossywhite

macrumors 65816
Original poster
Feb 28, 2008
1,120
3
Hi there. Objective C is extremely fiddly and convoluted, in my eyes. I want to take this code:

Code:
@implementation appController
int cnt,rsz=0;

-(IBAction)sendText:(id)sender{
	[myText setStringValue:[sourceText stringValue]];
	[myButton setTitle:@"clicked"];
}
-(void)windowDidResize:(NSNotification *)winSize{
	NSLog(@"The window did resize");
	rsz++;
	NSLog(@"Window resizes: %i",rsz);
}
-(void)windowDidMove:(NSNotification *)winMove{
	NSLog(@"The window did move");
	cnt++;
	NSLog(@"Window moved %i times",cnt);
}
-(void)windowDidMiniaturize:(NSNotification *)winMin{
	NSLog(@"Window went to Dock");
}
-(void)windowDidDeminiaturize:(NSNotification *)winUnMin{
	NSLog(@"Window came from Dock");
}
@end

... and I want the number of times the window was moved, to be output to a label. I am told I need to do some kind of string conversion :confused: whatever that means, and had some smartass IRC guy keep linking me to Apple's documents, when in fact, all I wanted was a little help (this is why IRC earns it's rep as code snobs!!).

Please - what do I convert to what, FROM what?. I just want the value stored in 'cnt' to be output to a label - can it be THAT hard to explain?.

Thanks.
 
The docs are actually very good, and i'm going to link them here, but hopefully this will be a bit more helpful:
http://developer.apple.com/mac/libr.../apple_ref/occ/clm/NSString/stringWithFormat:

You should be able to get an NSString with the value of your number like this:
Code:
NSString *myCntString = [NSString stringWithFormat:@"%d",cnt];

You can then use setStringValue: on the label to set it to myCntString.

-Lee

EDIT: There are tons of ways to do this, this is the first that occurred to me... you could do:
Code:
NSString *myCntString = [[NSNumber numberWithInt:cnt] stringValue];
 
You need something like this:

Code:
NSString* convertedStr = [NSString stringWithFormat: @"%d", cnt];

"%d" specifies a signed 32-bit int (see here if you want to convert anything other than an int).

Hope that helps..
 
Failed.
 

Attachments

  • Screen shot 2009-11-03 at 17.50.21.png
    Screen shot 2009-11-03 at 17.50.21.png
    129.2 KB · Views: 118
You can't put method calls outside of a class. They must go inside a class method, such as init.

You should also declare those as instance variables, not just global.

And for that warning about NSTextField, use setStringValue: - setTitle: is for buttons.
 
You can't put method calls outside of a class. They must go inside a class method, such as init.

You should also declare those as instance variables, not just global.

And for that warning about NSTextField, use setStringValue: - setTitle: is for buttons.

??? could you speak in English please :D

I got the setTitle part - I worked that out, thanks.
 
Wot kainjow said u above.. :)

You just need to to put that line in a method. So, in windowDidMove, you could update the textfield that shows the cnt variable.

Edit; too late again!
 
Fixed it guys:

Code:
#import "appController.h"


@implementation appController
int cnt,rsz,std=0;


-(IBAction)sendText:(id)sender{
	[myText setStringValue:[sourceText stringValue]];
	[myButton setTitle:@"clicked"];
}
-(void)windowDidResize:(NSNotification *)winSize{
	NSLog(@"The window did resize");
	rsz++;
	NSString *myMove = [NSString stringWithFormat:@"Resized: %i times",rsz];
	[resizedLbl setStringValue:myMove];
}
-(void)windowDidMove:(NSNotification *)winMove{
	NSLog(@"The window did move");
	cnt++;
	NSString *myCnt = [NSString stringWithFormat:@"Moved: %i times",cnt];
	[lbl setStringValue:myCnt];
}
-(void)windowDidMiniaturize:(NSNotification *)winMin{
	NSLog(@"Window went to Dock");
	std++;
	NSString *sent = [NSString stringWithFormat:@"Sent to Dock: %i times",std];
	[sentToDock setStringValue:sent];
}
-(void)windowDidDeminiaturize:(NSNotification *)winUnMin{
	NSLog(@"Window came from Dock");
}
@end

Thanks! :)
 
When you declare instance variables you should do it in the @interface part to make them instance variables of your class. Like local variables for functions, instance variables are for a specific instance of a class.

The way you have it now, they are global variables.
 
Arrgh coding is SO confusing - I'd much rather do industrial design! :(

Arrgh industrial design is SO confusing! I have this square peg and this round hole...

You ran into the computational equivalent. Unfortunately, even for a very young field like software engineering, there's lots of legacy. And it's not always clear what is "better". One camp might say "Let's solve this once and for all. Let's make all pegs round!" whereas the other will say "No, let's standardize on square holes."

Coding need not be confusing, as long as you take small steps and make sure you really understand what's going on before you take the next.
 
Coding need not be confusing, as long as you take small steps and make sure you really understand what's going on before you take the next.

I completely agree. You need to pickup Programming in Objective-C 2.0 by Kochan.
http://www.amazon.com/Programming-O...=sr_1_1?ie=UTF8&s=books&qid=1257357587&sr=8-1
If you work through some of the examples in this book you will not make these kinds of mistakes and it will make a whole lot more sense.

Object oriented programming is not something you jump into like PHP or even C. You need to take some time to learn conceptually why we do things the way we do, so that when you want to start programming things on your own you have an instinctive toolset to accomplish your goals.

EDIT: on a side note, in my current project I get an odd warning that says "Initialization from distinct Objective-C type" for
Code:
NSMutableCharacterSet *setToSkip = [[NSMutableCharacterSet decimalDigitCharacterSet] invertedSet];
	[setToSkip removeCharactersInString: @"."];

The code works perfectly at runtime, NSMutableCharacterSet is a subclass of NSCharacterSet right? so I should be able to make this call. I guess I don't understand the error, and haven't bothered to play with it since the code snip works.
 
As an Amazon Associate, MacRumors earns a commission from qualifying purchases made through links in this post.
EDIT: on a side note, in my current project I get an odd warning that says "Initialization from distinct Objective-C type" for
Code:
NSMutableCharacterSet *setToSkip = [[NSMutableCharacterSet decimalDigitCharacterSet] invertedSet];
	[setToSkip removeCharactersInString: @"."];

The code works perfectly at runtime, NSMutableCharacterSet is a subclass of NSCharacterSet right? so I should be able to make this call. I guess I don't understand the error, and haven't bothered to play with it since the code snip works.

invertedSet returns an NSCharacterSet according to the documentation, so you should double-check to see if that's a bug or not, because if it's not mutable removeCharactersInString would probably fail.

I'd change it to this:
Code:
[[[[NSCharacterSet decimalDigitCharacterSet] invertedSet] mutableCopy] autorelease];
 
invertedSet returns an NSCharacterSet according to the documentation, so you should double-check to see if that's a bug or not, because if it's not mutable removeCharactersInString would probably fail.

I'd change it to this:
Code:
[[[[NSCharacterSet decimalDigitCharacterSet] invertedSet] mutableCopy] autorelease];

I assumed it was something like that, but it certainly works. I'm running a scanner to look for doubles inside a string, and I don't want it to skip . since .25 and 25 are different numbers! I know it doesn't skip . because if the string has no double but has a period it will keep looking for a double indefinitely. (I made a counter to abort scanning if it can't find a double for a set number of tries)

That said I just noticed NSMutableCharacterSet has an instance method - invert which is even better.

Because of the fact that it did work before, I assume that NSMutableCharacterSet overrides +invertedSet to return an inverted mutable set.

EDIT: also if it returned NSCharacterSet instead of NSMutableCharacterSet, it should have an exception at runtime for sending it -removeCharactersInString:. So it's almost certain that it returns a NSMutableChararcterSet. Either way I changed it use -invert then -removeCharactersInString: and it doesn't "warn" me about anything and still runs.
 
When you declare instance variables you should do it in the @interface part to make them instance variables of your class. Like local variables for functions, instance variables are for a specific instance of a class.

The way you have it now, they are global variables.

Do you mean like this?:

Code:
#import <Cocoa/Cocoa.h>


@interface appController : NSObject {
	
	IBOutlet NSTextField *myText;
	IBOutlet NSButton *myButton;
	IBOutlet NSTextField *sourceText;	IBOutlet NSTextField *lbl;
	IBOutlet NSTextField *resizedLbl;
	IBOutlet NSTextField *sentToDock;
	
}
-(IBAction)sendText:(id)sender;
int cnt,rsz,std=0;
@end
 
Do you mean like this?:

Code:
#import <Cocoa/Cocoa.h>


@interface appController : NSObject {
	
	IBOutlet NSTextField *myText;
	IBOutlet NSButton *myButton;
	IBOutlet NSTextField *sourceText;	IBOutlet NSTextField *lbl;
	IBOutlet NSTextField *resizedLbl;
	IBOutlet NSTextField *sentToDock;
	
}
-(IBAction)sendText:(id)sender;
int cnt,rsz,std=0;
@end

I don't think you can initialise them in the interface file: you should do this in your init method.
 
I don't think you can initialise them in the interface file: you should do this in your init method.

It's called an .m (main) file, not an interface file, and post #9 said to do what I have done :confused:

MORE proof that Objective-C is just plain confusing!
 
It's not necessary to initialize ivars to 0 or nil. The alloc method guarantees that all ivars in the new object are zeroed. This is described in the basic reference docs.

Besides that, this is bad form:

int cnt,rsz,std=0;

It defines three variables, but only initializes one of them. If the variables are static, they are already initialized to zero (guaranteed by C runtime).

Finally, if the variables are intended to be ivars, they need to be declared between the {}'s, not outside of them. Re-read the basic reference docs on how to define a class with ivars (instance variables).
 
It's not necessary to initialize ivars to 0 or nil. The alloc method guarantees that all ivars in the new object are zeroed. This is described in the basic reference docs.

Besides that, this is bad form:

int cnt,rsz,std=0;

It defines three variables, but only initializes one of them.

No, in C the above declares all as type INT and gives them ALL the value of 0. As Objective-C is a superset of C, then I see no reason why this won't work, do you? :confused:
 
No, in C the above declares all as type INT and gives them ALL the value of 0. As Objective-C is a superset of C, then I see no reason why this won't work, do you? :confused:

If the variables are static, they are zeroed because static variables default to zero. In other words, removing the initializer would have no effect, because static variables are guaranteed to be zero initially.

If the variables are local (which they aren't in the given context), then only the last one is initialized. This is true in C, AFAIK. If you can cite a standard that says otherwise, please do.

If the variables are ivars (which they aren't in the given context), then the initializer again has no effect, because alloc zeros all ivars.
 
I would put your instance variables within the braces (as below). I don't know if this is strictly necessary, but I think it's neater/simpler to keep variables and methods separate.

As for the other issue, I would have guessed chown33 was right, to me your line looks like it's only initialising the last variable.

But also as he said, you don't need to initialise instance variables to zero; a nice little time-saver.

Code:
#import <Cocoa/Cocoa.h>

@interface appController : NSObject {
	
	IBOutlet NSTextField *myText;
	IBOutlet NSButton *myButton;
	IBOutlet NSTextField *sourceText;	
        IBOutlet NSTextField *lbl;
	IBOutlet NSTextField *resizedLbl;
	IBOutlet NSTextField *sentToDock;
        int cnt;
        int rsz;
        int std;	
}
-(IBAction)sendText:(id)sender;

@end
 
I would put your instance variables within the braces (as below). I don't know if this is strictly necessary, but I think it's neater/simpler to keep variables and methods separate.

As for the other issue, I would have guessed chown33 was right, to me your line looks like it's only initialising the last variable.

But also as he said, you don't need to initialise instance variables to zero; a nice little time-saver.

Code:
#import <Cocoa/Cocoa.h>

@interface appController : NSObject {
	
	IBOutlet NSTextField *myText;
	IBOutlet NSButton *myButton;
	IBOutlet NSTextField *sourceText;	
        IBOutlet NSTextField *lbl;
	IBOutlet NSTextField *resizedLbl;
	IBOutlet NSTextField *sentToDock;
        int cnt;
        int rsz;
        int std;	
}
-(IBAction)sendText:(id)sender;

@end

So why on EARTH must there be three lines of code, when one would suffice:

Code:
#import <Cocoa/Cocoa.h>


@interface appController : NSObject {
	IBOutlet NSTextField *myText;
	IBOutlet NSButton *myButton;
	IBOutlet NSTextField *sourceText;	IBOutlet NSTextField *lbl;
	IBOutlet NSTextField *resizedLbl;
	IBOutlet NSTextField *sentToDock;
	int cnt,rsz,std;

}

-(IBAction)sendText:(id)sender;

@end

Just tried it and that works ^^
 
So why on EARTH must there be three lines of code, when one would suffice:

You don't strictly need to put each variable on a separate line, you can put them all on one line if you so choose. As a matter of practice, I always put them one per line:

- Easier to read.
- Easier to add a comment per variable.
- Avoids confusion with initialisation, or with pointers.

E.g.
Code:
int* a, b, c;

Is that declaring 3 integer pointers, or one integer pointers and two integers? With one declaration per line, there's never such confusion.

But use whatever works for you!!
 
So why on EARTH must there be three lines of code, when one would suffice:

It technically is the same, but I'd guess many would prefer them being on their own lines for readability.

Also, you should avoid naming variables cryptically. Just use "count" instead of "cnt". There is no need to condense everything to save "space" ;)

I work with someone who likes to keep variable names as short as possible, preferring mysterious acronyms, or suffixing similar variables with a counter (like n, n0, etc.). When working on large projects it gets very old very fast.
 
So why on EARTH must there be three lines of code, when one would suffice:

Code:
#import <Cocoa/Cocoa.h>


@interface appController : NSObject {
	IBOutlet NSTextField *myText;
	IBOutlet NSButton *myButton;
	IBOutlet NSTextField *sourceText;	IBOutlet NSTextField *lbl;
	IBOutlet NSTextField *resizedLbl;
	IBOutlet NSTextField *sentToDock;
	int cnt,rsz,std;

}

-(IBAction)sendText:(id)sender;

@end
So why on EARTH must there be twelve lines of code, when two would suffice:
Code:
#import <Cocoa/Cocoa.h>
@interface appController : NSObject {IBOutlet NSTextField *myText; IBOutlet NSButton *myButton; IBOutlet NSTextField *sourceText; 	IBOutlet NSTextField *lbl; IBOutlet NSTextField *resizedLbl; IBOutlet NSTextField *sentToDock; int cnt,rsz,std; } -(IBAction)sendText:(id)sender; @end
;)
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.