Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/97.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 使用UICollectionReusableView对单元格进行分组_Ios_Objective C_Json_Afnetworking_Uicollectionviewcell - Fatal编程技术网

Ios 使用UICollectionReusableView对单元格进行分组

Ios 使用UICollectionReusableView对单元格进行分组,ios,objective-c,json,afnetworking,uicollectionviewcell,Ios,Objective C,Json,Afnetworking,Uicollectionviewcell,我很难将进行同步JSOn调用的旧代码更新为使用AFNetworking进行异步调用的新代码 在我以前的代码中,我使用日期字符串(“release_date”)使用UICollectionReusableView对单元格进行分组,所有这些都是在viewDidLoad中完成的。现在有了AFNetworking,我将所有内容都从viewDidLoad中移出,所以我一直在尝试如何将旧代码与新代码合并 这是我必须使用AFNetworking解析JSON的新代码: - (void)viewDidLoad {

我很难将进行同步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吧。将您的模型(来自网络的内容)分离到一个单独的类中,该类执行网络操作,并将内容分组到数组和字典中。视图控制器应该只观察模型。您可以使用委派或(我最喜欢的)KVO来了解模型何时更新了可用数据。然后您只需更新集合视图。视图控制器应该只是模型和视图之间的接口。如果你用这种方式把事情分开,你会发现这更自然,而且你也不会反对这个系统。

你比你想象的更接近

只需将您过去在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];
编辑:在您的代码中,您不再为即将发布的版本分配任何内容(注释代码行块91-102),并且您正在引用数组中不存在的索引。解决方法很简单:

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

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

应用程序加载后崩溃,错误指向my cellForItemAtIndexPath:NSDictionary*upcomingReleaseDictionary=[self.UpComingReleaseObjectAtIndex:indexPath.row];我的整个项目都在github上,以防您想查看我的整个代码:。谢谢你的帮助。2.)git-push-origin-master:)除了一个空项目之外,您没有任何东西@Chrisbedoya现在你可以在Github上看到我的应用程序(在“发布”下选中“UpcomingReleasesViewController”文件夹。很抱歉给您带来不便,再次感谢。@ChrisBedoya请参见编辑。通过打开异常断点,您可能会更容易地发现这个问题。请参见此问题:现在我有了可重用视图,正确显示了正确的日期和正确的单元格数量。但由于某些原因,单元格会继续返回每次有新的可重用视图时,都会显示第一个单元格。如果一个视图中有两个单元格,我的应用程序将显示前两个单元格(发布日期最早的单元格)。在下一个可重用视图中,不再显示属于该日期的单元格,而是再次显示日期最早的单元格。