Ios 使用UICollectionReusableView对单元格进行分组
我很难将进行同步JSOn调用的旧代码更新为使用AFNetworking进行异步调用的新代码 在我以前的代码中,我使用日期字符串(“release_date”)使用UICollectionReusableView对单元格进行分组,所有这些都是在viewDidLoad中完成的。现在有了AFNetworking,我将所有内容都从viewDidLoad中移出,所以我一直在尝试如何将旧代码与新代码合并 这是我必须使用AFNetworking解析JSON的新代码: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 {
- (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请参见编辑。通过打开异常断点,您可能会更容易地发现这个问题。请参见此问题:现在我有了可重用视图,正确显示了正确的日期和正确的单元格数量。但由于某些原因,单元格会继续返回每次有新的可重用视图时,都会显示第一个单元格。如果一个视图中有两个单元格,我的应用程序将显示前两个单元格(发布日期最早的单元格)。在下一个可重用视图中,不再显示属于该日期的单元格,而是再次显示日期最早的单元格。