2013-11-15 3 views
3

У меня возникли проблемы с обновлением моего старого кода, который сделал синхронные вызовы JSOn на новый, который делает асинхронные вызовы с использованием AFNetworking.Использование UICollectionReusableView для группировки ячеек

В моем старом кодексе я группировал ячейки с помощью UICollectionReusableView с использованием строки даты ("release_date"), все это было сделано в viewDidLoad. Теперь с AFNetworking я переместил все из viewDidLoad, поэтому я застрял, пытаясь понять, как объединить мой старый код с моим новым.

Это новый код, который я должен разобрать мой JSON с AFNetworking:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    self.upcomingReleases = [[NSMutableArray alloc] init]; 

    [self makeReleasesRequests]; 

    [self.collectionView registerClass:[ReleaseCell class] forCellWithReuseIdentifier:@"ReleaseCell"]; 
} 

-(void)makeReleasesRequests //AFNetworking Call 
{ 
    NSURL *url = [NSURL URLWithString:@"http://www.soleresource.com/upcoming.json"]; 

    NSURLRequest *request = [NSURLRequest requestWithURL:url]; 

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request]; 

    operation.responseSerializer = [AFJSONResponseSerializer serializer]; 

    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 

     NSLog(@"@"); 

     self.upcomingReleases = [responseObject objectForKey:@"upcoming_releases"]; 

     [self.collectionView reloadData]; 

    } failure:nil]; 

    [operation start]; 
} 

кода я имел в моем viewDidLoad, прежде чем я начал использовать AFNetworking сделать JSON вызовов и «группа» мои клетки:

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    NSURL *upcomingReleaseURL = [NSURL URLWithString:@"http://www.soleresource.com/upcoming.json"]; 

    NSData *jsonData = [NSData dataWithContentsOfURL:upcomingReleaseURL]; 

    NSError *error = nil; 

    NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error]; 

    NSArray *upcomingReleasesArray = [dataDictionary objectForKey:@"upcoming_releases"]; 

    //This is the dateFormatter we'll need to parse the release dates 
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 
    [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"]; 
    NSTimeZone *est = [NSTimeZone timeZoneWithAbbreviation:@"EST"]; 
    [dateFormatter setTimeZone:est]; 
    [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]]; //A bit of an overkill to avoid bugs on different locales 

    //Temp array where we'll store the unsorted bucket dates 
    NSMutableArray *unsortedReleaseWeek = [[NSMutableArray alloc] init]; 
    NSMutableDictionary *tmpDict = [[NSMutableDictionary alloc] init]; 

    for (NSDictionary *upcomingReleaseDictionary in upcomingReleasesArray) { 

     //We find the release date from the string 
     NSDate *releaseDate = [dateFormatter dateFromString:[upcomingReleaseDictionary objectForKey:@"release_date"]]; 

     //We create a new date that ignores everything that is not the actual day (ignoring stuff like the time of the day) 
     NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
     NSDateComponents *components = 
     [gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:releaseDate]; 

     //This will represent our releases "bucket" 
     NSDate *bucket = [gregorian dateFromComponents:components]; 

     //We get the existing objects in the bucket and update it with the latest addition 
     NSMutableArray *releasesInBucket = [tmpDict objectForKey:bucket]; 
     if (!releasesInBucket){ 
      releasesInBucket = [NSMutableArray array]; 
      [unsortedReleaseWeek addObject:bucket]; 
     } 

     UpcomingRelease *upcomingRelease = [UpcomingRelease upcomingReleaseWithName:[upcomingReleaseDictionary objectForKey:@"release_name"]]; 
     upcomingRelease.release_date = [upcomingReleaseDictionary objectForKey:@"release_date"]; 
     upcomingRelease.release_date = [upcomingReleaseDictionary objectForKey:@"release_date"]; 
     [releasesInBucket addObject:upcomingRelease]; 
     [tmpDict setObject:releasesInBucket forKey:bucket]; 
    } 

    [unsortedReleaseWeek sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { 
     NSDate* date1 = obj1; 
     NSDate* date2 = obj2; 
     //This will sort the dates in ascending order (earlier dates first) 
     return [date1 compare:date2]; 
     //Use [date2 compare:date1] if you want an descending order 
    }]; 

    self.releaseWeekDictionary = [NSDictionary dictionaryWithDictionary:tmpDict]; 
    self.releaseWeek = [NSArray arrayWithArray:unsortedReleaseWeek]; 

    [self.collectionView registerClass:[ReleaseCell class] forCellWithReuseIdentifier:@"ReleaseCell"]; 
} 

