如何在TitleForHeaderInSection上排序日期

时间:2022-01-31 20:46:17

I have program as below: ..- However, I want to sort the data descending by date in the TitleForHeaderInSection, and also want to format the date in the Header as

我有如下程序:..-但是,我想在TitleForHeaderInSection中按日期降序排序数据,并且还希望将标题中的日期格式化为

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]];
//    [formatter setDateStyle:NSDateFormatterMediumStyle];
[formatter setDateFormat:@"EEE, d MMM yyyy"];
NSDate *headerDate = (NSDate *)[managedObject valueForKey:@"dateCreated"];
NSString *headerTitle = [formatter stringFromDate:headerDate];

Here is the Code:

这是代码:

- (void)viewDidLoad {
    [super viewDidLoad];

    [self.navigationItem setTitle:@"List of Items"];

    NSURL *serverURL = [NSURL URLWithString:SERVER_URL];
    [[DataManager sharedInstance] loadData:serverURL withCompletion:^(NSArray *itemListArray, NSError *error) {
        if (error != nil) {
            UIAlertView *errorAlertView = [[UIAlertView alloc] initWithTitle:@"Server Error" message:@"Unable to fetch Data from Server" delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
            [errorAlertView show];
        }
        else {
            fetchData = [self convertSectionTableData:itemListArray keyString:@"date"];
            [self.listTableView reloadData];
        }
    }];
    [self.listTableView reloadData];}


- (NSMutableDictionary *)convertSectionTableData:(NSArray *)convertDataSet keyString:(NSString *)keyString {
    NSMutableDictionary *outputData = [NSMutableDictionary dictionary];
    NSMutableArray *temp = [NSMutableArray array];
    NSString *key = NULL;
    for (NSDictionary *dic in convertDataSet) {

        if (key == NULL) {
            key = [dic objectForKey:keyString];
        } else if (key != [dic objectForKey:keyString]) {
            [outputData setValue:temp forKey:key];
            temp = [NSMutableArray array];

            key = [dic objectForKey:keyString];
        }

        if ([[dic objectForKey:keyString] isEqualToString: key]) {
            [temp addObject:dic];
        }

        if (dic == [convertDataSet lastObject]) {
            [outputData setValue:temp forKey:key];
        }
    }

    return outputData;}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [fetchData count];}

-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [[fetchData allValues][section] count];}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *cellIdentifier = @"CustomListTableCell";

    CustomListTableCell *cell = (CustomListTableCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    int section = (int)indexPath.section;
    int row = (int)indexPath.row;

    NSDictionary *data = [[fetchData allValues][section] objectAtIndex:row];

    cell.homeLabel.text = [data objectForKey:@"home"];

    return cell;}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return [fetchData allKeys][section];}

@end

1 个解决方案

#1


0  

The basic idea is that dictionaries are unordered, so you need some way to retrieve them in the correct order. I might suggest building a sorted array of the keys of the dictionary.

基本思想是字典是无序的,因此您需要某种方式以正确的顺序检索它们。我可能会建议构建字典键的排序数组。

// build dictionary of objects, keyed by date

NSMutableDictionary *objectsForDates = ...

// build sorted array of dates in descending order

NSArray *dates = [[objectsForDates allKeys] sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
    return [obj2 compare:obj1];
}];

You can then use this dates object to represent the "sections" of your table view and then use that to know which entry in your dictionary to return:

然后,您可以使用此日期对象来表示表视图的“部分”,然后使用它来知道要返回的字典中的哪个条目:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [self.dates count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.objectsForDates[self.dates[section]] count];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return [self.formatter stringFromDate:self.dates[section]];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    Location *object = self.objectsForDates[self.dates[indexPath.section]][indexPath.row];
    cell.textLabel.text = object.home;
    return cell;
}

Note, I would suggest a couple of unrelated changes to your code:

请注意,我建议您对代码进行一些不相关的更改:

  1. I'd suggest using a custom object type to contents of your JSON. This offers stronger typing than a simple NSDictionary.

    我建议使用自定义对象类型来表示您的JSON内容。这提供了比简单的NSDictionary更强的输入。

    I'd also make sure that the types are more naturally typed (e.g. the id looks like it should be a NSInteger; the date looks like it should be a NSDate).

    我还要确保类型更自然地类型化(例如,id看起来应该是NSInteger;日期看起来应该是NSDate)。

    I'd also give this custom type an initWithDictionary initializer, to simplify the parsing code.

    我还给这个自定义类型一个initWithDictionary初始化程序,以简化解析代码。

  2. The logic for building the dictionary keyed by date (your convertSectionTableData) can be simplified a bit.

    构建按日期键入的字典(您的convertSectionTableData)的逻辑可以简化一点。

  3. Your date formatter for the UI should not use locale of en_US. Your formatter that's parsing the JSON should (or more accurately, it should use en_US_POSIX), but when presenting the format in the UI, you should use the users' own locale.

    UI的日期格式化程序不应使用en_US的语言环境。您解析JSON的格式化程序应该(或者更确切地说,它应该使用en_US_POSIX),但在UI中呈现格式时,您应该使用用户自己的语言环境。

    Your date formatter for the UI also should not use a fixed dateFormat string. Either use one of the pre-existing dateStyle, or if you must use dateFormat, build a localized version using dateFormatFromTemplate.

    UI的日期格式化程序也不应使用固定的dateFormat字符串。要么使用预先存在的dateStyle,要么必须使用dateFormat,使用dateFormatFromTemplate构建本地化版本。

