这篇文章是针对斯坦福iOS7 2013-1014的公开课Assignment 6 Top Regions所进行的解答的第七部分。
4. YWhen a region is chosen, all the photos in your database that were taken in that region should be displayed (no sections are required). When a photo is then chosen, it should be displayed in the same way photos were displayed in last week’s assignment.
本节主要是完成photos的表单和显示image。
首先创建一个CoreDataTableViewController的子类,名为PhotosTVC,这是一个通用的类(以后我们会用它创建两个子类),先创建一个私有方法:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"Photo Cell"];
Photo *photo = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = photo.title;
cell.detailTextLabel.text = photo.subtitle;
return cell;
}
然后使用PhotosTVC创建一个子类名为RegionPhotosTVC,不要忘了在storyboard中把相关的nib设置一下为这个类,定义一个public 属性:
@property (nonatomic, strong) Region *region;
当region被设置时,我们设置fetchedResultsController(还记得吧,设置它之后所有的单元格dataSource就不需要你管了)。
- (void)setRegion:(Region *)region
{
_region = region;
self.title = region.name;
[self setupFetchedResultsController];
}
使用region直接可以获取managedObjectContext,同事由于先前我们使用的是region.name来划分的所以这里为了防止删除时导致的数据不对应,谓词中需要加入region.name
- (void)setupFetchedResultsController
{
NSManagedObjectContext *context = self.region.managedObjectContext;
if (context) {
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Photo"];
request.predicate = [NSPredicate predicateWithFormat:@"region = %@ OR region.name = %@", self.region, self.region.name];
request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"title"
ascending:YES
selector:@selector(localizedStandardCompare:)]];
self.fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:context
sectionNameKeyPath:nil
cacheName:nil];
} else {
self.fetchedResultsController = nil;
}
}
然后在RegionsTVC中定义segue,并设置需要传入RegionPhotosTVC的region
- (void)prepareViewController:(id)vc
forSegue:(NSString *)segueIdentifier
fromIndexPath:(NSIndexPath *)indexPath
{
Region *region = [self.fetchedResultsController objectAtIndexPath:indexPath];
if ([vc isKindOfClass:[RegionPhotosTVC class]]) {
RegionPhotosTVC *rpTVC = (RegionPhotosTVC *)vc;
rpTVC.region = region;
}
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue
sender:(id)sender
{
NSIndexPath *indexPath = nil;
if ([sender isKindOfClass:[UITableViewCell class]]) {
indexPath = [self.tableView indexPathForCell:sender];
}
[self prepareViewController:segue.destinationViewController
forSegue:segue.identifier
fromIndexPath:indexPath];
}
然后在PhotosTVC中(注意我们使用的是通用的类,不是RegionPhotosTVC),把URL传给一个ImageViewController(后面会定义),这样就可以查看图片
#import “ImageViewController.h”
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
NSIndexPath *indexPath = nil;
if ([sender isKindOfClass:[UITableViewCell class]]) {
indexPath = [self.tableView indexPathForCell:sender];
}
[self prepareViewController:segue.destinationViewController forSegue:segue.identifier fromIndexPath:indexPath];
}
- (void)prepareViewController:(id)vc forSegue:(NSString *)segueID fromIndexPath:(NSIndexPath *)indexPath
{
Photo *photo = [self.fetchedResultsController objectAtIndexPath:indexPath];
if ([vc isKindOfClass:[ImageViewController class]]) {
ImageViewController *ivc = (ImageViewController *)vc;
ivc.imageURL = [NSURL URLWithString:photo.imageURL];
ivc.title = photo.title;
}
}
新建一个UIViewController的子类名为ImageViewController(这个和课上的是一样的,我就不赘述了,只把代码贴出来,当然你也可以直接把课上的文件拖进来):
.h中
@property (nonatomic,strong)NSURL *imageURL;
.m中
@interface ImageViewController () <UIScrollViewDelegate, UISplitViewControllerDelegate>
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UIImage *image;
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *spinner;
@end
@implementation ImageViewController
- (void)setScrollView:(UIScrollView *)scrollView
{
_scrollView = scrollView;
_scrollView.minimumZoomScale = 0.2;
_scrollView.maximumZoomScale = 2.0;
_scrollView.delegate = self;
_scrollView.contentSize = self.image ? self.image.size : CGSizeZero;
}
- (UIImageView *)imageView
{
if (!_imageView) {
_imageView = [[UIImageView alloc] init];
}
return _imageView;
}
- (UIImage *)image
{
return self.imageView.image;
}
- (void)setImage:(UIImage *)image
{
self.scrollView.zoomScale = 1.0;
self.imageView.image = image;
[self.imageView sizeToFit];
self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);
self.scrollView.contentSize = self.image ? self.image.size : CGSizeZero;
[self.spinner stopAnimating];
[self setZoomScaleToFillScreen];
}
- (void)setZoomScaleToFillScreen
{
double wScale = self.scrollView.bounds.size.width / self.imageView.image.size.width;
double hScale = (self.scrollView.bounds.size.height
- self.navigationController.navigationBar.frame.size.height
- self.tabBarController.tabBar.frame.size.height
- MIN([UIApplication sharedApplication].statusBarFrame.size.height,
[UIApplication sharedApplication].statusBarFrame.size.width)
) / self.imageView.image.size.height;
if (wScale > hScale) self.scrollView.zoomScale = wScale;
else self.scrollView.zoomScale = hScale;
}
- (void)fetchImage
{
self.image = nil;
if (!self.imageURL) return;
[self.spinner startAnimating];
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]];
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:self.imageURL
completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
if (!error) {
if ([response.URL isEqual:self.imageURL]) {
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:location]];
dispatch_async(dispatch_get_main_queue(), ^{
self.image = image;
});
}
}
}];
[task resume];
}
- (void)setImageURL:(NSURL *)imageURL
{
_imageURL = imageURL;
[self fetchImage];
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.scrollView addSubview:self.imageView];
}
#pragma mark - scroll view delegate
- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
{
return self.imageView;
}
# pragma mark - split view controller delegate
- (void)awakeFromNib
{
self.splitViewController.delegate = self;
}
- (BOOL)splitViewController:(UISplitViewController *)svc
shouldHideViewController:(UIViewController *)vc
inOrientation:(UIInterfaceOrientation)orientation
{
return UIInterfaceOrientationIsPortrait(orientation);
}
- (void)splitViewController:(UISplitViewController *)svc
willHideViewController:(UIViewController *)aViewController
withBarButtonItem:(UIBarButtonItem *)barButtonItem
forPopoverController:(UIPopoverController *)pc
{
UIViewController *master = aViewController;
if ([master isKindOfClass:[UITabBarController class]]) {
master = ((UITabBarController *)master).selectedViewController;
}
if ([master isKindOfClass:[UINavigationController class]]) {
master = ((UINavigationController *)master).topViewController;
}
if (master) {
barButtonItem.title = master.title;
} else {
barButtonItem.title = @"Top Places";
}
self.navigationItem.leftBarButtonItem = barButtonItem;
}
- (void)splitViewController:(UISplitViewController *)svc
willShowViewController:(UIViewController *)aViewController
invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem
{
self.navigationItem.leftBarButtonItem = nil;
}
不要忘了在storyboard中把相关的nib设置一下为这个类。