PDA

View Full Version : How do I take a C string and use it in a label?




glossywhite
Nov 3, 2009, 10:46 AM
Hi there. Objective C is extremely fiddly and convoluted, in my eyes. I want to take this 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.



lee1210
Nov 3, 2009, 10:54 AM
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/library/documentation/cocoa/reference/Foundation/Classes/NSString_Class/Reference/NSString.html#//apple_ref/occ/clm/NSString/stringWithFormat:

You should be able to get an NSString with the value of your number like this:

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:

NSString *myCntString = [[NSNumber numberWithInt:cnt] stringValue];

whooleytoo
Nov 3, 2009, 10:59 AM
You need something like this:


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


"%d" specifies a signed 32-bit int (see here (http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/Strings/Articles/formatSpecifiers.html#//apple_ref/doc/uid/TP40004265) if you want to convert anything other than an int).

Hope that helps..

glossywhite
Nov 3, 2009, 11:51 AM
Failed.

kainjow
Nov 3, 2009, 11:52 AM
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.

glossywhite
Nov 3, 2009, 11:57 AM
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.

whooleytoo
Nov 3, 2009, 11:58 AM
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!

glossywhite
Nov 3, 2009, 12:24 PM
Fixed it guys:

#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! :)

jared_kipe
Nov 3, 2009, 04:04 PM
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.

glossywhite
Nov 3, 2009, 06:43 PM
Arrgh coding is SO confusing - I'd much rather do industrial design! :(

Sander
Nov 4, 2009, 05:11 AM
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.

jared_kipe
Nov 4, 2009, 12:03 PM
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-Objective-C-2-0-Stephen-Kochan/dp/0321566157/ref=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
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.

kainjow
Nov 4, 2009, 12:11 PM
EDIT: on a side note, in my current project I get an odd warning that says "Initialization from distinct Objective-C type" for
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:
[[[[NSCharacterSet decimalDigitCharacterSet] invertedSet] mutableCopy] autorelease];

jared_kipe
Nov 4, 2009, 12:37 PM
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:
[[[[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.

glossywhite
Nov 5, 2009, 08:59 AM
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?:

#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

robbieduncan
Nov 5, 2009, 09:39 AM
Do you mean like this?:

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

glossywhite
Nov 5, 2009, 11:51 AM
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!

chown33
Nov 5, 2009, 11:55 AM
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).

glossywhite
Nov 5, 2009, 11:59 AM
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:

chown33
Nov 5, 2009, 12:05 PM
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.

whooleytoo
Nov 5, 2009, 12:05 PM
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.


#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

glossywhite
Nov 5, 2009, 12:07 PM
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.


#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:


#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 ^^

whooleytoo
Nov 5, 2009, 12:14 PM
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.

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

kainjow
Nov 5, 2009, 12:16 PM
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.

dejo
Nov 5, 2009, 12:19 PM
So why on EARTH must there be three lines of code, when one would suffice:


#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:
#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

;)

glossywhite
Nov 5, 2009, 12:28 PM
So why on EARTH must there be twelve lines of code, when two would suffice:
#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

;)

Your comparison to my comment is illogical. My point is valid.

dejo
Nov 5, 2009, 12:37 PM
Your comparison to my comment is illogical. My point is valid.
I thought my comparison was perfectly logical. My point was: readability.

glossywhite
Nov 5, 2009, 01:34 PM
I thought my comparison was perfectly logical. My point was: readability.

Your point had nothing whatsoever to do with the fact that:


int cnt,rsz,std;


is MUCH neater and more concise than:


int cnt;
int rsz;
int std;


which completely wastes space.

Your example is just out of context, and completely nothing to do with mine.

dejo
Nov 5, 2009, 01:46 PM
Your example is just out of context, and completely nothing to do with mine.
Let's just chalk this up to differences in opinion with regards to coding style and leave it at that. Sorry to have brought it up.

chown33
Nov 5, 2009, 01:56 PM
IBOutlet NSTextField *sourceText;
IBOutlet NSTextField *lbl;
IBOutlet NSTextField *resizedLbl;
IBOutlet NSTextField *sentToDock;

Such a waste space. Rewrite it as:

IBOutlet NSTextField *srcText,*lbl,*rszdLbl,*snt2Dk;

glossywhite
Nov 5, 2009, 02:07 PM
IBOutlet NSTextField *sourceText;
IBOutlet NSTextField *lbl;
IBOutlet NSTextField *resizedLbl;
IBOutlet NSTextField *sentToDock;

Such a waste space. Rewrite it as:

IBOutlet NSTextField *srcText,*lbl,*rszdLbl,*snt2Dk;


:p so true, so true - how could I have missed that?! :o

Having said that, I don't like to use too many abbreviations; theBestThingAboutObjectivecIsThatYouWriteCamelTextLikeThisToPreventAmbiguityFromOccuring

lee1210
Nov 5, 2009, 02:10 PM
There's really an argument about this going on? This is definitely a style issue. Both styles are perfectly valid. Maybe i need to get rid of variable declarations all the time and deleting a line is faster for me than picking out the variable from a list. Maybe my monitor is wider than it is tall, so i can't get a lot of lines on a screen at once, so keeping line count down is really important. Maybe i'm getting paid per line of code so i need as much verbosity as possible.

The point is, different strokes for different folks. At runtime there will be no difference, and at compile time it will be extremely negligible, so do what's consistent with others on your project, and if you're it, do what you like.

-Lee

glossywhite
Nov 5, 2009, 02:16 PM
There's really an argument about this going on? This is definitely a style issue. Both styles are perfectly valid. Maybe i need to get rid of variable declarations all the time and deleting a line is faster for me than picking out the variable from a list. Maybe my monitor is wider than it is tall, so i can't get a lot of lines on a screen at once, so keeping line count down is really important. Maybe i'm getting paid per line of code so i need as much verbosity as possible.

The point is, different strokes for different folks. At runtime there will be no difference, and at compile time it will be extremely negligible, so do what's consistent with others on your project, and if you're it, do what you like.

-Lee

Who's arguing? :D

dejo
Nov 5, 2009, 02:21 PM
Having said that, I don't like to use too many abbreviations...
You sure about that?

int cnt,rsz,std;

:D

lee1210
Nov 5, 2009, 02:34 PM
Your comparison to my comment is illogical. My point is valid.

I thought my comparison was perfectly logical. My point was: readability.

Your point had nothing whatsoever to do with the fact that:
..
is MUCH neater and more concise than:
...
which completely wastes space.

Your example is just out of context, and completely nothing to do with mine.

...
Such a waste space. Rewrite it as:
...

Reads a bit like an argument to me. Heated discussion, then? =)

-Lee

glossywhite
Nov 5, 2009, 03:27 PM
I often have my comments mis-interpreted as flaming or arguing, when, in fact, that may not be my intention. I am a passionate person, and I apologise if my comments come across as rude or argumentative - I don't mean them to be, in ANY way. :D