0

I am reading Apple's Key Value Programming Guide. In the topic, Simple Collection Operators, I read:

The following example returns the average value of the transaction amount for the objects in transactions: NSNumber *transactionAverage=[transactions valueForKeyPath:"@avg.amount"];

I attempt to write a program in which I can use the above. Below are the files of that program. I am unable to understand why the above does not work for me.

Transaction.h

    #import <Foundation/Foundation.h>

@interface Transaction : NSObject
{
NSString *payee;
NSNumber *amount;
NSDate *date;
}
- (void) setPayee: (NSString *) aP 
    setAmount: (NSNumber *) aN
      setDate: (NSDate *) aD;

@end

Transaction.m #import "Transaction.h"

@implementation Transaction
- (void) setPayee: (NSString *) aP 
    setAmount: (NSNumber *) aN
      setDate: (NSDate *) aD 
{
payee = aP;
amount = aN;
date = aD;
} 
@end

TransactionDataBase.h

#import <Foundation/Foundation.h>
#import "Transaction.h"
@interface TransactionDataBase : NSObject
{
NSMutableArray *tArray;
}
  - (id) objectInTArrayAtIndex: (NSUInteger) index;
- (void) insertObject: (Transaction *) tA
inTArrayAtIndex: (NSUInteger) index;
  - (NSUInteger) countOfTArray;
  @end

TransactionDataBase.m

     #import "TransactionDataBase.h"

   @implementation TransactionDataBase
  - (id) init
  {
self = [super init];
if (self) {
    tArray = [[NSMutableArray alloc] initWithCapacity:40];
   }
    return self;
  }

    - (id) objectInTArrayAtIndex: (NSUInteger) index
  {
  return [tArray objectAtIndex:index];
  }

  - (void) insertObject: (Transaction *) tA
    inTArrayAtIndex: (NSUInteger) index
 {
[tArray insertObject:tA atIndex:index];
   }

 - (NSUInteger) countOfTArray
  {
return [tArray count];
    }
   @end


  main.m:


  #import <Foundation/Foundation.h>
    #import "Transaction.h"
   #import "TransactionDataBase.h"

    int main(int argc, const char * argv[])
   {

      @autoreleasepool {

    Transaction *t1 = [[Transaction alloc] init];
    Transaction *t2 = [[Transaction alloc] init];
    Transaction *t3 = [[Transaction alloc] init];

    NSDate *nowDate = [[NSDate alloc]  initWithString:@"2.4.2012"];
    NSDate *nowDate2 = [[NSDate alloc] initWithString:@"2.4.2012"];
    [t1 setPayee:@"c" setAmount:[NSNumber numberWithInt:3000] setDate:nowDate];

    [t2 setPayee:@"c" setAmount:[NSNumber numberWithInt:5000] setDate:nowDate2];


    [t3 setPayee:@"y" setAmount:[NSNumber numberWithInt:1000] setDate:nowDate2];

    TransactionDataBase *db1 = [[TransactionDataBase alloc] init];
    [db1 insertObject:t1 inTArrayAtIndex:0];
    [db1 insertObject:t2 inTArrayAtIndex:1];
    [db1 insertObject:t3 inTArrayAtIndex:2];
    NSNumber *avgT = [db1 valueForKeyPath: "@avg.amount"];
    NSLog(@"%@", avgT);


}
return 0;
  }
Rounak
  • 613
  • 3
  • 8
  • 22

2 Answers2

0

Your TransactionDataBase class must support a key path that returns an array with the values it is storing. Also, the Transaction class must support key-value coding for the key @"amount". You have to add appropriate properties to these classes.

The key path you use in [db1 valueForKeyPath: "t1.@avg.amount"] must then take the names of these properties into account, i.e. with your current code, the array of items in TransactionDataBase must be accessible via the key @"t1".

Ole Begemann
  • 135,006
  • 31
  • 278
  • 256
0

I think you want NSNumber *avgT = [db1 valueForKeyPath:@"@avg.amount"]; You want to average over all the "amount" values in your array, not just in the t1 object -- it doesn't make sense to average over one value.

rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • What do you mean "how to make it work"? If it's not working now, what's happening? Are you getting an error? – rdelmar Apr 20 '12 at 18:14
  • See my edited answer -- the key path is a string, so you still need the @ at the beginning as well as the one in front of avg. – rdelmar Apr 20 '12 at 18:25
  • NSNumber *avgT = [db1 valueForKeyPath: @"@avg.amount"]; gives the error: Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ valueForUndefinedKey:]: this class is not key value coding-compliant for the key @avg.' *** First throw call stack: ( 0 CoreFoundation – Rounak Apr 20 '12 at 18:35
  • I'm not sure what's going on with your TransactionDatabase, but that's the problem -- if you add t1,t2, and t3 to an NSMutable array it works fine. – rdelmar Apr 20 '12 at 19:10
  • 1
    I don't know why you defined the TransactionDatabase class, it's not doing anything you couldn't just do with an NSMutableArray. I did get your code to work by making TransactionDataBase a subclass of NSArray and implementing the count and objectAtIndex: methods, but why bother? – rdelmar Apr 20 '12 at 20:02