Правильный способ перехода между представлением коллекции и представлением с разбивкой по страницам

В настоящее время у меня есть вид uicollection, который отображает конкретный альбом на фотографиях пользователей (библиотека ALAssets).

В моем mainView.m я собираю фотографии:

+ (ALAssetsLibrary *)defaultAssetsLibrary {
    static dispatch_once_t pred = 0;
    static ALAssetsLibrary *library = nil;
    dispatch_once(&pred, ^{
        library = [[ALAssetsLibrary alloc] init];
    });
    return library;
}


- (void)beginLoadingPhotoInfo {

...

[library enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos
                               usingBlock:assetGroupEnumerator
                             failureBlock:^(NSError *error) {NSLog(@"Probs");}
         ];
}

Загрузите их (уменьшенная версия) все в представление коллекции, и все это работает хорошо.

Затем, когда пользователь выбирает фотографию, я вызываю этот метод prepareToSegue: (все еще в mainView.m)

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    if([[segue identifier] isEqualToString:@"showDetail"])
    {
        NSIndexPath *indexPath = [[self.collectionView indexPathsForSelectedItems] lastObject];
        DetailViewController *detailviewcontroller = [segue destinationViewController];
        detailviewcontroller.photoArrayIndex = indexPath.row;

        //photos array
        detailviewcontroller.photosArray = _photoListArray;





}

В настоящее время я отправляю массив с информацией о фотографиях и пытаюсь прокрутить до позиции в массиве.

Я нашел этот ресурс здесь для горизонтальной подкачки:

http://adoptioncurve.net/archives/2013/04/creating-a-paged-photo-gallery-with-a-uicollectionview/

Что позволяет для подкачки с использованием представления коллекции. Я написал, что класс detailViewController.


Вот вопрос. Как мне соединить два?

Идея 1. Пусть мой mainView отправит целое число, представляющее выбранную фотографию, а затем detailViewController загрузит ее и начнет лениво загружать фотографии.

Идея 2: Каким-то образом предварительно загрузить некоторые полноэкранные фотографии, а затем отправить целое число с местом в массиве.

Идея 3: Отправить и число, и мой объект массива в detailViewController, чтобы мне больше не приходилось перечислять библиотеку ресурсов.

Являются ли какие-либо из них правильным подходом или я полностью упустил идею?


редактировать:

В моем подробном контроллере есть макет потока uicollectionview с включенной подкачкой страниц. Это метод, в котором я настроил макет:

- (void) setCollectionView {

    [self.collectionView registerClass:[DetailViewCell class] forCellWithReuseIdentifier:@"detailViewCell"];

    //Flow Layout
    UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
    [flowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
    [flowLayout setMinimumInteritemSpacing:0.0f];
    [flowLayout setMinimumLineSpacing:0.0f];
    [self.collectionView setPagingEnabled:YES];
    [self.collectionView setCollectionViewLayout:flowLayout];


    CGFloat pageWidth = self.collectionView.frame.size.width;
    NSInteger num = _photosArrayIndex + 1;
    CGPoint scrollTo = CGPointMake(pageWidth * num, 0);
    NSLog(@"scroll to: %@", NSStringFromCGPoint(scrollTo));
    [self.collectionView setContentOffset:scrollTo];


}

Что он должен сделать, это взять значение из моего основного вида и перейти к этому изображению. К сожалению это не так. Я не уверен, почему, а также я чувствую, что есть лучший способ сделать это. Это просто похоже на хакиш.

Как мне лучше соединить два более качественных контроллера и как правильно загрузить фотографии / как мне добраться до фотографии (в полноразмерном подробном виде), на которой я работал, когда они были в макете сетки.

Помощь приветствуется.

1 ответ

Решение

ОК, здесь есть три части.

Во-первых UICollectionViewController подкласс для отображения галереи фотографий (UIImage). Второе UIPageViewController подкласс, чтобы управлять смахиванием из стороны в сторону каждого человека PhotoViewController, В-третьих, это UIViewController подкласс (PhotoViewController), чтобы отобразить одну фотографию.

Раскадровка будет выглядеть примерно так...

Слева находится UICollectionViewController это имеет отношение к UIPageViewController в середине. Справа находится UIViewController это имеет Identifier установить в панели свойств (обратите внимание, нет никакого перехода к этому).

Идентификатор для PhotoViewController...

в PhotoPageViewController У меня есть пользовательский объект...

С типом класса 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 называется photo а затем UIImageView поместить это в. Я оставлю это на ваше усмотрение, так как вы можете сделать это разными способами.

Я поставил масштабируемый UIScrollView в моем, так что пользователь может ущипнуть масштабировать фотографию. У меня также есть некоторая дополнительная информация, такая как имя человека, который сделал фотографию, и дата, когда она была сделана и т. Д. Установите это так, как вам нравится.

Коллекция View 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.
    }
}
Другие вопросы по тегам