Reputation: 1295
I have a set of Objective-C files in my app labeled Crop.h/Crop.m. Inside is a custom array of different vegetables from a video game - each vegetable has properties like a name, growing season, number of days to grow, etc.
I need to write a function which loops through this array and checks each Crop name value to see if it matches with my view title (self.title). Below is an example of two crop objects:
Crop *turnip = [[Crop alloc] init];
[turnip setName:@"Turnip"];
[turnip setSeason:@"Spring"];
[turnip setBagPrice:120];
[turnip setSaleValue:60];
[turnip setDaysToGrow:5];
[turnip setRenewableDays:0];
Crop *potato = [[Crop alloc] init];
[potato setName:@"Potato"];
[potato setSeason:@"Spring"];
[potato setBagPrice:150];
[potato setSaleValue:80];
[potato setDaysToGrow:8];
[potato setRenewableDays:0];
Then what I'm thinking is calling a new class function titled returnCropData: which takes the self.title as a parameter. I'm just not sure if this is my best method... I'd appreciate any suggestions from iOS devs.
Here's the simple class method I have so far - no data matching yet as I'm still trying to figure out which loop would be best. I'm also struggling to figure out the syntax to add an NSString parameter onto the function
+ (Crop *)returnCropData
{
Crop *turnip = [[Crop alloc] init];
[turnip setName:@"Turnip"];
[turnip setSeason:@"Spring"];
[turnip setBagPrice:120];
[turnip setSaleValue:60];
[turnip setDaysToGrow:5];
[turnip setRenewableDays:0];
// more crops here....
NSMutableArray *cropListing = [[NSMutableArray alloc] init];
[cropListing addObject:turnip];
[cropListing addObject:potato];
// add the other crops here...
return potato;
// return any Crop value for now
}
Upvotes: 1
Views: 4047
Reputation: 10772
Apple's Objective-C docs recommend you use objectWithParams:
grammar for class methods (constructors). So in your case, you should change your existing method name to
+ (Crop *)cropWithName:(NSString *)name
And call it with Crop *turnip = [Crop cropWithName:@"Turnip];
and then in your for loop you can check if the passed in name equals the name of your object with [name isEqualToString:turnip.name]
.
This will work, however it seems as though every time that method is called you're creating a ton of Crop objects - time intensive on your part, and memory intensive on the device. Instead, you should look into making a plist file that uses a dictionary to represent each kind of Crop, and then in your creation method you can use your passed in name to look up all the other information about the specified crop. Then you can just return one instance of Crop instead of instantiating a massive amount.
Here's a link to Apple documentation that explains plists:
Specifically, in any objects that I want to pull from a plist I define the following method that takes values from a dictionary and sets an object's properties:
- (id)initWithDictionary:(NSDictionary *)dictionary
{
self = [super init];
[self setValuesForKeysWithDictionary:dictionary];
return self;
}
And then in a class where I want to access an array of data, I would create a synthesized @property and then define this method (in this case, I've got Song objects):
- (NSMutableArray *)songs
{
if (_songs == nil)
{
NSArray *songDicts = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"ChillMix" ofType:@"plist"]];
_songs = [[NSMutableArray alloc] initWithCapacity:[songDicts count]];
// Fast enumeration //
for (NSDictionary *currDict in songDicts)
{
Song *song = [[Song alloc] initWithDictionary:currDict];
[_songs addObject:song];
}
}
return _songs;
}
Here is a sample project I've developed: https://github.com/Jlawr3nc3/MusicLibraryiOS
[NSArray arrayWithContentsOfFile:]
should be your new best friend. It's awesome. If you can format your XML in plist format, you're down to one. single. line. to parse data. (PS normal XML is annoying as hell to parse on iOS so this is a huge time save if you can avoid straight up XML).
Also, I'm not sure what the use case would be for creating a crop object based on a view's title. Since you're already aware of the name of the crop before the view is instantiated, you could create a Crop object and set a Crop property of the view to the crop object you created, and then in viewDidLoad just do self.title = self.crop.name;
. Finally, if you've got a UITableView
of crop objects you shouldn't populate the table view with static text; instead populate it with objects you create from a plist, and then in didSelectRowAtIndexPath:
you can do [self.arrayOfCrops objectAtIndex:indexPath.row]
to get the object you tapped on, and pass it in with the view you load. Anyway, check out Apple's sample code for more info on plists and tableviews etc, 'cause they've got a lot of information on this exact stuff.
Upvotes: 3