ios - 使用 UICollectionReusableView 对单元格进行分组

标签 ios objective-c json afnetworking uicollectionviewcell

我在将进行同步 JSOn 调用的旧代码更新为使用 AFNetworking 进行异步调用的新代码时遇到了问题。

在我的旧代码中,我使用日期字符串(“release_date”)将单元格与 UICollectionReusableView 分组,所有这些都是在 viewDidLoad 中完成的。现在,使用 AFNetworking,我将所有内容都从 viewDidLoad 中移出,所以我一直在努力弄清楚如何将我的旧代码与我的新代码合并。

这是我必须使用 AFNetworking 解析我的 JSON 的新代码:

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

在我开始使用 AFNetworking 进行 JSON 调用和“分组”我的单元格之前,我在 viewDidLoad 中的代码:

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

我基本上是想弄清楚如何将对我的单元格进行分组的代码作为日期字符串并将其与我的新代码集成。

谢谢。

最佳答案

想想 MVC。将您的模型(来自网络的东西)分离到一个单独的类中,该类执行网络操作,并将事物分组到数组和字典中。您的 View Controller 应该简单地观察模型。您可以使用委托(delegate)或(我最喜欢的)KVO 来了解模型何时有可用的更新数据。然后你只需更新你的 Collection View 。您的 View Controller 应该只是模型和 View 之间的接口(interface)。如果您以这种方式将事情分开,您会发现它更自然,并且您不会与系统作斗争。

关于ios - 使用 UICollectionReusableView 对单元格进行分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20007056/

相关文章:

ios - Swift Playgrounds 中的 JavaScriptCore

ios - 尝试设置非属性列表对象

ios - 将任何对象保存到钥匙串(keychain)

objective-c - 测试目标找不到应用程序的 Objective-C 生成的接口(interface) header

ios - Collection View 中的奇怪行为

javascript - 如何从 ajax 调用中过滤 null 或未定义的值?

ios - 没有在 TableView 中重新加载正确的数据

iOS:是否可以为侧载开发应用程序推送更新?

json - ElasticSearch嵌套数组部分更新

ios - 使用 UITableView 验证动态表单的模式