Constant in objective-c - iphone

I would like to add some constant keys for my application, these constants can be accessed anywhere in program. So I declare the constants in interface file:
#import <UIKit/UIKit.h>
NSString * MIN_INTERVAL_KEY = #"MIN_INTERVAL_KEY";
NSString * MAX_TOBACCO_KEY = #"MAX_TOBACCO_KEY";
NSString * ICON_BADGE = #"ICON_BADGE";
#interface SmokingViewController : UIViewController {
}
And I would like to access them from the MinIntervalViewController class:
- (void)viewDidAppear:(BOOL)animated {
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
if (user) {
self.selectedValue = [user objectForKey:MIN_INTERVAL_KEY];
}
[super viewDidAppear:animated];
}
But the application shows an error in the MinIntervalViewController class:
error: 'MIN_INTERVAL_KEY' undeclared (first use in this function)
Do I miss something? Any help would be appreciated.
Thanks

Constants.h
#import <Cocoa/Cocoa.h>
#interface Constants : NSObject {
}
extern int const kExampleConstInt;
extern NSString * const kExampleConstString;
#end
Constants.m
#import "Constants.h"
#implementation Constants
int const kExampleConstInt = 1;
NSString * const kExampleConstString = #"String Value";
#end
To use:
#import "Constants.h"
Then, simply call the specific variable you wish to use.
NSString *newString = [NSString stringWithString:kExampleConstString];

In the .h file:
extern NSString * const MIN_INTERVAL_KEY;
In one (!) .m file:
NSString * const MIN_INTERVAL_KEY = #"MIN_INTERVAL_KEY";
And what you seemed to have missed is to actually import the header file declaring MIN_INTERVAL_KEY ;-) So if you declared it in SmokingViewController.h but like to use it in MinIntervalViewController.m, then you need to import "SmokingViewController.h" in your MinIntervalViewController.m. Since Objective-C is really more or less an extension to C all C visibility rules apply.
Also, what helps to debug things like that is to right-click on the .m file in Xcode and select "Preprocess". Then you see the file preprocess, i.e. after CPP has done its work. This is what the C compiler REALLY is digesting.

Related

NSString custom md5 class method warning:

I have done I custom class method for NSString to md5 a NSString.
This is my code:
NSString+CustomMethod.h
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#interface NSString (CustomMethod)
+ (NSString*)MD5:(NSString *)string;
#end
NSString+CustomMethod.m
#import "NSString+CustomMethod.h"
#implementation NSString (CustomMethod)
+ (NSString*)MD5:(NSString *)string
{
// Create pointer to the string as UTF8
const char *ptr = [string UTF8String];
// Create byte array of unsigned chars
unsigned char md5Buffer[CC_MD5_DIGEST_LENGTH];
// Create 16 byte MD5 hash value, store in buffer
CC_MD5(ptr, strlen(ptr), md5Buffer);
// Convert MD5 value in the buffer to NSString of hex values
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x",md5Buffer[i]];
return output;
}
#end
This Methodclass works great, but compiler give me a warring:
warning: class method '+MD5:' not found (return type defaults to 'id') [3]
How can I remove this warning ??
PS: if a put #import "NSString+CustomMethod.h" no warning is shown, but it's a workAround, I have created a custom method class not to include my custom class everywhere I need it
Thanks for any helps !!
Put #import "NSString+CustomMethod.h" in .pch file or in file where you want to use it.

init my own api class

