PDA

View Full Version : Make an NSString global?




ethana
Aug 2, 2008, 05:29 PM
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?



gralem
Aug 2, 2008, 05:56 PM
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";

ethana
Aug 2, 2008, 06:11 PM
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

#import <UIKit/UIKit.h>

@interface FamousBDayViewController : UIViewController {

NSString *moreInfo;
}

@end


AppViewController.m

#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

Garrett
Aug 3, 2008, 03:51 AM
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

#import <UIKit/UIKit.h>

@interface FamousBDayViewController : UIViewController {

NSString *moreInfo;
}

@end


AppViewController.m

#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);

DaveGee
Aug 3, 2008, 10:09 AM
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

johnnybluejeans
Aug 3, 2008, 10:59 AM
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.

mcannell
Dec 22, 2008, 02:18 AM
I'm still trying to figure out using a simple string as a global.

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

@property (nonatomic, copy) NSString *moreInfo;

right before @end


I also use:

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:

NSLog(self.moreInfo);

It doesn't like that

so I tried:

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

@synthesize moreInfo;

xsmasher
Dec 23, 2008, 02:25 AM
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.

chameleon
Jun 30, 2010, 09:59 PM
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:


#import <UIKit/UIKit.h>

@interface MyViewController : UIViewController {
NSMutableString *gameSolution;
}

@property (nonatomic, copy) NSMutableString *gameSolution;

@end

I synthesize it:


@implementation MyViewController

@synthesize gameSolution;

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


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!

kainjow
Jun 30, 2010, 10:05 PM
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.

chameleon
Jun 30, 2010, 10:23 PM
Use self.gameSolution to assign it

Bingo! And there it is. It's just that simple.

I would have never thought of it, so THANK YOU for the help!

jared_kipe
Jul 1, 2010, 03:55 PM
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...