好的,这有三个部分。
首先是UICollectionViewController
显示照片库的子类 ( UIImage
)。其次是UIPageViewController
管理每个人左右滑动的子类PhotoViewController
。第三是显示单张照片的UIViewController
子类 ( )。PhotoViewController
故事板看起来像这样......
左边是一个UICollectionViewController
this,中间有一个segue UIPageViewController
。右边是在属性窗格UIViewController
中有一个Identifier
集合的 a(注意,这没有 segue)。
PhotoViewController
...的标识符
在PhotoPageViewController
我有一个自定义对象...
在属性窗格中设置了 Class 类型PhotoPageModelController
...这是作为PhotoPageViewController
.
这几乎就是所有需要的故事板设置。
因此,首先要设置的是PhotoPageModelController
. 这是这样的数据源,PhotoPageViewController
它将分配子类UIViewController
以便PhotoPageViewController
可以显示它们。
模型控制器
PhotoPageModelController.h
@class PhotoViewController;
@interface PhotoPageModelController : NSObject <UIPageViewControllerDataSource>
// this is the array of the photos. Either an array of UIImages or objects containing
// them or something. My personal project had an array of photoIDs that I could use to
// pull the photos out of Core Data.
// In this example the array will contain instances of UIImage.
@property (nonatomic, strong) NSArray *photos;
- (PhotoViewController *)viewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard *)storyboard;
- (NSUInteger)indexOfViewController:(PhotoViewController *)controller;
@end
PhotoPageModelController.m
#import "PhotoPageModelController.h"
#import "PhotoViewController.h"
@implementation PhotoPageModelController
- (UIImage *)photoAtIndex:(NSUInteger)index
{
// check that the index is in bounds and then return the UIImage to display.
// In my project I just returned the ID of the photo and let the photo
// controller load the actual image from core data. (See below)
if ([self.photos count] == 0
|| index >= [self.photos count]) {
return nil;
}
return self.photos[index];
}
#pragma mark - convenience methods
- (PhotoViewController *)viewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard *)storyboard
{
UIImage *photo = [self photoAtIndex:index];
if (photo == nil) {
return nil;
}
// This is why we don't have a segue. We are loading it manually
// from the storyboard using the identifier.
EventPhotoViewController *controller = [storyboard instantiateViewControllerWithIdentifier:@"PhotoViewController"];
// The model controller is where the PhotoViewController gets the actual image from.
// Or an object containing the image with a name, date, details, etc...
// The controller doesn't know anything about the other photos. Only the one it's displaying.
controller.photo = photo;
return controller;
}
- (NSUInteger)indexOfViewController:(PhotoViewController *)controller
{
// Return the index of the given data view controller.
// For simplicity, this implementation uses a static array of model objects and the view controller stores the model object; you can therefore use the model object to identify the index.
return [self.photos indexOfObject:controller.photo];
}
#pragma mark - page view data source
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerBeforeViewController:(UIViewController *)viewController
{
// We need to find the index of the current controller so we can get the index
// and then the view controller for the one before it.
NSUInteger index = [self indexOfViewController:(PhotoViewController *) viewController];
if ((index == 0) || (index == NSNotFound)) {
// We have reached the beginning of the photos array so return nil.
// This tells the Page View Controller that there isn't another page.
return nil;
}
index--;
return [self viewControllerAtIndex:index storyboard:viewController.storyboard];
}
// This is the same as above but going forward instead of backward.
- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController viewControllerAfterViewController:(UIViewController *)viewController
{
NSUInteger index = [self indexOfViewController:(EventPhotoViewController *) viewController];
if (index == NSNotFound) {
return nil;
}
index++;
if (index == [self.photoIDs count]) {
return nil;
}
return [self viewControllerAtIndex:index storyboard:viewController.storyboard];
}
@end
好的。这就是照片页面模型控制器。
页面视图控制器
接下来为PhotoPageViewController
.
PhotoPageViewController.h
#import <Foundation/Foundation.h>
@interface PhotoPageViewController : UIPageViewController
@property (nonatomic, strong) NSArray *photos;
@property (nonatomic) NSUInteger initialIndex;
@end
PhotoPageViewController.m
#import "PhotoPageViewController.h"
#import "PhotoPageModelController.h"
@interface PhotoPageViewController ()
// this property is connected in the storyboard
@property (nonatomic, weak) IBOutlet PhotoPageModelController *modelController;
@end
@implementation PhotoPageViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.modelController.photos = self.photos;
// We use the initialIndex property to get the first controller and display it.
UIViewController *initialController = (UIViewController *)[self.modelController viewControllerAtIndex:self.initialIndex storyboard:self.storyboard];
[self setViewControllers:@[initialController]
direction:UIPageViewControllerNavigationDirectionForward
animated:NO
completion:^(BOOL finished) {
}];
// That's it. Because we have the datasource class it makes this class really easy and short.
// It doesn't even need to know anything about the view controllers it is displaying.
// It's just a dispensing machine.
}
@end
照片视图控制器
接下来是显示实际照片的视图控制器。
它只需要一个类型UIImage
为 called的属性,photo
然后UIImageView
将其放入其中。我将把它留给您,因为您可以通过多种不同的方式进行操作。
我已经在我的中放了一个可缩放UIScrollView
的,以便用户可以捏缩放照片。我还有一些额外的信息,例如拍摄照片的人的姓名和拍摄日期等...根据您的喜好进行设置。
集合视图 segue
最后一部分(最后)是从集合视图到页面视图控制器。
这是在prepareForSegue
.
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
if ([segue.identifier isEqualToString:@"PhotoSegue"]) {
PhotoPageViewController *controller = segue.destinationViewController;
NSIndexPath *selectedIndex = [self.collectionView indexPathsForSelectedItems][0];
// The PageViewController doesn't need anything except the index to start on...
// i.e. the index of the photo that the user just selected.
controller.initialIndex = (NSUInteger)selectedIndex.item;
// ...and the array of photos it will be displaying.
controller.photos = self.photos;
// Everything else is done by the PageViewController.
}
}