-1
\$\begingroup\$

I have a card-based iOS app that uses a sizable static array of cards. Each card has several properties, mostly strings, numbers and boolean.

The first version of this app had 3-4 properties. The next version had about 7-8. Now it has 10-11. I have plans to add another 5-10 properties.

With each iteration, I had to change lots of code:

[allCards addObject:[FlashCard flashCardWithVarA:@"ABC" varB:@"DEF" varC:@"GHI"]];

became:

[allCards addObject:[FlashCard flashCardWithVarA:@"ABC" varB:@"DEF" varC:@"GHI" varD:FALSE varE:FALSE varF:@"JK" varG:FALSE varH:@"123"]];

and then:

[allCards addObject:[FlashCard flashCardWithVarA:@"ABC" varB:@"DEF" varC:@"GHI" varD:FALSE varE:FALSE varF:@"JK" varG:FALSE varH:@"123" varJ:@"4567" varK:@"890" varL:@"LMN" varM:@"OPQ" varN:@"RST" varO:@"U"]];

I also have to add the new properties to the FlashCard object. I have to change the initializer, etc.

Each time I do it, I think to myself, there must be a better way. Especially because I have to modify 200 calls to [allCards addObject:].

Any suggestions or ideas?

\$\endgroup\$
  • \$\begingroup\$ I saw something once where the programmer passed in a single dictionary and did all the processing inside the method. Maybe, I'll try that. \$\endgroup\$ – Zonker.in.Geneva Jan 30 '17 at 22:19
1
\$\begingroup\$

Well if you are looking to reduce the number of properties your objects have, you'll have to figure out a way to refactor the class interface. But seeing as you have a flash card app, I don't think that's possible, I'm just assuming you need all of those properties

If you're trying to save the pain of re-writing every message whenever you change the interface, you can leave the old interface alone, an create new methods that get called by the old.

Example:

-(instancetype)flashCardWithVarA:(NSString*)a varB:(NSString*)b varC:(NSString*)c
{
  [self flashCardWithVarA:a varB:b varC:c varD:DEFAULTVALUE varN:DEFAULTVALUE];
}

This way you don't have to change your callers

However, just assuming based off of my knowledge of how flashcards work, you are going to want to change the creation of every flash card whenever you change the initialization interface.

So, in short, you're sort of hosed :)

I would say that if you find that most of your objects are passing the same value when initializing, then maybe see if there's a way you can just default that value in the initialization of the Flash Card object, and then explicitly force a flash card to re-set that default value if it needs to

\$\endgroup\$
1
\$\begingroup\$

Put all this static data into a .plist file.

Now you can cleanly maintain that seperate from your source code, and easily suck the whole thing in as needed.

NSString *path = [NSBundle.mainBundle pathForResource:@"flashCards" ofType:@"plist"]; 
NSArray *flashCardDicts = [NSArray arrayWithContentsOfFile:path]; 

Now just loop through that array and build all your FlashCard objects from the dictionaries

for (NSDictionary *dict in flashCardDicts) {
    FlashCard *flashCard = [FlashCard flashCardWithVarA:dict[@"A"]
                                                   varB:dict[@"B"]
                                                   varC:dict[@"C"]
                                                   varD:[dict[@"D"] boolValue]
                                                   varE:[dict[@"E"] boolValue]
                                                   varF:dict[@"F"]
                                                   varG:[dict[@"G"] boolValue]
                                                   varH:dict[@"H"]];
    ...
}

Or more even more simply.

for (NSDictionary *dict in flashCardDicts) {
    FlashCard *flashCard = [FlashCard flashCardWithDict:dict];
    ...
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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