Anyway, pulling that together, you get something like:

无论如何,把它拉到一起,你会得到类似的东西:

@interface Location : NSObject
@property (nonatomic) NSInteger identifier;
@property (nonatomic, copy) NSString *home;
@property (nonatomic, strong) NSDate *date;

- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
@end

@implementation Location

- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
    self = [super init];
    if (self) {
        self.identifier = [dictionary[@"id"] integerValue];
        self.home = dictionary[@"home"];
        [self setDateFromString:dictionary[@"date"]];
    }
    return self;
}

- (void)setDateFromString:(NSString *)string {
    static NSDateFormatter *formatter;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        formatter = [[NSDateFormatter alloc] init];
        formatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
        formatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
        formatter.dateFormat = @"yyyy-MM-dd";
    });

    self.date = [formatter dateFromString:string];
}
@end

And

@interface ViewController ()

@property (nonatomic, strong) NSMutableDictionary *objectsForDates;
@property (nonatomic, strong) NSArray *dates;

@property (nonatomic, strong) NSDateFormatter *formatter;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // set formatter for output

    self.formatter = [[NSDateFormatter alloc] init];
    [self.formatter setDateFormat:[NSDateFormatter dateFormatFromTemplate:@"EEEdMMMyyyy" options:0 locale:[NSLocale currentLocale]]];
    self.formatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];

    // perform request

    NSURL *url = [NSURL URLWithString:@"http://borindatabase.000webhostapp.com/jsonData.php"];
    [[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error || !data) {
            NSLog(@"networkError: %@", error);
            return;
        }

        NSError *parseError;
        NSArray *values = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
        if (![values isKindOfClass:[NSArray class]]) {
            NSLog(@"parseError: %@", parseError);
        }

        // build dictionary of objects, keyed by date

        NSMutableDictionary *objectsForDates = [[NSMutableDictionary alloc] init];
        for (NSDictionary *value in values) {
            Location *object = [[Location alloc] initWithDictionary:value];
            NSMutableArray *objects = objectsForDates[object.date];
            if (!objects) {
                objects = [[NSMutableArray alloc] init];
                objectsForDates[object.date] = objects;
            }
            [objects addObject:object];
        }

        // build sorted array of dates in descending order

        NSArray *dates = [[objectsForDates allKeys] sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
            return [obj2 compare:obj1];
        }];

        // now update UI

        dispatch_async(dispatch_get_main_queue(), ^{
            self.objectsForDates = objectsForDates;
            self.dates = dates;
            [self.tableView reloadData];
        });

    }] resume];

}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [self.dates count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.objectsForDates[self.dates[section]] count];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return [self.formatter stringFromDate:self.dates[section]];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    Location *object = self.objectsForDates[self.dates[indexPath.section]][indexPath.row];
    cell.textLabel.text = object.home;
    return cell;
}

@end

#1


0  

The basic idea is that dictionaries are unordered, so you need some way to retrieve them in the correct order. I might suggest building a sorted array of the keys of the dictionary.

基本思想是字典是无序的,因此您需要某种方式以正确的顺序检索它们。我可能会建议构建字典键的排序数组。

// build dictionary of objects, keyed by date

NSMutableDictionary *objectsForDates = ...

// build sorted array of dates in descending order

NSArray *dates = [[objectsForDates allKeys] sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
    return [obj2 compare:obj1];
}];

You can then use this dates object to represent the "sections" of your table view and then use that to know which entry in your dictionary to return:

然后,您可以使用此日期对象来表示表视图的“部分”,然后使用它来知道要返回的字典中的哪个条目:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [self.dates count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.objectsForDates[self.dates[section]] count];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return [self.formatter stringFromDate:self.dates[section]];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    Location *object = self.objectsForDates[self.dates[indexPath.section]][indexPath.row];
    cell.textLabel.text = object.home;
    return cell;
}

Note, I would suggest a couple of unrelated changes to your code:

