0

我的应用程序有一个 CollectionView (UpcomingReleasesViewController) 和一个 CollectionViewCell (ReleaseCell)。每个 Cell 都有特定的信息(release_name 和 release_price),我使用 JSON 从 Rails 应用程序中解析这些信息。

单击单元格后,应用程序会将您带到显示该信息的详细视图 (ReleaseViewController)。这是我第一次拥有的代码,它可以满足我的需求。

即将发布的ViewController.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];
    }
}

这是我的详细视图控制器(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 解析的日期时间字符串)对 Cells 进行“分组”,然后我让它工作了,但是 Segue 坏了,每当我点击一个 Cell 时,应用程序就会带我到空白页面(由于某种原因,release_name 标签为空白,而 release_price 标签返回“nill”)。

即将到来的ReleasesViewController.h

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

即将发布的ViewController.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 再次正常工作?

谢谢。

4

1 回答 1

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 的行无法获得正确的对象。就像 in 一样cellForItemAtIndexPath,从你的字典中获取它:

releaseViewController.singleRelease = [self.upReleases objectForKey:self.releaseBuckets[selectedIndexPath.section]][selectedIndexPath.row];
于 2013-10-05T22:36:48.260 回答