我的应用程序有一个CollectionView(UpcomingReleasesViewController)和一个CollectionViewCell(ReleaseCell)。每个Cell都有一些信息(release_name和release_price),我正在使用JSON从Rails应用程序解析。
点击一个Cell后,该应用会将您带到显示该信息的详细视图(ReleaseViewController)。这是我第一次做了我想要的代码。
UpcomingReleasesViewController.m
@interface UpcomingReleasesViewController ()
@property (nonatomic, strong) NSMutableArray *upcomingReleases;
@end
@implementation UpcomingReleasesViewController
- (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_price = [upcomingReleaseDictionary objectForKey:@"release_price"];
upcomingRelease.release_date = [upcomingReleaseDictionary objectForKey:@"release_date"];
[self.upcomingReleases addObject:upcomingRelease];
}
[self.collectionView registerClass:[ReleaseCell class] forCellWithReuseIdentifier:@"ReleaseCell"];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = @"Cell";
ReleaseCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
UpcomingRelease *upcomingRelease = [self.upcomingReleases objectAtIndex:indexPath.row];
cell.release_name.text = upcomingRelease.release_name;
cell.release_price.text = [NSString stringWithFormat:@"$%@", upcomingRelease.release_price];
return cell;
}
- (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];
}
}
这是我的detailViewController(ReleaseViewController)
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_date;
@end
ReleaseViewController.h
#import "ReleaseViewController.h"
@interface ReleaseViewController ()
@end
@implementation ReleaseViewController
@synthesize singleRelease = _singleRelease;
@synthesize release_name = _release_name;
@synthesize release_price = _release_price;
@synthesize release_date = _release_date;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.release_name.text = self.singleRelease.release_name;
self.release_price.text = [NSString stringWithFormat:@"$%@", _singleRelease.release_price];
self.release_date.text = [NSString stringWithFormat:@"%@", _singleRelease.formattedDate];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
现在我试图按照发布日期(通过JSON解析日期时间字符串)对单元格进行“分组”,然后我就让它工作了,但是当我点击一个Cell时,Segue就被打破了应用程序将我带到一个空白页面(由于某种原因,release_name标签为空白,release_price标签返回“nill”)。
UpcomingReleasesViewController.h
@property (strong, nonatomic) NSDictionary *upReleases;
@property (strong, nonatomic) NSArray *releaseBuckets;
UpcomingReleasesViewController.m
- (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_price = [upcomingReleaseDictionary objectForKey:@"release_price"];
[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];
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return [self.releaseBuckets count];
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [[self.upReleases objectForKey:self.releaseBuckets[section]] count];
}
-(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;
}
- (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;
}
#pragma mark - Open Release Page
- (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];
}
}
我需要更改什么才能使Segue再次正常工作?
感谢。
答案 0 :(得分:0)
如果这是您的实际代码,那么您的问题在于prepareForSegue::
方法。就我所见,这仍然是你的“旧”实施:
- (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];
}
}
只能使用indexPath的行来获取正确的对象。就像在cellForItemAtIndexPath
中一样,从你的字典中获取它:
releaseViewController.singleRelease = [self.upReleases objectForKey:self.releaseBuckets[selectedIndexPath.section]][selectedIndexPath.row];