0

I have the following array of data which I am fetching from SQLite3 database.

array (
    {
    amount = "$100";
    balance = "$1505";
    date = "06/22/2015";
    id = 16;
    note = Pay;
    type = Pay;
},
    {
    amount = "$1000";
    balance = "$1405";
    date = "06/22/2015";
    id = 15;
    note = Pay;
    type = Pay;
},
    {
    amount = "$200";
    balance = "$405";
    date = "06/22/2015";
    id = 14;
    note = Pay;
    type = Pay;
},
    {
    amount = "$100";
    balance = "$205";
    date = "06/22/2015";
    id = 13;
    note = Pay;
    type = Pay;
},
    {
    amount = "$100";
    balance = "$105";
    date = "06/22/2015";
    id = 12;
    note = Pay;
    type = Pay;
},
    {
    amount = "$50";
    balance = "$5,320.00";
    date = "06/16/2015";
    id = 11;
    note = Pay;
    type = Pay;
},
    {
    amount = "$50";
    balance = "$5,270.00";
    date = "06/09/2015";
    id = 10;
    note = Pay;
    type = Pay;
},
    {
    amount = "$50";
    balance = "$5220";
    date = "06/02/2015";
    id = 9;
    note = Pay;
    type = Pay;
},
    {
    amount = "$100";
    balance = "$5170";
    date = "06/03/2015";
    id = 8;
    note = Pay;
    type = Pay;
},
    {
    amount = "$100";
    balance = "$5070";
    date = "06/02/2015";
    id = 7;
    note = Pay;
    type = Pay;
},
    {
    amount = "$20";
    balance = "$4970";
    date = "05/29/2015";
    id = 6;
    note = water;
    type = Deposit;
},
    {
    amount = "$100";
    balance = "$4950";
    date = "05/29/2015";
    id = 5;
    note = water;
    type = Expense;
},
    {
    amount = "$50";
    balance = "$5050";
    date = "05/29/2015";
    id = 4;
    note = Pay;
    type = Pay;
}

)

I want to make a tableview with sections on yearly basis and in rows each section data will show monthly basis after performing calculation of income and expense. For more info I am attaching a screen shot herewith. enter image description here

I am attempting to solve the problem using the following method.

-(NSMutableArray*)arrangeSection:(NSMutableArray *)source
{
    NSDateFormatter *_formatter=[[NSDateFormatter alloc]init];
    [_formatter setLocale:[NSLocale currentLocale]];
    [_formatter setDateFormat:@"YYYY"];
    NSMutableArray *arrayMain=[NSMutableArray array];
    for (int i=0; i<source.count; i++){
    NSDictionary *dict=source[i];
    NSDateFormatter *_formatterLocal=[[NSDateFormatter alloc]init];
    [_formatterLocal setLocale:[NSLocale currentLocale]];
    [_formatterLocal setDateFormat:@"MM/dd/yyyy"];
    NSDate * date = [_formatterLocal dateFromString:[dict objectForKey:TABLE_DATE]];
    NSString *yy=[_formatter stringFromDate:date];
    NSMutableDictionary *secDict=[NSMutableDictionary dictionary];
    NSMutableArray *secArray=[NSMutableArray array];

    if (i==0){
        [secDict setObject:yy forKey:@"Year"];
        [secArray addObject:dict];
        [secDict setObject:secArray forKey:@"Data"];
        [arrayMain addObject:secDict];
    }
    else{
        BOOL flg=NO;
        for (NSDictionary *dict2  in arrayMain){
            if([[dict2 objectForKey:@"Year"]isEqualToString:yy]){
                flg=YES;
                [[dict2 objectForKey:@"Data"]addObject:dict];
                break;
            }
        }

        if (!flg){
            [secDict setObject:yy forKey:@"Year"];
            [secArray addObject:dict];
            [secDict setObject:secArray forKey:@"Data"];
            [arrayMain addObject:secDict];

        }
    }
}
return arrayMain;

}

