Classes/PeriodicElements.m
/* |
Copyright (C) 2015 Apple Inc. All Rights Reserved. |
See LICENSE.txt for this sample’s licensing information |
Abstract: |
Encapsulates the collection of elements and returns them in presorted states. |
*/ |
#import "PeriodicElements.h" |
#import "AtomicElement.h" |
@implementation PeriodicElements |
// we use the singleton approach, one collection for the entire application |
static PeriodicElements *sharedPeriodicElementsInstance = nil; |
+ (PeriodicElements *)sharedPeriodicElements { |
@synchronized(self) { |
static dispatch_once_t pred; |
dispatch_once(&pred, ^{ sharedPeriodicElementsInstance = [[self alloc] init]; }); |
} |
return sharedPeriodicElementsInstance; |
} |
+ (id)allocWithZone:(NSZone *)zone { |
@synchronized(self) { |
if (sharedPeriodicElementsInstance == nil) { |
sharedPeriodicElementsInstance = [super allocWithZone:zone]; |
return sharedPeriodicElementsInstance; // assignment and return on first allocation |
} |
} |
return nil; //on subsequent allocation attempts return nil |
} |
- (id)copyWithZone:(NSZone *)zone { |
return self; |
} |
// setup the data collection |
- (instancetype) init { |
if (self = [super init]) { |
[self setupElementsArray]; |
} |
return self; |
} |
- (void)setupElementsArray { |
NSDictionary *eachElement; |
// create dictionaries that contain the arrays of element data indexed by |
// name |
self.elementsDictionary = [NSMutableDictionary dictionary]; |
// physical state |
self.statesDictionary = [NSMutableDictionary dictionary]; |
// unique first characters (for the Name index table) |
self.nameIndexesDictionary = [NSMutableDictionary dictionary]; |
// create empty array entries in the states Dictionary or each physical state |
(self.statesDictionary)[@"Solid"] = [NSMutableArray array]; |
(self.statesDictionary)[@"Liquid"] = [NSMutableArray array]; |
(self.statesDictionary)[@"Gas"] = [NSMutableArray array]; |
(self.statesDictionary)[@"Artificial"] = [NSMutableArray array]; |
// read the element data from the plist |
NSString *thePath = [[NSBundle mainBundle] pathForResource:@"Elements" ofType:@"plist"]; |
NSArray *rawElementsArray = [[NSArray alloc] initWithContentsOfFile:thePath]; |
// iterate over the values in the raw elements dictionary |
for (eachElement in rawElementsArray) |
{ |
// create an atomic element instance for each |
AtomicElement *anElement = [[AtomicElement alloc] initWithDictionary:eachElement]; |
// store that item in the elements dictionary with the name as the key |
(self.elementsDictionary)[anElement.name] = anElement; |
// add that element to the appropriate array in the physical state dictionary |
[(self.statesDictionary)[anElement.state] addObject:anElement]; |
// get the element's initial letter |
NSString *firstLetter = [anElement.name substringToIndex:1]; |
NSMutableArray *existingArray = [self.nameIndexesDictionary valueForKey:firstLetter]; |
// if an array already exists in the name index dictionary |
// simply add the element to it, otherwise create an array |
// and add it to the name index dictionary with the letter as the key |
// |
if (existingArray != nil) |
{ |
[existingArray addObject:anElement]; |
} else { |
NSMutableArray *tempArray = [NSMutableArray array]; |
(self.nameIndexesDictionary)[firstLetter] = tempArray; |
[tempArray addObject:anElement]; |
} |
} |
// create the dictionary containing the possible element states |
// and presort the states data |
self.elementPhysicalStatesArray = @[@"Solid", @"Liquid", @"Gas", @"Artificial"]; |
[self presortElementsByPhysicalState]; |
// presort the dictionaries now |
// this could be done the first time they are requested instead |
// |
[self presortElementInitialLetterIndexes]; |
self.elementsSortedByNumber = [self presortElementsByNumber]; |
self.elementsSortedBySymbol = [self presortElementsBySymbol]; |
} |
// return the array of elements for the requested physical state |
- (NSArray *)elementsWithPhysicalState:(NSString *)aState { |
return (self.statesDictionary)[aState]; |
} |
// presort each of the arrays for the physical states |
- (void)presortElementsByPhysicalState { |
for (NSString *stateKey in self.elementPhysicalStatesArray) { |
[self presortElementsWithPhysicalState:stateKey]; |
} |
} |
- (void)presortElementsWithPhysicalState:(NSString *)state { |
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" |
ascending:YES |
selector:@selector(localizedCaseInsensitiveCompare:)] ; |
NSArray *descriptors = @[nameDescriptor]; |
[(self.statesDictionary)[state] sortUsingDescriptors:descriptors]; |
} |
// return an array of elements for an initial letter (ie A, B, C, ...) |
- (NSArray *)elementsWithInitialLetter:(NSString*)aKey { |
return (self.nameIndexesDictionary)[aKey]; |
} |
// presort the name index arrays so the elements are in the correct order |
- (void)presortElementInitialLetterIndexes { |
self.elementNameIndexArray = [[self.nameIndexesDictionary allKeys] sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]; |
for (NSString *eachNameIndex in self.elementNameIndexArray) { |
[self presortElementNamesForInitialLetter:eachNameIndex]; |
} |
} |
- (void)presortElementNamesForInitialLetter:(NSString *)aKey { |
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" |
ascending:YES |
selector:@selector(localizedCaseInsensitiveCompare:)] ; |
NSArray *descriptors = @[nameDescriptor]; |
[(self.nameIndexesDictionary)[aKey] sortUsingDescriptors:descriptors]; |
} |
// presort the elementsSortedByNumber array |
- (NSArray *)presortElementsByNumber { |
NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"atomicNumber" |
ascending:YES |
selector:@selector(compare:)] ; |
NSArray *descriptors = @[nameDescriptor]; |
NSArray *sortedElements = [[self.elementsDictionary allValues] sortedArrayUsingDescriptors:descriptors]; |
return sortedElements; |
} |
// presort the elementsSortedBySymbol array |
- (NSArray *)presortElementsBySymbol { |
NSSortDescriptor *symbolDescriptor = [[NSSortDescriptor alloc] initWithKey:@"symbol" |
ascending:YES |
selector:@selector(localizedCaseInsensitiveCompare:)] ; |
NSArray *descriptors = @[symbolDescriptor]; |
NSArray *sortedElements = [[self.elementsDictionary allValues] sortedArrayUsingDescriptors:descriptors]; |
return sortedElements; |
} |
@end |
Copyright © 2015 Apple Inc. All Rights Reserved. Terms of Use | Privacy Policy | Updated: 2015-08-25