请注意,我建议您对代码进行一些不相关的更改:

  1. I'd suggest using a custom object type to contents of your JSON. This offers stronger typing than a simple NSDictionary.

    我建议使用自定义对象类型来表示您的JSON内容。这提供了比简单的NSDictionary更强的输入。

    I'd also make sure that the types are more naturally typed (e.g. the id looks like it should be a NSInteger; the date looks like it should be a NSDate).

    我还要确保类型更自然地类型化(例如,id看起来应该是NSInteger;日期看起来应该是NSDate)。

    I'd also give this custom type an initWithDictionary initializer, to simplify the parsing code.

    我还给这个自定义类型一个initWithDictionary初始化程序,以简化解析代码。

  2. The logic for building the dictionary keyed by date (your convertSectionTableData) can be simplified a bit.

    构建按日期键入的字典(您的convertSectionTableData)的逻辑可以简化一点。

  3. Your date formatter for the UI should not use locale of en_US. Your formatter that's parsing the JSON should (or more accurately, it should use en_US_POSIX), but when presenting the format in the UI, you should use the users' own locale.

    UI的日期格式化程序不应使用en_US的语言环境。您解析JSON的格式化程序应该(或者更确切地说,它应该使用en_US_POSIX),但在UI中呈现格式时,您应该使用用户自己的语言环境。

    Your date formatter for the UI also should not use a fixed dateFormat string. Either use one of the pre-existing dateStyle, or if you must use dateFormat, build a localized version using dateFormatFromTemplate.

    UI的日期格式化程序也不应使用固定的dateFormat字符串。要么使用预先存在的dateStyle,要么必须使用dateFormat,使用dateFormatFromTemplate构建本地化版本。

Anyway, pulling that together, you get something like:

无论如何,把它拉到一起,你会得到类似的东西:

@interface Location : NSObject
@property (nonatomic) NSInteger identifier;
@property (nonatomic, copy) NSString *home;
@property (nonatomic, strong) NSDate *date;

- (instancetype)initWithDictionary:(NSDictionary *)dictionary;
@end

@implementation Location

- (instancetype)initWithDictionary:(NSDictionary *)dictionary {
    self = [super init];
    if (self) {
        self.identifier = [dictionary[@"id"] integerValue];
        self.home = dictionary[@"home"];
        [self setDateFromString:dictionary[@"date"]];
    }
    return self;
}

- (void)setDateFromString:(NSString *)string {
    static NSDateFormatter *formatter;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        formatter = [[NSDateFormatter alloc] init];
        formatter.locale = [NSLocale localeWithLocaleIdentifier:@"en_US_POSIX"];
        formatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];
        formatter.dateFormat = @"yyyy-MM-dd";
    });

    self.date = [formatter dateFromString:string];
}
@end

And

@interface ViewController ()

@property (nonatomic, strong) NSMutableDictionary *objectsForDates;
@property (nonatomic, strong) NSArray *dates;

@property (nonatomic, strong) NSDateFormatter *formatter;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // set formatter for output

    self.formatter = [[NSDateFormatter alloc] init];
    [self.formatter setDateFormat:[NSDateFormatter dateFormatFromTemplate:@"EEEdMMMyyyy" options:0 locale:[NSLocale currentLocale]]];
    self.formatter.timeZone = [NSTimeZone timeZoneForSecondsFromGMT:0];

    // perform request

    NSURL *url = [NSURL URLWithString:@"http://borindatabase.000webhostapp.com/jsonData.php"];
    [[[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error || !data) {
            NSLog(@"networkError: %@", error);
            return;
        }

        NSError *parseError;
        NSArray *values = [NSJSONSerialization JSONObjectWithData:data options:0 error:&parseError];
        if (![values isKindOfClass:[NSArray class]]) {
            NSLog(@"parseError: %@", parseError);
        }

        // build dictionary of objects, keyed by date

        NSMutableDictionary *objectsForDates = [[NSMutableDictionary alloc] init];
        for (NSDictionary *value in values) {
            Location *object = [[Location alloc] initWithDictionary:value];
            NSMutableArray *objects = objectsForDates[object.date];
            if (!objects) {
                objects = [[NSMutableArray alloc] init];
                objectsForDates[object.date] = objects;
            }
            [objects addObject:object];
        }

        // build sorted array of dates in descending order

        NSArray *dates = [[objectsForDates allKeys] sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
            return [obj2 compare:obj1];
        }];

        // now update UI

        dispatch_async(dispatch_get_main_queue(), ^{
            self.objectsForDates = objectsForDates;
            self.dates = dates;
            [self.tableView reloadData];
        });

    }] resume];

}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [self.dates count];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return [self.objectsForDates[self.dates[section]] count];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    return [self.formatter stringFromDate:self.dates[section]];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    Location *object = self.objectsForDates[self.dates[indexPath.section]][indexPath.row];
    cell.textLabel.text = object.home;
    return cell;
}

@end