How to use Static Variable to save a string in objective-c? - ios

I want to use Static Var to save a NSString.
So I define a Static Var in a .h file like this:
#ifndef GlobalParameters_h
#define GlobalParameters_h
//access token
static NSString *applicationToken;
#endif
In class A, I change the static var like this:
#import "ClassA.h"
#import "GlobalParameters.h"
extern NSString *applicationToken;
#implementation ClassA
+ (void)parseResponse:(NSString *)response
{
NSDictionary *responseDic = [response objectFromJSONString];
NSString *token = [responseDic objectForKey:#"token"];
applicationToken = [token copy];
NSLog(#"%#",applicationToken);
}
When the debugger run to
applicationToken = [token copy];
I found the "applicationToken" is nil,but the next sentence
NSLog(#"%#",applicationToken);
can output the right value in console! And in ClassB , the "applicationToken" is nil too.
I don't know why the static var is nil. I think the compiler will find the definition of "applicationToken" in GlobalParameters.h.But why I can't modify the static value?
Thanks for your help:)

static global variable mean that it's own for every object-file it's used. So there is willbe own applicationToken for ClassA, ClassB.
To create global variable for all object-files you need this:
In GlobalParameters.h:
#ifndef GlobalParameters_h
#define GlobalParameters_h
//access token
extern NSString *applicationToken;
#endif
In GlobalRarameters.m:
#import "GlobalParameters.h"
NSString *applicationToken;
P.S. I hope you use ARC, because if not, then applicationToken = [token copy]; will cause memory leaks.

Hey Its working fine , I am checking like this
Once check the are you getting "responseDic" (or) not , Check the
The dictionary have token key
static NSString *applicationToken;
applicationToken = #"srinivas";
NSLog(#"%#",applicationToken);
NSDictionary *responseDic = [NSDictionary dictionaryWithObject:#"static" forKey:#"token"];
NSString *token = [responseDic objectForKey:#"token"];
applicationToken = [token copy];
NSLog(#"%#",applicationToken);
[AppDelegate parseResponse:responseDic];

Related

Objective c - create a variable name at runtime and evaluate its value

I have a few keys defined as static vars:
static NSString icon_0 = #"image_0.png";
static NSString icon_1 = #"some_image_with_a_different_name.png";
static NSString icon_3 = #"picure_of_a_bear.png";
now inside a datasource method where I get the indexpath i would like to create the variable name from a string:
-(UICollectionviewCell*)cellForIndexPath:(NSIndexPath *)path
{
NSString *varName = [NSString stringWithFormat:#"icon_%d",path.row];
// here I need the static NSString which corresponds to the var name created
// i.e
NSString imageName;
if (indexPath.row == 0)
{
imageName = #"image_0.png";
}
// would be much nicer to do something like
NSString *imageName = [varName evaluate]; // get the content out of it...
}
How can I do this on static variable?
I tried
NSString *iconName = [self valueForKey:str];
but it isn't an iVar so not working...
i'd not use static vars but a static dictionary like this:
runnable example:
#import <Foundation/Foundation.h>
NSDictionary *DDImageName(NSString *varName);
NSDictionary *DDImageName(NSString *varName) {
static NSDictionary *dict = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//TODO
//add all names and the image names here
dict = #{#"icon_0": #"image_0.png",
#"icon_1": #"some_image_with_a_different_name.png",
#"icon_2": #"picure_of_a_bear.png"};
});
return dict[varName];
}
//demo only
int main(int argc, char *argv[]) {
#autoreleasepool {
NSString *varName = #"icon_0";
NSString *imgName = DDImageName(varName);
NSLog(#"imageName for %# = %#", varName, imgName);
}
}
If you make your variables instance variables or properties of an object, then you could use key value coding (KVC) to read and write values to them:
-(UICollectionviewCell*)cellForIndexPath:(NSIndexPath *)path
{
NSString *varName = [NSString stringWithFormat:#"icon_%d",path.row];
// here I need the static NSString which corresponds to the var name created
// i.e
NSString imageName;
if (indexPath.row == 0)
{
[self setValue = #"image_0.png" forKey: varName];
}
}
or
string = [self valueForKey: varName];
As #Daij-Djan points out, though, it's probably better to refactor your code to save your information to a dictionary rather than trying to manipulate your instance variables using string variable names. KVC is fairly slow, and will crash your program if a key doesn't exist at runtime, so it's fragile.

How to convert NSString to NSObject?

In my project i need to compare and NSString with NSObject. How to convert NSString to NSObject. OR Is there any chance to compare NSString with NSObject.
NSString class itself inherits from NSObject class, So you can directly compare them, see below code or check this link
NSString *str = #"xyz";
NSObject *obj = #"xyz";
if([str isEqualToString:(NSString *)obj]) {
NSLog(#"comparision successful");
}
If your NSObject is indeed an NSString, you can just cast it;
NSString *text = (NSString*)someObject;
Where someObject is the object you want to be a string. If you're not sure if the object is an NSString, you can check by doing the following;
if ([someObject class] == [NSString class){
NSString *text = (NSString*)someObject;
}
Hope that helps.

how to centralize the way you set icons with enum and singleton in an app

Okey!
So how can I centralizing the way I set my icons in a larger scale project.
Insted of setting icons with [UIImage ImageNamed: #"iconNamed"]; everywhere and having to look into all the places in your project to change the string whenever an icon is being changed
and insted of having a long list of method implementations returning a string.
The end result should be like:
Alternatively just have constants defined like Apple does for global keys...
In the .h file:
extern NSString *const kIconMenuSmallWht;
extern NSString *const kIconMenuBigWht;
extern NSString *const kIconShoppingSmall;
extern NSString *const kIconShoppingBig;
extern NSString *const kIconSleepingSmall;
extern NSString *const kIconSleepingBig;
In the .m file:
NSString *const kIconMenuSmallWht = #"ag_icons_btn_menu_wht";
NSString *const kIconMenuBigWht = #"c";
NSString *const kIconShoppingSmall = #"ag_icons_idx_ico_shopping_wht";
NSString *const kIconShoppingBig = #"ag_icons_idx_ico_shopping_wht";
NSString *const kIconSleepingSmall = #"ag_icons_idx_ico_shopping_wht_120";
NSString *const kIconSleepingBig = #"ag_icons_idx_ico_hotel_wht_120";
These are constants... global variables are not always bad!
(and many feel singletons are just globals anyway and are just as evil)
This will also give autocomplete in Xcode and have a single place to go for updates/changes but is simpler and has no method calls or objects to create so better performance (albeit likely infinitesimally better performance).
So first you create a .h file like #interface MyIcons : NSObject
and you kick off your singleton implementation with:
+(MyIcons *)sharedIcons ;
followed by:
typedef enum {
IconMenuSmallWht,
IconMenuBigWht,
IconShoppingSmall,
IconShoppingBig,
IconSleepingSmall,
IconSleepingBig,
} iconType;
- (NSString*) iconToString:(iconType) chooseIcon;
in the .m file you finish up your singleton implementation first:
+(MyIcons *)sharedIcons {
static dispatch_once_t once;
static MyIcons *sharedIcons = nil;
dispatch_once(&once, ^{
sharedIcons = [[self alloc] init];
});
return sharedIcons;
}
and you end with doing:
- (NSString*) iconToString:(iconType) chooseIcon {
NSString *result = nil;
switch(chooseIcon) {
case IconMenuSmallWht:
result = #"ag_icons_btn_menu_wht";
break;
case IconMenuBigWht:
result = #"c";
break;
case IconShoppingSmall:
result = #"ag_icons_idx_ico_shopping_wht";
break;
case IconShoppingBig:
result = #"ag_icons_idx_ico_shopping_wht_120";
break;
case IconSleepingSmall:
result = #"ag_icons_idx_ico_hotel_wht";
break;
case IconSleepingBig:
result = #"ag_icons_idx_ico_hotel_wht_120";
break;
return result;
}
Thats it. It just add icons to the enum and to this switch/case.
and wherevever you want to implement your icons you just #import MyIcons.h
add [MyIcons SharedIcons]iconToString: and voila you get your list of choosing.
Hope you enjoy this way of doing it. I know I will! (-:-)

gettin EXC_BAD_ACCESS while using nsstring

I am getting crazy during 4 hours and I really need help. Here is the code:
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
//check if strGroup has prefix and suffix #
BOOL result;
result = [strGroup hasPrefix: #"#"];
if (result)
{
result = [strGroup hasSuffix: #"#"];
if (result)
{
NSMutableString* string = [NSMutableString stringWithString: strGroup];
str = [strGroup substringWithRange: NSMakeRange (1, [string length]-2)];
strToHoldAllContact = [NSString stringWithFormat:#"%#",str];
}
}
NSLog(#"strToHoldAllContact=%#",strToHoldAllContact);
}
I am gettin the value of strToHoldAllContact correctly. But when I try to access strToHoldAllContact from another method I am getting the error:
[CFString respondsToSelector:]: message sent to deallocated instance 0x856f2a0
Use
strToHoldAllContact = [NSString stringWithFormat:#"%#",str];
[[strToHoldAllContact retain] autorelease];
and forget about release.
where ever you are initializing or setting the string do this [strToHoldAllContact retain]; and don't forget to release it once you are done using it
Just replace
strToHoldAllContact = [NSString stringWithFormat:#"%#",str];
to
strToHoldAllContact = [[NSString alloc] initWithFormat:#"%#",str];
And release it after you don't need it anymore.
with ARC, in .h declare strToHoldAllContact as:
#property(strong) NSString *strToHoldAllContact;
in .m, use it (after #synthesize) as self.strToHoldAllContact = [NSString stringWithFormat:#"%#",str];
this way you will not have problems.
without ARC,in .h declare strToHoldAllContact as:
#property(retain) NSString *strToHoldAllContact;
and use it same ways as with ARC in.m file.

In Objective-C, How Can I Make a Global Configuration That Is Accessible to All?

I am new to Objective-C and iOS development and I'm not sure if I'm doing it right. Anyway, basically I have a file Configs.plist which, for now has two sets of Keys:Value (Customer:Generic and Short_Code:Default). I want these data to be easily accessible to all classes so I created these:
Configs.h
extern NSString * const CUSTOMER;
extern NSString * const SHORT_CODE;
#interface Configs
+ (void)initialize;
+ (NSDictionary *)getConfigs;
#end
Configs.m
#import "Configs.h"
NSString * const CUSTOMER = #"Customer";
NSString * const SHORT_CODE = #"Short_Code";
static NSDictionary *myConfigs;
#implementation Configs
+ (void)initialize{
if(myConfigs == nil){
NSString *path = [[NSBundle mainBundle] pathForResource:#"Configs" ofType:#"plist"];
settings = [[NSDictionary alloc] initWithContentsOfFile:path];
}
}
+ (NSDictionary *)getConfigs{
return settings;
}
#end
And on a the test file Test.m:
NSLog(#"Customer: %#", [[Configs getConfigs] objectForKey:CUSTOMER]);
NSLog(#"Short Code: %#", [[Configs getConfigs] objectForKey:SHORT_CODE]);
The thing is, this approach works but I want to know if there are better ways to do this.
I think this is good as long as your configuration does not change during execution. If it does, you're better off with the singleton exposing your config as properties, so you would be able to do something like this:
[[Config shared] customer];
[[Config shared] setShortCode:#"CODE"];
You could still init the config from the plist, or implement coding protocol to store it in the NSUserDefaults.

Resources