objective-c - 在 Collection View 和分页详细 View 之间转换的正确方法

标签 objective-c alassetslibrary

目前我有一个 uicollection View ,它显示用户照片中的特定相册(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");}
         ];
}

将它们(缩略图版本)全部加载到 Collection View 中,一切正常。

然后当用户选择一张照片时,我调用这个 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/

允许使用 Collection View 进行分页。我写了一个 detailViewController 类。


问题来了。我应该如何将两者联系起来?

想法 1:让我的 mainView 发送一个表示所选照片的​​整数,然后 detailViewController 将加载该照片并开始延迟加载照片。

想法 2:以某种方式预加载一些全屏照片,然后将整数与数组中的点一起发送。

想法 3:将数字和我的数组对象都发送到 detailViewController,这样我就不必再次枚举 Assets 库。

这些是正确的方法还是我完全错过了这个想法?


编辑:

我的细节 Controller 中有一个启用了分页的 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];


}

它应该做的是从我的主视图中获取值并移动到该图像。不幸的是它没有。我不确定为什么,而且我觉得有更好的方法可以做到这一点。这似乎有点骇人听闻。

我如何更好地连接两个更好的 Controller 以及加载照片的正确方法是什么/我如何获得照片(在全尺寸细节 View 中)我在网格布局中时的照片。

感谢您的帮助。

最佳答案

好的,这分为三个部分。

首先是 UICollectionViewController 子类,用于显示照片库 (UIImage)。 其次是 UIPageViewController 子类,用于管理每个 PhotoViewController 的左右滑动。 第三个是显示单张照片的 UIViewController 子类 (PhotoViewController)。

Storyboard看起来像这样......

enter image description here

左边是一个 UICollectionViewController,它与中间的 UIPageViewController 有一个 segue。右侧是一个 UIViewController,它在属性 Pane 中设置了一个 Identifier(请注意,这里没有继续)。

PhotoViewController 的标识符...

enter image description here

PhotoPageViewController 中,我有一个自定义对象...

enter image description here

在属性 Pane 中设置了类类型 PhotoPageModelController...这作为 PhotoPageViewController 的数据源连接。

enter image description here

这几乎就是所有需要的 Storyboard设置。

因此,首先要设置的是 PhotoPageModelController。这是 PhotoPageViewController 的数据源,因此将分发 UIViewController 的子类,以便 PhotoPageViewController 可以显示它们。

模型 Controller

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

好的。这就是照片页面模型 Controller 。

页面 View Controller

接下来是 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

照片 View Controller

接下来是将显示实际照片的 View Controller 。

它所需要的只是一个名为 photoUIImage 类型的属性,然后是一个 UIImageView 来放置它。我将保留它给你,因为你可以用很多不同的方式做到这一点。

我在我的中放了一个可缩放的 UIScrollView,这样用户就可以捏缩放照片。我还有一些额外的信息,例如拍摄照片的人的姓名和拍摄日期等...随心所欲地进行设置。

Collection View 转场

最后一部分(最后)是从 Collection View 到页面 View Controller 。

这是在 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.
    }
}

关于objective-c - 在 Collection View 和分页详细 View 之间转换的正确方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18084002/

相关文章:

ios - ALAsset "real"文件名

ios - ALAssetsLibrary 获取所有视频

ios - 获取新创建 Assets 的 URL,iOS 9 风格

ios - 本 map 库中的 tableView 中的照片使用过多 RAM

ios - ALAssetsGroup,如何检查是否存在?

ios - 将自定义文本添加到 iPhone sdk 中的 uibutton

iphone - 更改 ios 应用程序的语言

iphone - HTTP 通信的架构方法和 iOS 中返回的 JSON 的解析

ios - Apple 二进制文件被拒绝 (2.16)

objective-c - 如何更新 splitViewController 中的详细 View ?