1
\$\begingroup\$

I often get into the dilemma of how to use string constants, this is the way I use now:

UIImage *image = [UIImage imageNamed:@"apple.png"];
NSArray *imageNames = @[@"apple01.png",@"apple02.png"];    
NSDictionary *imageKeyValues = @{@"Avatar" : @"apple.png"};

Once I encounter this type of code, I often use string pointers to refactor, because I don't know what the string code means:

static NSString *appleImage = @"apple.png";
UIImage *image = [UIImage imageNamed:appleImage];

NSArray *imageNames = @[@"apple01.png",@"apple02.png"];

static NSString  *avatarKey = @"Avatar";
NSDictionary *imageKeyValues = @{avatarKey : appleImage};

My question now is: Should I assign each string to a variable? Many strings are not shared and will only be used once. Is it worth modifying like this? Is there a better way?

\$\endgroup\$
1
  • \$\begingroup\$ What is the purpose of the imageNames example? It is the same in the two snippets. Was that an oversight, or are you trying to make some argument for why you refactored appleImage and avatarKey but not the elements of that array? (Frankly, I'm not getting the “I don't know what the string code means”, as it seems that you obviously do.) \$\endgroup\$
    – Rob
    Feb 3, 2021 at 18:32

3 Answers 3

1
\$\begingroup\$

You ask:

Should I assign each string to a variable? Many strings are not shared and will only be used once.

Obviously, in the other case, where the string is reused/shared, then of course one would (and should) define the constant/pointer once rather than ever repeating the same string literal in multiple places. This makes code easier to maintain.

You might also use constants/pointer to centralize the definition of all the possible keys in one place. E.g. if the string literals define possible key names used in some web interface, we might want to put all these key names in one place, making it easier to keep track of the API.

But if the strings are not shared and there is no organizational benefit to centralizing these definitions, then no, one would not assign each string its own variable.

Is it worth modifying like this?

If you are asking whether you should convert this ...

- (UIImage *)appleImage {
    UIImage *image = [UIImage imageNamed:@"apple.png"];
    return image;
}

... to the following ...

- (UIImage *)appleImage {
    static NSString *name = @"apple.png";
    UIImage *image = [UIImage imageNamed:name];
    return image;
}

... then the answer is, no, there is little benefit in doing do.

I would advise against pulling the string literal into its own local NSString pointer just for the sake of it. It just adds syntactic noise in this case. Yes, there are cases where one might pull the literal into its own line for the sake of clarity, but that not is not the case here.

The governing principles are code maintainability and readability.

\$\endgroup\$
1
  • \$\begingroup\$ Thank you very much for your answer \$\endgroup\$
    – Nullable
    Feb 7, 2021 at 7:23
0
\$\begingroup\$

Refactoring your code to what you provided would really only be necessary if you plan on expanding the use of these strings.

\$\endgroup\$
0
\$\begingroup\$

I'm going to be the heretic in the room... I think your first code sample is just fine and doesn't need any refactoring at all.

Let's pretend for a moment that the code lines in question are in wildly different places in the code base instead of one right after the other.

When I see NSDictionary *imageKeyValues = @{@"Avatar" : @"apple.png"}; somewhere. Learn a lot. I don't have to hunt all over the code trying to figure this dictionary out.

If I were to see NSDictionary *imageKeyValues = @{avatarKey : appleImage}; I learn much less. I have no idea what the key or value are at all. I have to hunt in some other file to figure out what this line might mean or whether I can safely use it in my current context.

Then there's the horrible practice of having a single file that contains all the string literals for the entire program.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.