I want to create a class that will contains static values accessable from all project.
Pseudocode:
class Constants:
constant String API_URL : "http://api.service.com"
constant Integer SOME_VALUE : 7
How can I do this with Objective-C ?
Answer for your question is extern keyword . I will explain it to you using an example . Add objective c classes your project and name them Common , Now in Common.h
#interface Common : NSObject
extern NSString *SiteApiURL;
#end
After you defined an instance of NSString Class using the extern keyword what you need to do is switch to Common.m class and initialize the value for NSString (SiteApiURL)
#import "Common.h"
#implementation Common
NSString *SiteApiURL = #"http://api.service.com";
#end
Import the Common.h class within the project-Prefix.pch file like this
#import <Availability.h>
#ifndef __IPHONE_3_0
#warning "This project uses features only available in iOS SDK 3.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "Common.h"
#endif
All done , now you can use the object "SiteApiURL" anywhere in the whole project and you need not to import any class anywhere i.e. You can use this variable anywhere in the project directly.
You could do it using preprocessors:
#define API_URL #"http://api.service.com"
#define SOME_VALUE (7)
Accessing defines would be simple: [object do:API_URL];
Or you could use constants
NSString * const apiURL = #"http://api.service.com";
NSNumber * const someValue = #7;
Accessing consts would be like accessing variables, So the string would just be a simple call. The NSNumber is an object wrapper for primitives so you'd need to access it like: someValue.intValue
You can create a Singleton with all necessary constants Here is a sample
If you do not want to create the class than you can use static private variables and static getters.
#interface
+(NSString*) getValue;
#end
#implementation
static NSString *_value = #"....";
+(NSString*) getValue {
return _value;
}
#end
Related
My project currently has a file containing many constants that I use in a variety of places throughout my codebase. I'm writing a class extension in swift and need to access some of these constants.
I have something like this defining my constants in Objective-C:
//
// AppConstants.h
//
#import <Foundation/Foundation.h>
#interface AppConstants : NSObject
extern NSString *const SOME_CONSTANT_IN_APP_CONSTANTS;
#end
I've added my AppConstants.h to the bridging header, but when I try and do:
someDictionary.objectForKey(PROPERTY_CALL_CAMPUS_SECURITY_TITLE)
I get:
Use of unresolved identifier 'PROPERTY_CALL_CAMPUS_SECURITY_TITLE'
Is there a way to access constants defined in Objective-C in my Swift code?
MyClass.h file
#import <Foundation/Foundation.h>
#interface MyClass : NSObject
{
// This is the Place of Instance Variable
}
- (void)thePublicMethod;
#end
MyClass.m file
#import "MyClass.h"
#interface MyClass()
- (void)thePrivateMethod;
#end
#implementation MyClass
-(void)thePublicMethod {
NSLog(#"Public Method Called");
}
- (void)thePrivateMethod {
NSLog(#"Private Method Called");
}
#end
The main.m file
#import <Foundation/Foundation.h>
#import "MyClass.h"
int main(int argc, const char * argv[])
{
#autoreleasepool {
MyClass *myObj = [[MyClass alloc] init];
[myObj thePublicMethod];
// [myObj thePrivateMethod];
}
return 0;
}
since “Private” methods can be created by defining them in a class’s implementation file while omitting them from its interface file.
i want to access thePrivateMethod from main.m and also can i call thePrivateMethod() from thePublicMethod() is it possible and how ?
If you want to access an internal method from somewhere other than the class's implementation, then you need to truly declare it as a private method.
Move that class extension to its own header file, say MyClass_Private.h. Then #import that header into both main.m and MyClass.m.
I.e. move this:
#interface MyClass()
- (void)thePrivateMethod;
#end
Into a file called MyClass_Private.h and then #import "MyClass_Private.h" in both your MyClass.m and main.m files.
Internal means only used in the innards of this framework or class.
Private means may be used by this framework or the class, but may be exposed to clients that are more intimately tied to the class than through Public API. Typically reserved for framework authors on large scale systems (like the OS).
Public means may be used anywhere by any client of the class.
No matter how or where or IF you declare a method, at all.. If it exists.. calling it is as simple as
[myInstance performSelector:NSSelectorFromString(#"yourSuperSecretMethod:")
withObject:myKillerObject];
If the method got compiled.. It will get called. There is no "hiding" it. Even if not declared, the runtime "gives up" this information to any interested party. #see class-dump, if interested in learning more.
I am new to iOS and obective-c so I am not too sure how to best accomplish this seemingly simple task.
What I want is to make a class that looks like this in pseudocode:
class UtilityClass
{
// Have a method that I can pass parameters to
String doCalculation ( String art1 , String arg2 )
{
return arg1 + arg2;
}
}
My uncertainty is:
1) xCode seems to be inclined to lay out my file structure in a relatively flat way. So should I make a utils directory and have this file be under utils/fileName ? Usually I am kind of used to having at least some src directory, but so far I have not been prompted by anything to create one.
2) How do I import and call this class/function from my controllers?
Thanks,
Alex
Just create a new group called Utilities, and then create your class inside it. Like,
utils.h
utils.m
Later in your ViewController's header file just add.
#import "utils.h"
if this utils class is used by many controllers in very fat project then, find a file called, Should be inside supporting files group.
YourAppName-Prefix.pch
In that file you have a code block like this,
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#endif
Just edit this block and add your utils.h reference here, In this way your entire project can create utils object without explicitly importing into their own header.
Edit like this.,
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "utils.h"
#endif
First of all create a new File in Xcode and uncheck xib file. Name the Project as you like . and extend it from NSObject .
for creating static method you have to replace function starting - to + like
interface. class
#interface Utility : NSObject
+ (int)getNumber;
+ (void)setNumber:(int)number;
#end
.m class
#import "Utility.h"
#implementation Utility
static int number = 1;
+ (int)getNumber {
return number;
}
+ (void)setNumber:(int)newNumber {
number = newNumber;
}
+ (id)alloc {
[NSException raise:#"Cannot be instantiated!" format:#"Static class 'ClassName' cannot be instantiated!"];
return nil;
}
#end
call it in any other ViewController like
NSLog(#"number = %d", [Utility getNumber]);
[Utility setNumber:3];
NSLog(#"number = %d", [Utility getNumber]);
for details..
Where you store the files is up to you, just make sure XCode knows where to find them. The class itself should be made like any other Objective C class, just make it inherit from NSObject instead of one of the graphical classes:
// MyClass.h
#interface MyClass : NSObject {
int instanceVar;
}
#property (nonatomic, assign) int property;
#end
// MyClass.m
#import "MyClass.h"
#implementation MyClass
#synthesize property;
-(id) init {
...
}
-(int) function {
...
}
#end
To use the class in another file, just import the header like any other class
#import "MyClass.h"
I have Class A and Class B.
Class B subclasses Class A
Class A has a static constant NSString variable
In a method of Class B I need to use the static constant NSString variable of Class A. What are my options ?
I tried declaring the same thing again, but caused problem (internal inconsistency), tried without using (says, variable undeclared).
Any idea how I can solve this problem ?
Thanks.
Make a class method returning that constant, like this:
+(NSString*) constString {
return myConstString;
}
You can declare static constant strings in the .h file. That way they are public and can be used by other classes that import the header file, including your subclass.
Alternatively, you can declare a reference to the string in your Class B using extern:
extern NSString *const MyString;
That basically tells the compiler that the value of that string is defined elsewhere in the code and it doesn't have to worry about it.
By "Class A has a static constant NSString variable", I assume you're referring to having something like the following defined in your Class A .m file:
static NSString * const MyString = #"MyString";
#implementation ClassA
#end
To allow Class A and its subclasses to see the value, you can do something like this:
MDClassAPrivate.h:
#import <Foundation/Foundation.h>
static NSString * const MDBlahBlahKey = #"MDBlahBlah";
MDClassA.h:
#import <Foundation/Foundation.h>
#interface MDClassA : NSObject {
}
#end
MDClassA.m:
#import "MDClassA.h"
#import "MDClassAPrivate.h"
#implementation MDClassA
#end
MDClassB.h:
#import "MDClassA.h"
#interface MDClassB : MDClassA {
}
#end
MDClassB.m:
#import "MDClassB.h"
#import "MDClassAPrivate.h"
#implementation MDClassB
#end
By moving the static const variables to a separate file, you can allow any class to import them in the implementation file.
My personal solution to this problem would be a pseudo-protected method that returns the constant string.
// ClassA.m
#interface ClassA ()
- (NSString *)constantString;
#end
#implementation ClassA
- (NSString *)constantString {
return #"MyConstantString";
}
#end
Then following on into your subclass:
// ClassB.m
#interface ClassA ()
// This is a method redeclaration to avoid build warnings
- (NSString *)constantString;
#end
#implementation ClassB
- (void)someMethod {
NSString *theConstantString = [self constantString];
// do stuff...
}
#end
The assumption here is that your constant string really is constant, if you want it to be dynamic you would need to modify this solution slightly, but it can still handle it.
You can use 'userDefaults' to set a value that is accessible in the whole application.
[[NSUserDefaults standardUserDefaults] setObject:object forKey:#"objectKey"];
I have a class structure
Class A
{
Object of classB
Object of classC
}
Now for this purpose I have files A.h/A.m B.h/B.m , C.h/C.m
Now I have a separate file G.h which has a number of global variables which are used by all the class A,B,C
Now I have imported B.h , C.h , G.h inside A.h . I also have separately imported the file G.h inside B.h and C.h
Now when build the project , I receive a link error for duplicate symbol on the global varibles (which is probably due to multiple inclusion of the file G.h) .
How can I solve this ??? The following is my code structure
//A.h
#import "B.h"
#import "C.h"
#import "G.h"
#interface A : NSObject {
B *b;
C *c;
}
//B.h
#import "G.h"
//C.h
#import "G.h"
//G.h
A *a=nil;
#interface G : NSObject { //whole class is empty}
You should declare your globals in G.h but define them in G.m, so that they're only linked once in the target. So if, for example, you have a string constant that's globally defined, you would do:
G.h
extern NSString const *appName;
G.m
NSString const *appName = #"My Great App";
In your pasted code, it's the A instance that's being duplicated. It's imported into each other translation unit, but with the same name every time which means that the compiled objects can't be linked. Assuming you want a shared A instance called a, you'd do:
G.h
#class A;
extern A *a;
G.m
#import "A.h"
#import "G.h"
A *a = nil;
Use the #class compiler directive in your class headers instead of importing the headers of the other classes. #class provides a forward declaration of a given class, so you can defer importing its header until you really need it, which is usually going to be in the corresponding .m file.
So instead of something like this:
#import "B.h"
#interface A : NSObject
{
B someObj;
}
...do this
#class B;
#interface A : NSObject
{
B someObj;
}
Now the compiler will understand that B is the name of a class, and therefore allow you to use it as a data type without importing B's header.