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

ethana

macrumors 6502a
Original poster
Jul 17, 2008
836
0
Seattle, WA
Ok, this is probably a totally newbie question, but how do I make an NSString *moreInfo as a global string that can be changed, used, and obtained via any function?

I put NSString *moreInfo; above the @implementation block, and one function can use the string, but my touchesEnded:withEvent: function cannot. It pulls the string data back as "invalid".

Any quick ideas?
 
You define the NSString *moreInfo in the .h file, not in the .m. You put the definition in the interface section of the .h file, which will make the variable available anywhere in the class.

You have to allocate memory and instantiate the string once in the .m side of the class. This may be in the init method, or in viewDidLoad or something like that. Without being initiated, the variable will not be valid. You can instantiate moreInfo with something like this:

moreInfo = @"something";
 
Still having problems.... again, my touchesEnded:withEvent: function cannot get the string created in viewDidLoad. It pulls the string data back as "invalid". Here's my code after your suggestions:

AppViewController.h
Code:
#import <UIKit/UIKit.h>

@interface FamousBDayViewController : UIViewController {	
	
	NSString *moreInfo;
}

@end

AppViewController.m
Code:
#import "AppViewController.h"

@implementation AppViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
	if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
		moreInfo = @"http://www.starturl.com/";
	}
	return self;
}

/*
 Implement loadView if you want to create a view hierarchy programmatically
 - (void)loadView {
 }
 */

- (void)viewDidLoad {
moreInfo = @"http://www.myurl.com/";
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:moreInfo]];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
	// Return YES for supported orientations
	return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (void)didReceiveMemoryWarning {
	[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
	// Release anything that's not essential, such as cached data
}

- (void)dealloc {
	[super dealloc];
}

@end
 
Still having problems.... again, my touchesEnded:withEvent: function cannot get the string created in viewDidLoad. It pulls the string data back as "invalid". Here's my code after your suggestions:

AppViewController.h
Code:
#import <UIKit/UIKit.h>

@interface FamousBDayViewController : UIViewController {	
	
	NSString *moreInfo;
}

@end

AppViewController.m
Code:
#import "AppViewController.h"

@implementation AppViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
	if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
		moreInfo = @"http://www.starturl.com/";
	}
	return self;
}

/*
 Implement loadView if you want to create a view hierarchy programmatically
 - (void)loadView {
 }
 */

- (void)viewDidLoad {
moreInfo = @"http://www.myurl.com/";
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    [[UIApplication sharedApplication] openURL:[NSURL URLWithString:moreInfo]];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
	// Return YES for supported orientations
	return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

- (void)didReceiveMemoryWarning {
	[super didReceiveMemoryWarning]; // Releases the view if it doesn't have a superview
	// Release anything that's not essential, such as cached data
}

- (void)dealloc {
	[super dealloc];
}

@end

I am not positive, but I think you can do:
self.moreInfo = @"Testing";

And to test:
NSLog(self.moreInfo);
 
Shouldn't you have to alloc and init the variable?

Something like this?

moreInfo = [[NSString alloc] init];
moreInfo = @"My String Is This";

Then once no longer need the moreInfo variable (program termination or whenever) you should release the variable.

[moreInfo release];

If you don't to the alloc / init then whatever you put into moreInfo is subject to 'cleaning' by the internal memory handling routines... In other words, one second moreInfo could contain/point-to "Testing Testing Testing" and the next second it could become junk that points to nothing..

Dave
 
You can create some class files.. lets call them global.h and global.m.

In global.h before the @interface code, define your string with extern.

extern NSString *myGlobalString;

In global.m before the @implementation code define a value for the string, or at least give it a blank value

myGlobalString = @"";

In any file you need access to this string, add an include "global.h" in the header file and you should be able to use any externs you defined there.
 
I'm still trying to figure out using a simple string as a global.

I noticed that in your .h you don't have:

Code:
@property (nonatomic, copy) NSString *moreInfo;

right before @end


I also use:

Code:
self.moreInfo = @"...";



What I can't figure out is how to READ this information in a different class file. I added the .h at the top of my class file but what is the syntax to read it. To test I am using:

Code:
NSLog(self.moreInfo);

It doesn't like that

so I tried:

Code:
NSLog(myViewController.moreInfo);

doesn't like that either.
This should be and probably is quite easy.


also, don't forget to add under @implementation in your .m file

Code:
@synthesize moreInfo;
 
Shouldn't you have to alloc and init the variable?

Something like this?

moreInfo = [[NSString alloc] init];
moreInfo = @"My String Is This";

Then once no longer need the moreInfo variable (program termination or whenever) you should release the variable.

Not quite - objects work differently than simple types like into and float.
Your first line above creates a string object, and points newInfo at it.
Your second line creates *another* string, and points moreInfo at it.
Your first string gets lost (leaked) and you have no way to use it.

NStrings are immutable - once you create one, you can not "change" it - you can only create a new string and point your variable at it.

If you don't to the alloc / init then whatever you put into moreInfo is subject to 'cleaning' by the internal memory handling routines... In other words, one second moreInfo could contain/point-to "Testing Testing Testing" and the next second it could become junk that points to nothing..

Yes and No. Objects are 'cleaned' (dealloced) my internal routines when they get a release message *which sets their retain count to zero*. Objects have a retain count of one when init'ed, so they're not going to disappear on you.

Read this to learn more.
http://www.stepwise.com/Articles/Technical/2001-03-11.01.html

Re: your global question - make the string a property of your application delegate. It's easy to get the app delegate form any class, and access its properties.
 
I'm sorry to dig up this old thread, but I'm struggling with the same problem as the original poster. In my case I'm using an NSMutableString, but otherwise the problem is essentially the same.

I define the variable in the .h file like so:

Code:
#import <UIKit/UIKit.h>

@interface MyViewController : UIViewController {
	NSMutableString *gameSolution;
}

@property (nonatomic, copy) NSMutableString *gameSolution;

@end

I synthesize it:

Code:
@implementation MyViewController

@synthesize gameSolution;

And then I set the value by reading it from an SQLite database.

Code:
gameSolution = [NSMutableString stringWithUTF8String: (char *)sqlite3_column_text(compiledStatement, 0)];

All pretty simple stuff, and it all works.

The problem is that when I return to the ViewController after a button click, the value is gone. It's not being retained beyond the scope of the initial pass through the code. Once we leave to let the UI run, the value is lost.

Can someone please enlighten me as to why? It doesn't make sense to me...

Thanks!
 
Use self.gameSolution to assign it, otherwise you're just assigning the object to the new object but since it's an autoreleased object it's not getting retained thus the deallocation. Using the properties as they're intended results in proper memory management.
 
Code:
gameSolution = [NSMutableString stringWithUTF8String: (char *)sqlite3_column_text(compiledStatement, 0)];

All pretty simple stuff, and it all works.

The problem is that when I return to the ViewController after a button click, the value is gone. It's not being retained beyond the scope of the initial pass through the code. Once we leave to let the UI run, the value is lost.

Can someone please enlighten me as to why? It doesn't make sense to me...

Thanks!
The only reason this didn't work right was because you assigned a value that was autoreleased. If you retained it imediately, it would work just fine and is great if you don't change the value later (where getters/setters really shine).


To the OP.
Your code doesn't work because your defined @interface is for a class named "FamousBDayViewController" and your @implementation is for a class named "AppViewController" thus there is no ivar "moreInfo" to set or get...
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.