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

AndyCodez

macrumors regular
Original poster
Aug 6, 2009
187
0
I have a method like the following called in a different class, this method sets a static NSString.

Code:
static NSString *histString;

+ (void) setTheString:(NSString*) str1
{
   histString = str1;
}

I then proceed to set histString to an array but the program crashes because the type is NSCFString. Am I missing something major here? I'm teaching myself objective c and I have not ran across this issue in the book I have.

Thanks for any help I have been stuck on this for 2 or 3 days.
 
NSString is a strange beast: it's toll-free bridged to CFString, and, I think it's underlying representation is a NSCFString. Nothing should be wrong with what you've posted, but where you say "I then proceed to set histString to an array" worrys me. What do you mean by this? Can you post code? You certainly can't do (for instance)

Code:
char[] myChars = histString;

and expect it to work.
 
I'm at work right now, but if i remember correctly it something along these lines:

Code:
NSMutableArray *histArray;

[histArray addObject:histString];

Which I had something like [histArray addObject:mad:"Cake"]; or
NSString *strShort = @"Cake";
[histArray addObject:strShort];

and those worked fine.
 
The only thing I can suggest is to post all the code and the exact error when you can...

Ok thanks :) I'll do it while I'm on lunch. Basically it doesn't error, it will crash the program when trying to set [histArray addObject:histString]; I assumed it was because histString was of type NSCFString.

Do you know why methods with NSString params are set to type NSCFString instead of NSString that I had specified in the method declaration?
 
If it just crashes then post what you see in the debugger.

My understanding is that every NSString is always really a NSCFString as is every CFString. Nothing turns an NSString into a NSCFString: it was always one.
 
Here is the code:

Code:
@interface HistoryTableViewController : UIViewController {
	NSMutableArray *histList;
	
}

static NSString *historyString;
static NSString *histStringOperator;
static NSString *histStringVal1;
static NSString *histStringVal2;

// History methods
+ (void) setHistoryStringTotal:(NSString*) hString;
+ (void) setHistoryStringVal1:(NSString*) hString1;
+ (void) setHistoryStringVal2:(NSString*) hString2;
+ (void) setHistoryStringOperator:(NSString*) op;
+ (NSString*) retHistoryString;

@end

Code:
@implementation HistoryTableViewController


+ (void) setHistoryStringTotal:(NSString*) hString
{
	historyString = histStringVal1;
	historyString = [historyString stringByAppendingString:(histStringOperator)];
	historyString = [historyString stringByAppendingString:(histStringVal2)];
	historyString = [historyString stringByAppendingString:(hString)];
}

+ (void) setHistoryStringVal1:(NSString*) hString1
{
	histStringVal1 = hString1;
	
}

+ (void) setHistoryStringVal2:(NSString*) hString2
{

	histStringVal2 = hString2;
}
+ (void) setHistoryStringOperator:(NSString*) op
{
	
	histStringOperator = op;
	
}

+ (NSString*) retHistoryString
{
	return historyString;
}

// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
	
	histList = [[NSMutableArray alloc] init];
	
	[histList addObject:historyString];
	[histList addObject:@"Pie"];
	
	self.navigationItem.title = @"Calculation History";
}

Shorter section of implementation of a different class, with out the .h
Code:
	switch(operation)
	{
		case 1:
			value = value + [Globals doubleVal];
			//DisplayText = [NSString stringWithFormat:@"%d", value];
			break;
		case 2:
			value = [Globals doubleVal] - value;
			//DisplayText = [NSString stringWithFormat:@"%d", value];
			break;
		case 3:
			value = ([Globals doubleVal]/value);
			//DisplayText = [NSString stringWithFormat:@"%d", value];
			break;
		case 4:
			value = value * [Globals doubleVal];
			//DisplayText = [NSString stringWithFormat:@"%d", value];
			break;
		default:
			DisplayText = @"";
	}
	
	[HistoryTableViewController setHistoryStringVal2:txtOutput.text];
	DisplayText = [Globals convertToString:(value)];
	[HistoryTableViewController setHistoryStringTotal:DisplayText];
	txtOutput.text = DisplayText;
	
	[Globals setHistString:(DisplayText)];

	storedNum = 0;
		
}

//Operation =  1 = add, 2 = subract, 3 = divide, 4 = multiply
- (IBAction) btnAddPress:(id) sender
{
	//Store the first number
	[Globals setVal:([txtOutput.text floatValue])];
	[HistoryTableViewController setHistoryStringVal1:(txtOutput.text)];
	[HistoryTableViewController setHistoryStringOperator:@" + "];
		
	//clear out the textbox
	txtOutput.text = @"";
	
	//Set the operation for when the user hits enter
	operation = 1;
}

- (IBAction) btnSubtractPress:(id) sender
{
	[Globals setVal:([txtOutput.text floatValue])];
	[HistoryTableViewController setHistoryStringVal1:(txtOutput.text)];
	[HistoryTableViewController setHistoryStringOperator:@" - "];
	
	//clear out the textbox
	txtOutput.text = @"";
	
	//Set the operation for when the user hits enter
	operation = 2;
}

- (IBAction) btnDividePress:(id) sender
{
	[Globals setVal:([txtOutput.text floatValue])];
	[HistoryTableViewController setHistoryStringVal1:(txtOutput.text)];
	[HistoryTableViewController setHistoryStringOperator:@" / "];
	
	//clear out the textbox
	txtOutput.text = @"";
	
	//Set the operation for when the user hits enter
	operation = 3;
}

- (IBAction) btnMultiplyPress:(id) sender
{
	[Globals setVal:([txtOutput.text floatValue])];
	[HistoryTableViewController setHistoryStringVal1:(txtOutput.text)];
	[HistoryTableViewController setHistoryStringOperator:@" X "];
	
	//clear out the textbox
	txtOutput.text = @"";
	
	//Set the operation for when the user hits enter
	operation = 4;
}

When it crashes it says that histStringVal1 variable is invalid when I scroll over it to see what the value is while debugging. I'm not sure why it would be erroring I was thinking that its because of where the static methods are declared outside of the interface of the class, but you cant have variables in class methods that are in the interface for some reason... I get an error when I try to do that. I'll post more when I get back to work :) Thanks!
 
A setter whose parameter is an object has to retain that object.

You're not retaining the strings in several places in your code and they are being autoreleased so they become invalid.
 
A setter whose parameter is an object has to retain that object.

You're not retaining the strings in several places in your code and they are being autoreleased so they become invalid.

So basically i should be using [theString retain]; after i use it when its being called from a different class, in the setter of the static variable? I'm just learning all of this memory management stuff, never really had to worry about it before. I know i wouldn't need to do that with a type such as an Int, correct?

It seems there is a steep learning curve on objective C. At work I use Visual FoxPro (old school lol), and use a software from a company called HighJump for warehouse management development. Yes its terrible and old as well.

Having a good time learning objective c and the iphone SDK, except when i run into issues like this where I'm stuck for a few days!
 
Since we have entered the days of the @property writing a correct setter seems to be a lost art.

I can't see from what you posted why your methods are class methods. If it's possible to make them instance methods then do that. Then use @property to make your setters and getters. This will make your code more likely to be correct.
 
Well i assumed the + (void) ect is what makes it a class method vs - makes it an instance method.
 
Yep that was the problem I needed to have [theString retain]; in the setter. I didn't realize that those variables would be released every time the application leaves the scope.

Thanks phoney that really helped and I'll make sure to remember that!
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.