double MeanTime(SEL selector){
NSArray *dataList = GetDataList();
if ([dataList count] == 0){
return 0.0;
}
double cnt = (double) [dataList count];
double sum = 0.0;
for (StatData *data in dataList){
if ([data respondsToSelector:selector]){
sum += [[data performSelector: selector] doubleValue];
}
}
return sum/cnt;
}
double MeanDownloadTime(void){
return MeanTime(@selector(downloadTime));
}
double MeanProcessingTime(void){
return MeanTime(@selector(processingTime));
}
double MeanTotalTime(void){
return MeanTime(@selector(totalTime));
}
Yeah, I know, what's up with the C-style functions? This was inherited code where I was only changing the implementation of those functions, and I didn't feel like wrapping them in a nice pretty class just for the blog. The StatData class has several synthesized properties, including downloadTime, processingTime, and totalTime. I needed three functions that iterated over a list of StatData and computed the average of these properties. Objective-C's selectors provided a nice way to do this. I have to admit that I tried to over-think this at first, and tried using @selector(getDownloadTime:) at first, instead of @selector(downloadTime). I thought that this would be the method name that the compiler would synthesize from the property. This didn't even work, but the more obvious, straightforward usage did.
If an item in the dataList does not respond to selector, then MeanTime() will return an incorrect average. It will divide by the number of items in dataList not the number of items from dataList that were summed.
ReplyDelete(If having a dataList full of different items isn't something legal, then I would just take off the the respondsToSelector: test. That way, if something crazy gets passed in, it'll fail faster).