Reputation: 2084
I have a PLIST file in my app that contains various configuration data. Some of the data are URLs for accessing a server. This server hosts JSON files for several different versions of our code. What I want to be able to do is have a value in the PLIST file that has the version and then be able to reference it from other values. So the url value in the plist could be https://www.company.com/${VERSION}/jsonfile.svc (where ${VERSION} is a different key int he same plist file).
Upvotes: 2
Views: 443
Reputation: 447
As bshirley mentioned there is nothing automatic but Objective-C can help you with that. Below is a simple implementation of a NSDictionary
category called VariableExpansion
that demonstrates how this could be implemented (note that this is not fully tested but serves primarily to demonstrate the way you could make this automatic. Also, expandedObjectForKey
assumes you are dealing with NSString
s so you might need to tweak it a bit.
// In file NSDictionary+VariableExpansion.h
@interface NSDictionary (VariableExpansion)
- (NSString*)expandedObjectForKey:(id)aKey;
@end
// In file NSDictionary+VariableExpansion.m
#import "NSDictionary+VariableExpansion.h"
@implementation NSDictionary (VariableExpansion)
- (NSString*)expandedObjectForKey:(id)aKey
{
NSString* value = [self objectForKey:aKey];
NSError *error = NULL;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\$\\{([^\\{\\}]*)\\}"
options:NSRegularExpressionCaseInsensitive
error:&error];
__block NSMutableString *mutableValue = [value mutableCopy];
__block int offset = 0;
[regex enumerateMatchesInString:value options:0
range:NSMakeRange(0, [value length]) usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop)
{
NSRange matchRange = [match range];
matchRange.location += offset;
NSString* varName = [regex replacementStringForResult:match
inString:mutableValue
offset:offset
template:@"$1"];
NSString *varValue = [self objectForKey:varName];
if (varValue)
{
[mutableValue replaceCharactersInRange:matchRange
withString:varValue];
// update the offset based on the replacement
offset += ([varValue length] - matchRange.length);
}
}];
return mutableValue;
}
@end
// To test the code, first import this category:
#import "NSDictionary+VariableExpansion.h"
// Sample NSDictionary.
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:
@"http://${HOST}/${VERSION}/bla", @"URL",
@"1.0", @"VERSION",
@"example.com", @"HOST", nil];
// And the new method that expands any variables (if it finds them in the PLIST as well).
NSLog(@"%@", [dict expandedObjectForKey:@"URL"]);
The result of the last step is http://example.com/1.0/bla
showing that you could use multiple variables in a single value. If a variable is not found it will not be touched in your original string.
Since you are using PLIST as your source, use dictionaryWithContentsOfFile
as in
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:plistPath];
Upvotes: 3
Reputation: 8357
have you tried anything? this is fairly straightforward, convert it as you are mentioning, the method of particular use: stringByReplacingOccurrencesOfString:
.
Upvotes: 0