Matt
  • 139
  • 12
  • Do you have a specific question or code where you have attempted to solve the problem? – Paulw11 Jun 04 '15 at 22:18
  • I have added the method in my question on which I am working to solve the problem. – Matt Jun 04 '15 at 22:27
  • and what **specific** problem are you having with that code? – Paulw11 Jun 04 '15 at 22:27
  • In the mentioned method I want to make the following dictionary with month wise calculated data. NSDictionary *dict=source[i]; – Matt Jun 04 '15 at 22:29
  • That is a statement of requirement, not a problem statement. – Paulw11 Jun 04 '15 at 22:31
  • I have mentioned my problem dear. If you have the solution please mention. – Matt Jun 04 '15 at 22:33
  • 1
    Your have mentioned a requirement, but not a problem. A problem would be "I am trying to create a row per month, but get all the months in one row". However, If I were you I would start by creating an appropriate data model object for your rows. You will have an instance of this object for each month in each year section. The object will keep the balances and you can use a method on this object to process each transaction and update the balances accordingly. You will have an array of 12 of these objects for each section – Paulw11 Jun 04 '15 at 22:40
  • @Matt how did it go? Did you try my suggested answer below? – Sajjon Jun 05 '15 at 15:43
  • @Sajjon Yes I have tried your answer but that was showing just the way of implementing. Basically I was trying to right an algorithm. I have mentioned that in my answer. – Matt Jun 05 '15 at 18:24
  • @Matt That's quite the chunk of code you got there... It is not super easy to read nor understand. My idea of using models rather than NSDictionary was to make it easy to write clean code for sorting the models. Then you can [sort the model array](http://stackoverflow.com/a/6256848/1311272) based on e.g. an NSDate property in the model. – Sajjon Jun 06 '15 at 10:17

2 Answers2

0

If I understand you requirement correct you want a section per year, each section with 12 rows, one per month.

This should not be too hard to achieve :).

I suggest that you make models of your JSON object:

{
    amount = "$20";
    balance = "$4970";
    date = "05/29/2015";
    id = 6;
    note = water;
    type = Deposit;
}

Let's call this class a "MonthModel", then create a "YearModel" holding 12 (or less, if no data is available for said year) "MonthModels". I am posting a suggestion for a structure of models in the untested code below.

Something like:

YearModel

@interface YearModel()
@property (strong, nonatomic) NSArray *monthModels;
@property (strong, assign) NSInteger year;
@end

@implementation YearModel
- (instancetype)initModelForYear:(NSInteger)year withMonthModels:(NSArray*)monthModels {
    self = [super init];

    if(self) {
        self.year = year;
        self.monthModels = monthModels;
    }
    return self;
}
@end

Your MonthModel

@interface MonthModel()
@property (strong, assign) NSFloat balance;
@property (strong, assign) NSFloat amount;
@end

@implementation MonthModel
- (instancetype)initWithBalance:(NSFloat)balance andAmount:(NSFloat)amount {
    self = [super init];

    if(self) {
        self.balance = balance;
        self.amount = amount;
    }
    return self;
}
@end

If your UIViewController is your UITableViewDataSource, then it can use an array of YearModels

@interface MyViewController() <UITableViewDataSource, UITableViewDelegate>
    @property (strong, nonatomic) IBOutlet UITableView *tableView;
    @property (strong, nonatomic) NSArray* yearModels;
    @end

    @implementation MyViewController

        - (MonthModel*)monthModelForIndexPath:(NSIndexPath*)indexPath {
            YearModel* yearModel = [yearModels objectAtIndex:indexPath.section];
            MonthModel* monthModel = [yearModel.monthModels objectAtIndex:indexPath.row];
            return monthModel;
        }

        #pragma mark - UITableViewDataSource
        - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
            return [yearModels count];
        }

        - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
            YearModel* yearModel = [yearModels objectAtIndex:section];
            return [yearModel.monthModels count];
        }

        - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
            static NSString *cellIdentifier = @"MonthCell";
            MonthCell *cell = (MonthCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
            MonthModel* monthModel = [self monthModelForIndexPath:indexPath];
            [cell updateWithModel:monthModel];
            return cell;
        }

@end

Hopefully it will not be that tricky for you to somewhere in code create a method which reads your data from the SQLite and creates those models suggested above. And then set the "yearModels" property in the UIViewController.