I have an API class, lets call it MyClass, which I want to be available thruout my whole application. Hence I put the #import into MyProject-Prefix.pch file.
Now, when I (in my appDelegate) initiate the class, I get the error message cannot init a class object..
I understand that I am initiating my class incorrectly, but I have no idea on how I should do it... and since this is not common for development (as I see it) there ain't a lot of information to find thrue google (or I am searching wrong ;) )
So, I have two questions:
Any links for called "Creating Objective-C API's for Dummys"? ;)
Having a quick look at my code, what am I doing wrong?
This is my class:
MyClass.h
#import <Foundation/Foundation.h>
#import <CommonCrypto/CommonDigest.h>
#import "NSStringAdditions.h"
#import "XMLRPCResponse.h"
#import "XMLRPCRequest.h"
#import "XMLRPCConnection.h"
/**
* END required libs
*/
extern int EID;
extern NSString * SHARED_SECRET;
extern NSString * MODE;
#interface MyClass : NSObject
+ (id)initWithEid:(int)eid secret:(NSString*)secret mode:(NSString*)mode;
+ (NSArray*)web_invoice_infoWithOCR:(NSString*)ocr pno:(NSString*)pno;
+ (NSString*)the_digest:(NSString*)source;
#end
MyClass.m
#import "MyClass.h"
#implementation MyClass
int EID;
NSString * SHARED_SECRET;
NSString * MODE;
NSString * URL_LIVE;
NSString * URL_BETA;
#pragma mark init / dealloc
+ (id)init {
self = [super init];
if (self)
{
}
return self;
}
+ (id)initWithEid:(int)eid secret:(NSString*)secret mode:(NSString*)mode
{
self = [super init];
if (self)
{
if (![[mode lowercaseString] isEqualToString:#"beta"] && ![[mode lowercaseString] isEqualToString:#"live"])
{
#throw ([NSException exceptionWithName:#"Invalid mode" reason:[NSString stringWithFormat:#"Invalid mode '%#' selected. Should either be 'beta' or 'live'", mode] userInfo:nil]);
}
EID = eid;
SHARED_SECRET = secret;
MODE = [mode lowercaseString];
}
return self;
}
+ (NSArray*)web_invoice_infoWithOCR:(NSString*)ocr pno:(NSString*)pno {
NSArray *params = [NSArray arrayWithObjects:ocr, EID, pno, [MyClass the_digest:[NSString stringWithFormat:#"%d:%#:%#", EID, ocr, SHARED_SECRET]], nil];
NSLog(#"Array: %#", params);
return params;
}
- (id)xmrpc_call_function:(NSString*)method parameters:(NSArray*)params
{
// Not finished yet, Warning exists
}
[...]
Having a look at my code, you'll notice the +(id)init function. I have tried -(id)init, -(id)initialize, +(id)initialize, +(void)initialize, -(void)initialize.
This is how I "load" my class in my AppDelegate:
[MyClass initWithEid:1234 secret:#"1234" mode:#"BETA"];
EDIT
I am trying to initiate my class the same way e.g. Flurry does. Example:
[FlurryAnalytics startSession:#"1234"];
You need to alloc it first:
MyClass *myClass = [[MyClass alloc] initWithEid:1234 secret:#"1234" mode:#"BETA"];

How do a populate an NSArray const? (code not working included)

How do a populate an NSArray const? Or more generically how can I fix my code below to have an array constant (created in Constants.h & Constants.m) to be available to other parts of my code.
Was hoping to be able to access the constant as a static type object (i.e. as opposed to having to create an instance of constants.m and then access it) is this is possible.
I note the approach works OK for a string, but for NSArray the issue is populating the array.
Code:
constants.h
#interface Constants : NSObject {
}
extern NSArray * const ArrayTest;
#end
#import "Constants.h"
#implementation Constants
NSArray * const ArrayTest = [[[NSArray alloc] initWithObjects:#"SUN", #"MON", #"TUES", #"WED", #"THUR", #"FRI", #"SAT", nil] autorelease];
// ERROR - Initializer element is not a compile time constant
#end
The standard approach is to supply a class method that creates the array the first time it is requested and thereafter returns the same array. The array is never released.
A simple, example solution is this:
/* Interface */
+ (NSArray *)someValues;
/* Implementation */
+ (NSArray *)someValues
{
static NSArray *sSomeValues;
if (!sSomeValues) {
sSomeValues = [[NSArray alloc]
initWithObjects:/*objects*/, (void *)nil];
}
return sSomeValues;
}
You can of course fancy this up with GCD instead of using an if:
/* Implementation */
+ (NSArray *)someValues
{
static NSArray *sSomeValues;
static dispatch_once_t sInitSomeValues;
dispatch_once(&sInitSomeValues, ^{
sSomeValues = [[NSArray alloc]
initWithObjects:/*objects*/, (void *)nil];
});
return sSomeValues;
}

Objective C Singleton class "defined but not used" warning!

I'm using a Singleton class and following is the code:
.h File: 
#import <Foundation/Foundation.h>
#interface Credential : NSObject {
NSString *UID;
NSString *UPASS;
}
#property(nonatomic,retain) NSString *UID;
#property(nonatomic,retain) NSString *UPASS;
static Credential *credential = NULL;
+(Credential*) sharedInstance;
/*
+ #property(nonatomic,retain) NSString *UID;
+ #property(nonatomic,retain) NSString *UPASS;
*/
#end
.m file:
#import "Credential.h"
#implementation Credential
#synthesize UID,UPASS;
-(void) dealloc{
[UID release];
[UPASS release];
[super dealloc];
}
+(Credential*) sharedInstance
{
#synchronized(self)
{
if (credential == NULL) {
credential = [[Credential alloc] init];
}
}
return credential;
}
#end
The following line produces warning "defined but not used"
static Credential *credential = NULL;
I couldn't figure out that I've been using credential variable in .m file under "sharedInstance" function then why am I getting this warning?
A strange issue to me!
Does the problem go away when you move the static variable to the top of the implementation (.m) file? And on a related note, I think that you would benefit from getting rid of the singleton altogether.

passing NSString from one class to the other

I have a NSString that is taken from a UITextField in a ViewController. Every of my other ViewController will use this NSString as well. How can I pass this NSString to others ViewControllers?
You want to have a property in each of your controllers
#interface MyViewController : UIViewController{
NSString *title;
}
#property (retain) NSString *title;
#end;
#implementation MyViewController
#synthesize title;
#end;
Use it like:
MyViewController *myVC = [[MyViewController alloc] initWithFrame:...];
myVC.title = #"hello world";
You should be familiar with Memory Management
Create a class for sharing your common objects. Retrieve it using a static method, then read and write to its properties.
#interface Store : NSObject {
NSString* myString;
}
#property (nonatomic, retain) NSString* myString;
+ (Store *) sharedStore;
#end
and
#implementation Store
#synthesize myString;
static Store *sharedStore = nil;
// Store* myStore = [Store sharedStore];
+ (Store *) sharedStore {
#synchronized(self){
if (sharedStore == nil){
sharedStore = [[self alloc] init];
}
}
return sharedStore;
}
// your init method if you need one
#end
in other words, write:
Store* myStore = [Store sharedStore];
myStore.myString = #"myValue";
and read (in another view controller):
Store* myStore = [Store sharedStore];
myTextField.text = myStore.myString;
If the string remains the same, and never changes, you could make a file named defines.h (without the .m file) and have this line:
#define kMyString #"Some text"
Then wherever you need the string, just import the defines file and use the constant.
#import "defines.h"
Much simpler than making custom classes.
EDIT:
Didn't see you needed to grab from the text field.
In that case, you could have it stored as property of your app delegate class and get it from there. The delegate can be accessed from anywhere in your app.