Objective-C Category Question
I've created a custom sorting by creating a new category for the NSString
class. Below is my code.
@implementatio开发者_JAVA技巧n NSString (Support)
- (NSComparisonResult)sortByPoint:(NSString *)otherString {
int first = [self calculateWordValue:self];
int second = [self calculateWordValue:otherString];
if (first > second) {
return NSOrderedAscending;
}
else if (first < second) {
return NSOrderedDescending;
}
return NSOrderedSame;
}
- (int)calculateWordValue:(NSString *)word {
int totalValue = 0;
NSString *pointPath = [[NSBundle mainBundle] pathForResource:@"pointvalues"ofType:@"plist"];
NSDictionary *pointDictionary = [[NSDictionary alloc] initWithContentsOfFile:pointPath];
for (int index = 0; index < [word length]; index++) {
char currentChar = [word characterAtIndex:index];
NSString *individual = [[NSString alloc] initWithFormat:@"%c",currentChar];
individual = [individual uppercaseString];
NSArray *numbersForKey = [pointDictionary objectForKey:individual];
NSNumber *num = [numbersForKey objectAtIndex:0];
totalValue += [num intValue];
// cleanup
individual = nil;
numbersForKey = nil;
num = nil;
}
return totalValue;
}
@end
My question is whether I create a point dictionary to determine the point value associated with each character in the alphabet based on a plist. Then in my view controller, I call
NSArray *sorted = [words sortedArrayUsingSelector:@selector(sortByPoint:)];
to sort my table of words by their point values. However, creating a new dictionary each time the -sortByPoint:
method is called is extremely inefficient. Is there a way to create the pointDictionary beforehand and use it for each subsequent call in the -calculateWordValue:
?
This is a job for the static keyword. If you do this:
static NSDictionary *pointDictionary = nil
if (pointDictionary==nil) {
NSString *pointPath = [[NSBundle mainBundle] pathForResource:@"pointvalues" ofType:@"plist"];
pointDictionary = [[NSDictionary alloc] initWithContentsOfFile:pointPath];
}
pointDictionary
will be persistent for the lifetime of your app.
One other optimization is to build a cache of scores by using this against each of your words:
[dict setObject:[NSNumber numberWithInt:[word calculateWordValue:word]] forKey:word];
Then use the keysSortedByValueUsingSelector:
method to extract your list of words (note the selector chould be compare:, since the objects being compared are the NSNumbers).
Finally, the word argument on your method is redundant. Use self instead:
-(int)calculateWordValue {
...
for (int index = 0; index < [self length]; index++)
{
char currentChar = [self characterAtIndex:index];
...
}
...
}
Change your sortByPoint:(NSString *) otherString
method to take the dictionary as a parameter, and pass it your pre-created dictionary.
sortByPoint:(NSString *)otherString withDictionary:(NSDictionary *)pointDictionary
EDIT: Won't work because of usage in sortedArrayWithSelector. Apologies. Instead, you may be better off creating a wrapper class for your point dictionary as a singleton which you then obtain a reference to each time your sort function runs.
In calculateWordValue
:
NSDictionary *pointDictionary = [[DictWrapper sharedInstance] dictionary];
DictWrapper
has an NSDictionary as a property, and a class method sharedInstance
(to return the singleton. You have to set that dictionary and pre-initialize it before you do you first sorting.
精彩评论