如何使用UICollectionReusableView对单元进行分组(使用JSON) [英] How To Group Cells With UICollectionReusableView (Using JSON)

查看:96
本文介绍了如何使用UICollectionReusableView对单元进行分组(使用JSON)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Rails应用程序中的JSON填充我的应用程序( http://obscure-lake-7450.herokuapp.com/upcoming.json ).我的Rails应用程序中的每个帖子都有一个发布日期",并且按照发布日期进行分组(基本上每周都会发布某些运动鞋).我希望能够在我的应用程序中执行相同的操作,但是我很难做到这一点.

I'm populating my app with JSON off of a Rails app (http://obscure-lake-7450.herokuapp.com/upcoming.json). Every post in my Rails app has a "release date", and they're grouped by the release date (basically every week there's certain sneakers that release). I want to be able to do the same thing in my app but I'm having difficulty doing that.

在情节提要上,我有一个具有UICollectionReusableView类的集合可重用视图和一个名为"releasesGroup"的标识符,还有一个连接到UICollectionReusableView的标签称为"releasesHeader".

On my Storyboard I have a Collection Reusable View with a UICollectionReusableView class and an identifier called "releasesGroup", I also have a label that connects to the UICollectionReusableView called "releasesHeader".

我还想在标题中显示相应的日期,如下所示:

I also want to show the corresponding date in the header, something like this:

视图控制器

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSURL *upcomingReleaseURL = [NSURL URLWithString:@"http://obscure-lake-7450.herokuapp.com/upcoming.json"];

    NSData *jsonData = [NSData dataWithContentsOfURL:upcomingReleaseURL];

    NSError *error = nil;

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

    self.upcomingReleases = [NSMutableArray array];

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

    for (NSDictionary *upcomingReleaseDictionary in upcomingReleasesArray) {
        UpcomingRelease *upcomingRelease = [UpcomingRelease upcomingReleaseWithName:[upcomingReleaseDictionary objectForKey:@"release_name"]];
        upcomingRelease.release_date = [upcomingReleaseDictionary objectForKey:@"release_date"];
        [self.upcomingReleases addObject:upcomingRelease];
    }

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

- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
    return 1;
}

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

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

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

    UpcomingRelease *upcomingRelease = [self.upcomingReleases objectAtIndex:indexPath.row];

    cell.release_name.text = upcomingRelease.release_name;

    return cell;
}

我的UICollectionReusableView

@interface ReleasesGroup : UICollectionReusableView
@property (weak, nonatomic) IBOutlet UILabel *releasesHeader;
@end


@implementation ReleasesGroup
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
    }
    return self;
}
@end

谢谢.

我的Segue

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"showRelease"])
    {
        NSIndexPath *selectedIndexPath = [[self.collectionView indexPathsForSelectedItems] objectAtIndex:0];
        ReleaseViewController *releaseViewController = [segue destinationViewController];
        releaseViewController.singleRelease = self.upcomingReleases[selectedIndexPath.row];
    }
}

ReleaseViewController.h

#import <UIKit/UIKit.h>
#import "UpcomingRelease.h"

@interface ReleaseViewController : UIViewController

@property (strong, nonatomic) UpcomingRelease *singleRelease;
@property (weak, nonatomic) IBOutlet UILabel *release_name;
@property (weak, nonatomic) IBOutlet UILabel *release_price;
@property (weak, nonatomic) IBOutlet UILabel *release_colorway;
@property (weak, nonatomic) IBOutlet UILabel *release_date;
@property (weak, nonatomic) IBOutlet UIImageView *thumb;

@end

ReleaseViewController.m

#import "ReleaseViewController.h"

@interface ReleaseViewController ()

@end

@implementation ReleaseViewController

