1

I'm new to objective c and I come from .NET background. I want to create a static class which will store will constants of any type (NSString,NSArray etc.) In .NET I would create a class and declare the const using "public const". How do I do the same in objective C? I had a look at creating a class which is a Subclass of NSObject but I wasn't sure and I don't want to use #define .Any help would be appreciated

Sample:

public class ApplicationConstants()
{
   public const string globalString="This is a global string";
   public const int sample=1;
}

I want to do something like this in objective c. Any link to some sample code would be really helpful. I also want to store arrays in the same way

Aster Veigas
  • 866
  • 3
  • 13
  • 34
  • It’s not too clear to me what you’re asking. Could you maybe post a short piece of .NET code to do what you’re trying to do? – bdesham Dec 05 '13 at 17:06
  • If you are asking about class which let you store any object in Objective c this is id. – Greg Dec 05 '13 at 17:09
  • There are at least a half-dozen different ways to do this in C-based languages, none of them ideal. (Of course, neither is the Java/C# scheme above.) There was a discussion 2-3 months back that covered most of the techniques, if someone can dig it up. Lots of tradeoffs depending on your goals and hot issues. (Where performance is not a big issue, I kind of favor a NSDictionary of values -- easy to maintain and can store any type.) – Hot Licks Dec 05 '13 at 17:20

5 Answers5

3

Objective-C doesn't have class variables. There are two ways to achieve the same functionality:

  1. use global variables with a name that indicates what class they belong to. E.G.

Header:

extern NSString *const BCOpinionatedClassWillStartOpiningNotification;

Implementation:

NSString *const BCOpinionatedClassWillStartOpiningNotification = @"BCOpinionatedClassWillStartOpiningNotification";

2 Create a class method that returns the value. E.G:

Header:

@interface BCOpinionatedClass
+(NSInteger)theBestIntegerEver;
@end

Implementation:

@implementation OpinionatedClass
+(NSInteger)theBestIntegerEver
{
    return 1;
}
@end
Benedict Cohen
  • 11,912
  • 7
  • 55
  • 67
3

You should not create this object (you really shouldn't create this object in C# either, but we're discussing ObjC right now). There is no object-oriented sense to a class that is "all the constants for a program." The correct place to put these values is in the classes that require them. So for instance, if you create a string constant for an NSNotification name, you should put its definition in the class that posts that notification.

In general, you do not put these kinds of constants inside of classes at all. You use prefix naming for them to indicate what they relate to. So for instance, the UIApplicationDidBecomeActiveNotification string constant is defined in the UIApplication.hheader file, thus:

UIKIT_EXTERN NSString *const UIApplicationDidBecomeActiveNotification;

UIKIT_EXTERN is a portability macro that resolves to just extern. Inside of the .m, you would have some line like:

NSString *const UIApplicationDidBecomeActiveNotification = @"UIApplicationDidBecomeActiveNotification";

While this constant goes inside of UIApplication.h, it is not inside of the UIApplication class, or any class. Objective-C doesn't provide the kind of scoping you're used to in C#. We use naming prefixes instead of namespaces.

The same rules apply for other types; this isn't just for strings. For example, again from UIApplication.h:

typedef NS_ENUM(NSInteger, UIApplicationState) {
  UIApplicationStateActive,
  UIApplicationStateInactive,
  UIApplicationStateBackground
} NS_ENUM_AVAILABLE_IOS(4_0);

Here we define an enum, which indirectly is defining various integer values. Again, this is just in the header file. There is no encapsulation inside of UIApplication. We only know that it's part of UIApplication because of its prefix.

Even those things that are ubiquitous through the whole system, such as UIKitDefines.h and Availability.h, are still broken out into their own contained headers. There is no "here are all the definitions for all UIKit objects" file. You shouldn't create one for your program either.

Note that this use of global variables is only appropriate for constants. You should not use globals this way for mutable variables. They should belong to some class and have accessors. But again, they would belong to the class that uses them, not a "generic program stuff" class.

See also @Benedict Cohen's answer for how to implement these things as class methods, which has some benefits (it permits subclassing, for instance). It is also somewhat less convenient, and is not the most common approach.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
0

Take a look at this answer. For example, you can define string constants in your headers like:

FOUNDATION_EXPORT NSString *const aConstantString;

and then initialize them in the implementation file:

NSString *const aConstantString = @"Some constant string";

In case you're wondering what FOUNDATION_EXPORT is, in NSObjCRuntime.h it is #defined as extern.

Community
  • 1
  • 1
paulrehkugler
  • 3,241
  • 24
  • 45
  • and what kind of class would this be? I mean sublclass of what? Why cant I declare and initialize objects in the interface file? Will this work for NSArray's as well? In the implementation I have to synthesis the constant name right? – Aster Veigas Dec 05 '13 at 17:16
  • Keep in mind that Objective-C is a superset of C; you don't need to put these inside of an object at all. And yes, this will also work for arrays. – paulrehkugler Dec 05 '13 at 17:18
  • the class should be a subset of NSObject? – Aster Veigas Dec 05 '13 at 17:36
  • 1
    There is no class. These are global constants. – Rob Napier Dec 05 '13 at 18:06
  • Like I said, you don't have to have any object associated. Create a subclass of NSObject and delete the @ interface and @ implementation sections, and just import the header wherever you need to use the constants. – paulrehkugler Dec 05 '13 at 18:08
0

I think you are having some confusion with changing coding domains.

In .NET,

public const string globalString="This is a global string";

defines a constant string that is immutable, which means, you cannot change the content of the memory location pointed by globalString. And you can define such variable in class level.

On the other hand, Objective-C being a successor of pure C, is not fully object oriented. Instead, it supports declaring immutable variables at module level. And that means, you can define a immutable variable in your header and that would be accessible from any module importing that header.

So you can declare your constant variable at module level like, at the top of your header like,

extern const NSString* const globalString;

And then you need to initialize it, at the top of your implementation(.m) file like

const NSString* const globalString = @"This is a global string";

Here, const NSstring* const denotes the variable globalString points to a unique memory location (the trailing const) and it contains some immutable value(@"This is a global string") that cannot be changed (the leading const). So it becomes the equivalent to your .NET declaration.

Another thing to remember here that NSString,NSArray,NSDictionary, etc. are immutable by nature (with NSMutableString, NSMutableArray, NSMutableDictionary, etc. as their mutable counterparts) and you dont need to specify the leading const keyword for them as that is defined implicitly. So it is ok to write:

extern NSString* const globalString;

For declaring a constant string.

Hope it helps to understand.

Ayan Sengupta
  • 5,238
  • 2
  • 28
  • 40
  • yes I am a little confused that's the reason why I posted the question here. can you give a complete code sample of the h and m file? – Aster Veigas Dec 05 '13 at 17:35
  • 1
    You're reading the consts backwards. The second const means it's a constant pointer ("constant memory location"). The first const means it's an immutable NSString, which is meaningless in ObjC (NSString itself is immutable). The correct form is given by @paulrehkugler's answer (NSString * const …) – Rob Napier Dec 05 '13 at 17:51
  • @RobNapier thanks for your feedback. Sorry that I rather messed up with the ordering of `const` keyword and I should have used "trailing" and "leading" instead of "first" and "second" in my answer. Also, I think, I have missed to mention "NSString" in the list of immutable objects like "NSArray", etc. However, I don't believe using the leading `const` keyword would impose any bad on overall code but you are right that it is redundant. And that's what I tried to mention in the following statements. Modified my answer accordingly. Thanks again. – Ayan Sengupta Dec 05 '13 at 19:15
  • The main problem with "const NSString *" is that it's not just redundant, but actually confusing. For instance, it is identical to "const NSMutableString *" (which is not constant). – Rob Napier Dec 05 '13 at 20:06
0

Use singleton with an NSArray to hold your data. The objects to add can be initialised and added to the NSArray on your singleton init and be ready for use. Or even better, Use an NSMutableDictionary and you can store and retrieve objects using keys.

The singleton pattern: Singleton with ARC

NSDictionary: https://developer.apple.com/library/mac/documentation/cocoa/reference/foundation/classes/nsdictionary_class/Reference/Reference.html

Community
  • 1
  • 1
EhTd
  • 3,260
  • 4
  • 19
  • 18