CollectionViewCell

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { 
    static NSString *identifier = @"Cell"; 

    ReleaseCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath]; 

    // Part of my new code AFNetworking 
    NSDictionary *upcomingReleaseDictionary = [self.upcomingReleases objectAtIndex:indexPath.row]; 
    // 

    // I had this in my old code 
    UpcomingRelease *upcomingRelease = [self.releaseWeekDictionary objectForKey:self.releaseWeek[indexPath.section]][indexPath.row]; 
    // 
    cell.release_name.text = upcomingRelease.release_name; 

    return cell; 
} 

Это остальное:

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView 
{ 
    return [self.releaseWeek count]; 
} 

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 
{ 
    return [[self.releaseWeekDictionary objectForKey:self.releaseWeek[section]] count]; 
} 

-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath 
{ 
    ReleaseWeek *releaseWeek = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"releaseWeek" forIndexPath:indexPath]; 

    //We tell the formatter to produce a date in the format "Name-of-the-month day" 
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 
    [dateFormatter setDateFormat:@"MMMM dd"]; 
    NSTimeZone *est = [NSTimeZone timeZoneWithAbbreviation:@"EST"]; 
    [dateFormatter setTimeZone:est]; 
    [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]]; 

    //We read the bucket date and feed it to the date formatter 
    NSDate *releaseWeekDate = self.releaseWeek[indexPath.section]; 

    releaseWeek.releaseDate.text = [[dateFormatter stringFromDate:releaseWeekDate] uppercaseString]; 
    return releaseWeek; 
} 

Я в основном пытаюсь выяснить, как взять код, сгруппированные мои клетки строки, дата и интегрировать его с моим новым кодом.

Спасибо.

ответ

2

Think MVC. Отделите свою модель (материал, которая поступает из сети) в отдельный класс, который выполняет сетевые операции, и группирует вещи в массивы и словари. Контроллер вашего вида должен просто наблюдать за моделью. Вы можете использовать делегацию или (мой любимый) KVO, чтобы узнать, когда модель обновила доступные данные. Затем вы просто обновляете представление коллекции. Контроллер вашего представления должен просто быть интерфейсом между моделью и представлениями. Если вы отделите вещи таким образом, вы обнаружите, что это намного более естественно, и вы не боретесь с системой.

2

Вы ближе, чем думаете.

Проще говоря, все, что вы делали в viewDidLoad: (все между назначением jsonData для регистрации класса представления коллекции) в блок обратного вызова вашего вызова AFNetworking (где jsonData теперь называется responseObject).

В конце блока обратного вызова просто вызовите [self.collectionView reloadData], и представление вашей коллекции перезагрузится (т. Е. Вызовет numberOfItems и cellForItemAtIndexPath для каждого элемента).

В ваших методах UICollectionViewDataSource, которые возвращают количество разделов и элементов, просто верните 0, если свойства, содержащие вашу модель, равны нулю или пусты.

-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView 
{ 
    // Correctly returns 0 if nil or empty. 
    return [self.releaseWeek count]; 
} 

-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section 
{ 
    if(!self.releaseWeekDictionary[section] || !self.releaseWeek[section]) { 
     return 0; 
    }else{ 
     return [self.releaseWeekDictionary[self.releaseWeek[section]] count]; 
    } 
} 

Ниже приведен код подвалов в вашем блоке завершения.