@synthesize singleRelease = _singleRelease;
@synthesize release_name = _release_name;
@synthesize release_price = _release_price;
@synthesize release_colorway = _release_colorway;
@synthesize release_date = _release_date;
@synthesize thumb = _thumb;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSString *thumbURL = nil;

    if ([_singleRelease.images isKindOfClass:[NSArray class]] && [_singleRelease.images count])
        thumbURL = [[[[[_singleRelease.images objectAtIndex:0] objectForKey:@"image_file"] objectForKey:@"image_file"] objectForKey:@"medium"] objectForKey:@"url"];

    if (thumbURL)
    {
        NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:thumbURL]];
        UIImage *image = [UIImage imageWithData:imageData];
        self.thumb.image = image;
    }
    else {
        self.thumb.image = [UIImage imageNamed:@"cover.png"];
    }

    self.release_name.text = self.singleRelease.release_name;
    self.release_price.text = [NSString stringWithFormat:@"$%@", _singleRelease.release_price];
    self.release_colorway.text = self.singleRelease.release_colorway;
    self.release_date.text = [NSString stringWithFormat:@"%@", _singleRelease.formattedDate];
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

推荐答案

好吧,看来您缺少了很多东西.首先,要按天分组发布,您将需要某种日期操纵,在您的viewDidLoad方法中,您将需要将json数据分组为与发布日期相对应的存储桶".一旦有了这个,剩下的就是小菜一碟了.因此,就可以了:

Ok, it would appear that you are missing quite a few things. First off: to group the releases by day, you will need some kind of date manipulation, in your viewDidLoad method, you will need to already group the json data into "buckets" corresponding to the release date. Once you have this, the rest is a piece of cake. So onto it:

首先,您将在视图控制器中需要一个包含所有数据的属性.像这样:

First off, you'll need a property in your view controller that contains all of the data. Something like:

@property (strong, nonatomic) NSDictionary *upReleases;
@property (strong, nonatomic) NSArray *releaseBuckets;

然后,在您的viewDidLoad方法中,您需要填充此词典:

Then, in your viewDidLoad method, you'll need to populate this dictionary:

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSURL *upcomingReleaseURL = [NSURL URLWithString:@"http://obscure-lake-7450.herokuapp.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.SSSv"];
    NSTimeZone *gmt = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
    [dateFormatter setTimeZone:gmt];
    [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_GB"]]; //A bit of an overkill to avoid bugs on different locales

        //Temp array where we'll store the unsorted bucket dates
    NSMutableArray *buckets = [[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];
            [buckets addObject:bucket];
        }

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

    [buckets 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.upReleases = [NSDictionary dictionaryWithDictionary:tmpDict];
    self.releaseBuckets = [NSArray arrayWithArray:buckets];

}

接下来,您需要具有与发布存储区一样多的部分.小菜一碟:

Next, you need to have as many sections as the release buckets. Piece of cake:

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

每个存储桶中的单元格数量与该日期发布的产品数量相同:

And as many cells for each bucket as the products being released in that date:

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

然后,您需要为每个部分设置标题(同样,需要一些日期操作才能使标题部分具有正确的格式):

Then, you'll need to set up the header for each section (again, a little bit of date manipulation is necessary to have the right format for your header section):

-(UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
{
    ReleasesGroup* releaseGroup = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader withReuseIdentifier:@"releasesGroup" 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 *gmt = [NSTimeZone timeZoneWithAbbreviation:@"GMT"];
    [dateFormatter setTimeZone:gmt];
    [dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_GB"]];

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

    releaseGroup.releasesHeader.text = [[dateFormatter stringFromDate:bucketDate] uppercaseString];
    return releaseGroup;
}

最后,您需要设置单个单元格:

Lastly, you'll need to setup the single cells:

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

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

    UpcomingRelease *upcomingRelease = [self.upReleases objectForKey:self.releaseBuckets[indexPath.section]][indexPath.row];

    cell.release_name.text = upcomingRelease.release_name;

    return cell;
}

整个代码已经过测试并可以正常工作.

This whole code has been tested and works.

已编辑,以包含键的排序数组

EDITED to include a sorted array for the keys

这篇关于如何使用UICollectionReusableView对单元进行分组(使用JSON)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