2017-07-03 1 views
2

Ich habe Programm wie folgt: ..- Allerdings mag ich die Daten sortieren absteigend nach Datum in der TitleForHeaderInSection, und will auch das Datum in der Kopfzeile zu formatieren alsWie Datum sortieren auf 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]; 
Hier

ist der 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 
+0

können Sie Ihr Datenformat hinzufügen? – KKRocks

+0

Was macht Ihr Code derzeit? Ich meine, was funktioniert und was nicht? – Larme

+0

Dies sind die Daten, die ich abrufen möchte: http://borindatabase.000webhostapp.com/jsonData.php Die Daten wurden perfekt abgerufen, aber es wird nicht richtig sortiert. Und ich weiß nicht, wie man das Datum in TitleForHeaderInSection so formatiert: Mo, 3 Jul 2017 –

Antwort

0

die Grundidee ist, dass Wörterbücher ungeordnet sind, so müssen Sie eine Möglichkeit, sie in der richtigen Reihenfolge abzurufen. Ich könnte vorschlagen, ein sortiertes Array der Schlüssel des Wörterbuchs zu erstellen.

// 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]; 
}]; 

Sie können dann dieses dates Objekt verwenden, um die „Abschnitte“ der Tabelle Ansicht zu vertreten und dass dann, welcher Eintrag im Wörterbuch verwenden zu wissen, zurückzukehren:

- (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; 
} 

Hinweis, Ich würde vorschlagen, einige nicht verwandte Änderungen an Ihrem Code:

  1. Ich würde vorschlagen, einen benutzerdefinierten Objekttyp verwenden e zum Inhalt Ihres JSON. Dies bietet eine stärkere Typisierung als eine einfache NSDictionary.

    Ich würde auch sicherstellen, dass die Typen natürlichen eingegeben (zum Beispiel der id sieht aus wie es ein NSInteger sein soll, die date sieht aus wie es ein NSDate sein soll).

    Ich würde diesem benutzerdefinierten Typ auch einen initWithDictionary Initialisierer geben, um den Parsing-Code zu vereinfachen.

  2. Die Logik zum Erstellen des Wörterbuchs nach Datum (Ihre convertSectionTableData) kann ein wenig vereinfacht werden.

  3. Ihr Datumsformatierer für die Benutzeroberfläche sollte locale von nicht verwenden. Ihr Formatierer, der den JSON analysiert, sollte (oder genauer gesagt, er sollte en_US_POSIX verwenden), aber wenn Sie das Format in der Benutzeroberfläche präsentieren, sollten Sie das eigene Gebietsschema des Benutzers verwenden.

    Ihr Datumsformatierer für die Benutzeroberfläche sollte auch keinen festen dateFormat String verwenden. Verwenden Sie eines der bereits vorhandenen dateStyle, oder erstellen Sie eine lokalisierte Version unter Verwendung von dateFormatdateFormatFromTemplate.

Wie dem auch sei, die zusammen ziehen, erhalten Sie so etwas wie:

@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 

Und

@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 
+0

Vielen Dank Herr Rob. Die Wörterbücher wurden sortiert, aber ich würde es vorziehen, Descending zu sortieren.Ich möchte, dass das neueste Datum (Montag, 25. Juni 2017) oben und das älteste Datum (Montag, 5. Juni 2017) ganz unten ist. Und noch eins möchte ich die Daten 20 Reihe auf einmal .. holen und dann fortfahren, weitere 20 Reihe mehr zu holen, wenn wir scroll die untere Linie erreichen. Vielen Dank auf Ihre freundliche Unterstützung .. –

+0

Wenn Sie möchten, dass es in absteigender Reihenfolge sortiert, tauschen Sie 'obj1' und' obj2' im 'sortedArrayUsingComparator', wie ich in der überarbeiteten Antwort habe. In Bezug auf das Abrufen der Zeilen 20 zu einem Zeitpunkt wurde das obige vorausgesetzt, dass Sie alle Datensätze heruntergeladen haben. Die Herausforderung beim Paging besteht darin, dass dies Ihre Sortierung durcheinander bringt. Wenn Sie seitenweise abrufen möchten, müssen Sie (a) den Webdienst ändern, um sie für Sie zu sortieren. (b) Ändern Sie Ihren Client-Code so, dass er nicht sortiert, sondern lediglich in Abschnitte zusammengefasst wird. (c) Ändern Sie Ihren Web-Service, um zusätzliche Parameter für die Seitenparameter zu übernehmen. – Rob

+0

Vielen Dank Herr Rob .. es ist sehr schwierig .. Haben Sie irgendwelche Beispiele oder Tutorials in Bezug auf diese? Bitte beraten .. Danke –