[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) { 

     NSLog(@"@"); 

     NSArray *upcomingReleasesArray = [dataDictionary objectForKey:@"upcoming_releases"]; 

     //This is the dateFormatter we'll need to parse the release dates 
     NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; 
     [dateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"]; 
     NSTimeZone *est = [NSTimeZone timeZoneWithAbbreviation:@"EST"]; 
     [dateFormatter setTimeZone:est]; 
     [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]]; //A bit of an overkill to avoid bugs on different locales 

     //Temp array where we'll store the unsorted bucket dates 
     NSMutableArray *unsortedReleaseWeek = [[NSMutableArray alloc] init]; 
     NSMutableDictionary *tmpDict = [[NSMutableDictionary alloc] init]; 

     for (NSDictionary *upcomingReleaseDictionary in upcomingReleasesArray) { 

      //We find the release date from the string 
      NSDate *releaseDate = [dateFormatter dateFromString:[upcomingReleaseDictionary objectForKey:@"release_date"]]; 

      //We create a new date that ignores everything that is not the actual day (ignoring stuff like the time of the day) 
      NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
      NSDateComponents *components = 
      [gregorian components:(NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit) fromDate:releaseDate]; 

      //This will represent our releases "bucket" 
      NSDate *bucket = [gregorian dateFromComponents:components]; 

      //We get the existing objects in the bucket and update it with the latest addition 
      NSMutableArray *releasesInBucket = [tmpDict objectForKey:bucket]; 
      if (!releasesInBucket){ 
       releasesInBucket = [NSMutableArray array]; 
       [unsortedReleaseWeek addObject:bucket]; 
      } 

      UpcomingRelease *upcomingRelease = [UpcomingRelease upcomingReleaseWithName:[upcomingReleaseDictionary objectForKey:@"release_name"]]; 
      upcomingRelease.release_date = [upcomingReleaseDictionary objectForKey:@"release_date"]; 
      upcomingRelease.release_date = [upcomingReleaseDictionary objectForKey:@"release_date"]; 
      [releasesInBucket addObject:upcomingRelease]; 
      [tmpDict setObject:releasesInBucket forKey:bucket]; 
     } 

     [unsortedReleaseWeek sortUsingComparator:^NSComparisonResult(id obj1, id obj2) { 
      NSDate* date1 = obj1; 
      NSDate* date2 = obj2; 
      //This will sort the dates in ascending order (earlier dates first) 
      return [date1 compare:date2]; 
      //Use [date2 compare:date1] if you want an descending order 
     }]; 

     self.releaseWeekDictionary = [NSDictionary dictionaryWithDictionary:tmpDict]; 
     self.releaseWeek = [NSArray arrayWithArray:unsortedReleaseWeek]; 

     [self.collectionView reloadData]; 

    } failure:nil]; 

Edit: В своем коде, вы больше не назначая ничего upcomingReleases (блок комментировал строк кода 91-102), и вы врезаться ссылки на индекс, который не существует в массиве.Исправление легко:

109: self.upcomingReleases = [dataDictionary objectForKey:@"upcoming_releases"]; 

122: for (NSDictionary *upcomingReleaseDictionary in self.upcomingReleases) { 
+0

приложение нагрузки, но затем он выходит из строя, точки ошибки в моей cellForItemAtIndexPath: NSDictionary * upcomingReleaseDictionary = [self.upcomingReleases objectAtIndex: indexPath.row]; Весь мой проект находится на github просто, если вы хотите посмотреть мой весь код: https://github.com/chrisbedoya/solearchives. Спасибо за вашу помощь. – ChrisBedoya

+0

1.) git add. 2.) git push origin master :) У вас нет ничего, кроме пустого проекта. @ChrisBedoya –

+0

Теперь вы можете увидеть мое приложение в Github (отметьте «UpcomingReleasesViewController» в папке «Релизы». Извините за неудобства и еще раз спасибо. – ChrisBedoya

Смежные вопросы