However, please let me know if you need some inspiration the SQLite -> Model conversion.

Good luck!

Sajjon
  • 8,938
  • 5
  • 60
  • 94
0

I have solved my problem by the following method of sorting.

-(NSMutableArray*)arrangeSection:(NSMutableArray *)source
{
    NSDateFormatter *_formatter=[[NSDateFormatter alloc]init];
    [_formatter setLocale:[NSLocale currentLocale]];
    [_formatter setDateFormat:@"YYYY"];
    NSString *year = @"";
    NSString *month = @"";
    NSMutableArray *arrayMain=[[NSMutableArray alloc] init];
    NSMutableDictionary *lastDict = [[NSMutableDictionary alloc] init];
    NSMutableArray *lastArray = [[NSMutableArray alloc] init];
    for (int i=0; i<source.count; i++){
        NSDictionary *dict=source[i];  // Year data dictionary

        NSDateFormatter *_formatterLocal=[[NSDateFormatter alloc]init];
        [_formatterLocal setLocale:[NSLocale currentLocale]];
        [_formatterLocal setDateFormat:@"MM/dd/yyyy"];
        NSDate * date = [_formatterLocal dateFromString:[dict objectForKey:TABLE_DATE]];
        [_formatter setDateFormat:@"YYYY"];
        NSString *currentYear=[_formatter stringFromDate:date];
        if (![year isEqualToString:currentYear]) {
        if (i!=0) {
            [lastDict setObject:year forKey:@"Year"];
            [lastDict setObject:arrayMain forKey:@"Data"];
            [lastArray addObject:lastDict];
            lastDict = [[NSMutableDictionary alloc] init];
            arrayMain=[[NSMutableArray alloc] init];
        }
    }

    [_formatter setDateFormat:@"MMMM"];
    NSString *currentMonth = [_formatter stringFromDate:date];

    if (![month isEqualToString:currentMonth]) {
        NSMutableDictionary *secDict=[[NSMutableDictionary alloc] init];
        [secDict setObject:currentMonth forKey:TABLE_DATE];
        if ([[dict valueForKey:TABLE_TYPE] isEqualToString:@"Expense"]) {
           [secDict setObject:[dict valueForKey:TABLE_AMOUNT] forKey:TABLE_AMOUNT];
        }
        else
        {
            [secDict setObject:@"0" forKey:TABLE_AMOUNT];
        }
        if ([[dict valueForKey:TABLE_TYPE] isEqualToString:@"Deposit"])
        {
            [secDict setObject:[dict valueForKey:TABLE_AMOUNT] forKey:TABLE_NOTE];
        }
        else
        {
            [secDict setObject:@"0" forKey:TABLE_NOTE];
        }

        [secDict setObject:[dict valueForKey:TABLE_BALANCE] forKey:TABLE_BALANCE];
        [arrayMain addObject:secDict];
    }
    else
    {
        NSMutableDictionary *previousOBJ= [arrayMain objectAtIndex:[arrayMain count]-1];
        if ([[dict valueForKey:TABLE_TYPE] isEqualToString:@"Expense"])
        {
            [previousOBJ setValue:[NSString stringWithFormat:@"%d", [[previousOBJ valueForKey:TABLE_AMOUNT] integerValue] + [[dict valueForKey:TABLE_AMOUNT] integerValue]] forKey:TABLE_AMOUNT];
        }

        if ([[dict valueForKey:TABLE_TYPE] isEqualToString:@"Deposit"])
        {
            [previousOBJ setValue:[NSString stringWithFormat:@"%d", [[previousOBJ valueForKey:TABLE_NOTE] integerValue] + [[dict valueForKey:TABLE_AMOUNT] integerValue]] forKey:TABLE_NOTE];
        }

        [arrayMain replaceObjectAtIndex:[arrayMain count]-1 withObject:previousOBJ];
    }

    month = currentMonth;
    year = currentYear;
    if (i==source.count-1) {
        [lastDict setObject:year forKey:@"Year"];
        [lastDict setObject:arrayMain forKey:@"Data"];
        [lastArray addObject:lastDict];
    }

}
return lastArray;

}

Matt
  • 139
  • 12