0

I have a large constant (an NSString with 10^6 values). Because of its size I would like to declare it at the end of the source file (so I don't have to scroll through it every time I want to edit my code). Also because of its size I would like it to be a constant so I can load it at compile time instead of runtime. Also, because I do not want it accessible to outside users I do not want to declare it as extern in the header file.

I have it declared as a constant using the code below in the implementation file, however it is giving me a "Use of undeclared identifier 'hugeConstantString'" if I move it past the @end of the implementation (for obvious reasons).

NSString *const hugeConstantString = @"a_whooooooole_lotta_characters";

I've checked this out: Constants in Objective-C but it didn't tell me anything I didn't know already. Maybe my brain is fried, but: is there any way that I can define this huge constant AFTER my implementation and still have it accessible? Or if I declare it in another header file and import it, will it then be accessible to others?

Thanks!

Community
  • 1
  • 1

2 Answers2

2

I'm not sure such a large string is a good idea, but if you're going to use it, I suggest putting it in its own header file.

MyLongStringConstant.h

#define kLongString @"..."

MyClass.h

....
#import "MyLongStringConstant.h"
...
//Do something with kLongString
...

If you want to have it accessible in every file of your app, import the header inside your apps myApp_Prefix.pch file, which is imported into every file.

Moshe
  • 57,511
  • 78
  • 272
  • 425
  • While a good idea, this doesn't directly answer the poster's desire that he does "not want [the string] accessible to outside users". Though very little is actually inaccessible in a dynamic runtime like Objective-C, so I guess thinking along those lines isn't all that helpful and there's an extent to which you're right to disregard that wish. – Tommy Mar 30 '11 at 17:28
  • 1
    I doubt anyone is using a fully compiled app as a static library. This shouldn't be an issue. – Moshe Mar 30 '11 at 17:34
  • 1
    @Tommy I think you may be right. Just read [this little article](http://www.mcafee.com/us/resources/white-papers/foundstone/wp-pen-testing-iphone-ipad-apps.pdf) and it seems that someone who knows what they're doing could figure out how to access it pretty easily no matter how i try to privatize it. bummer. – CrawfishJones Mar 30 '11 at 19:23
  • @CrawfishJones - Interesting article. You can try encrypting it through a cipher of sorts, but I think that's beyond the scope of this answer(er). – Moshe Mar 30 '11 at 19:26
  • if i did the above, it would be dealt with at compile time though? also: i think decrypting it at runtime would be pretty costly, memory and processorwise no? but it's worth playing with... and no worries on the scope, i'v been playing with the commmon crypto libraries :) i guess my ultimate goal is to have it loaded as a constant at the program startup. not lazily as some giant object later? – CrawfishJones Mar 30 '11 at 19:41
  • If you use an include, it gets dealt with at compile time. You are right, encryption is likely to affect performance. If you lazily load it as an object, that will also affect performance. Just remember that size is an issue on embedded devices. I suggest reconsidering the need for a giant string. – Moshe Mar 30 '11 at 21:56
1

I am going to save the conversation of Why are you doing that and just post a simple solution for you. Thanks to Tommy in the comments here is a simpler version.

#import "LargeStringTest.h"


@implementation LargeStringTest

//Declare the string
static NSString *hugeConstantString;

- (id)init {
    self = [super init];
    if (self) {
        NSLog(@"Large String %@", hugeConstantString);
    }
    return self;
}

//Place all other code here

//Assign the string
static NSString *hugeConstantString = @"a_whooooooole_lotta_characters";

@end
Joe
  • 56,979
  • 9
  • 128
  • 135
  • I was in the process of posting a similar thing; note to original poster: the actual definition of hugeConstantString__ can be put anywhere you like, even past the @end, as long as the declaration (which is above - (id)init in the sample posted) is visible to those sections of code that need it. – Tommy Mar 30 '11 at 17:09
  • I gave Moshe +1 because that is the cleanest way of doing it. I was just offering an option similar to what the original question was asking. It is definitely an option though. – Joe Mar 30 '11 at 17:12
  • @Joe - Thanks for the upvote! This is a way to do it, but I wonder what the point of an entire wrapper class is for, when a single line of `#define` will suffice. – Moshe Mar 30 '11 at 17:14
  • I did not intend for this to be a wrapper class. I intended for my example to represent the only class that he plans on using the large string in. With #defines all the compiler does is substitute the define name with the large string but since compilers optimize string literals that would not be a bad option. – Joe Mar 30 '11 at 17:17
  • 2
    Having looked closely, I was actually going to post something much simpler, to the effect that you can declare the string in one place (as you do immediately above init) and then define it somewhere else. So the original poster can declare it at the top of his source file, then define it at the bottom. I have to admit not to having been thinking in terms of a wrapper class. – Tommy Mar 30 '11 at 17:24
  • dumb question, but is the initialize method automatically called when loading a class in iOS? if anyone knows... or should i schlep it into the viewDidLoad? Or will this load it at compile time? – CrawfishJones Mar 30 '11 at 19:27
  • The initialize function is the static initializer only called once before the first message is sent to that object. What I need to do is update my example to incorporate Tommy's solution to the problem that does not involve the initialized method. – Joe Mar 30 '11 at 19:29
  • so would it be inited when the program is loaded into memory, or lazily later (trying to avoid the latter) – CrawfishJones Mar 30 '11 at 19:56