页面视图控制器 - 从图像到另一个视图控制器

Posted

技术标签:

【中文标题】页面视图控制器 - 从图像到另一个视图控制器【英文标题】:Page View Controller - from images to another view controller 【发布时间】:2012-10-29 00:17:22 【问题描述】:

我对自己要完成的工作感到有些困惑。我有一个页面视图控制器,它有一个包含图像数组列表的数据源。它实际上是一个用户可以翻阅的教程。我想要做的是让最后一页成为登录屏幕,这样用户就可以输入信息并点击登录按钮。我认为这就像在数组中添加一个登录视图控制器一样简单,但是我错了 D:当我尝试时,我得到了这个错误:

* 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[UIViewController _isResizable]:无法识别的选择器发送到实例 0xa160660”

我为自己是个菜鸟而道歉,我对所有这些都是新手,只是想弄清楚它。这是我的代码(实际使用本网站完成):

我的数据源(ModelController.h)

#import <Foundation/Foundation.h>
@class DataViewController;
@interface ModelController : NSObject <UIPageViewControllerDataSource>
- (DataViewController *)viewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard   *)storyboard;
- (NSUInteger)indexOfViewController:(DataViewController *)viewController;`
@end

模型控制器.m

#import "ModelController.h"
#import "DataViewController.h"
#import "LoginViewController.h"

@interface ModelController()
@property (readonly, strong, nonatomic) NSArray *pageData;
@end


@implementation ModelController

- (id)init

self = [super init];
if (self)


    // Create the data model
    _pageData = [[NSArray alloc] initWithObjects:

                    [UIImage imageNamed:@"tutorial1.png"],
                    [UIImage imageNamed:@"tutorial2.png"],
                    [UIImage imageNamed:@"lastWishes.png"],
                    [UIImage imageNamed:@"todo.png"],
                    [UIImage imageNamed:@"web.png"],
                 (LoginViewController*)[[UIViewController alloc] init],

                     nil];

return self;


- (DataViewController *)viewControllerAtIndex:(NSUInteger)index storyboard:(UIStoryboard *)storyboard

// Return the data view controller for the given index.
if (([self.pageData count] == 0) || (index >= [self.pageData count]))

    return nil;


// Create a new view controller and pass suitable data.
DataViewController *dataViewController = [storyboard      instantiateViewControllerWithIdentifier:@"DataViewController"];
dataViewController.dataObject = self.pageData[index];
return dataViewController;


- (NSUInteger)indexOfViewController:(DataViewController *)viewController

// 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.pageData indexOfObject:viewController.dataObject];


#pragma mark - Page View Controller Data Source

- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController     viewControllerBeforeViewController:(UIViewController *)viewController

NSUInteger index = [self indexOfViewController:(DataViewController *)viewController];
if ((index == 0) || (index == NSNotFound)) 
    return nil;


index--;
return [self viewControllerAtIndex:index storyboard:viewController.storyboard];


- (UIViewController *)pageViewController:(UIPageViewController *)pageViewController     viewControllerAfterViewController:(UIViewController *)viewController

NSUInteger index = [self indexOfViewController:(DataViewController *)viewController];
if (index == NSNotFound) 
    return nil;


index++;
if (index == [self.pageData count]) 
    return nil;

return [self viewControllerAtIndex:index storyboard:viewController.storyboard];



@end

父级 (RootViewController.h)

#import <UIKit/UIKit.h>

@interface RootViewController : UIViewController <UIPageViewControllerDelegate>

@property (strong, nonatomic) UIPageViewController *pageViewController;

@end

RootViewController.m

#import "RootViewController.h"

#import "ModelController.h"

#import "DataViewController.h"

@interface RootViewController ()
@property (readonly, strong, nonatomic) ModelController *modelController;
@end

@implementation RootViewController

@synthesize modelController = _modelController;

- (void)viewDidLoad

[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Configure the page view controller and add it as a child view controller.
self.pageViewController = [[UIPageViewController alloc]   initWithTransitionStyle:UIPageViewControllerTransitionStylePageCurl  navigationOrientation:UIPageViewControllerNavigationOrientationVertical options:nil];
self.pageViewController.delegate = self;

DataViewController *startingViewController = [self.modelController viewControllerAtIndex:0 storyboard:self.storyboard];
NSArray *viewControllers = @[startingViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:NO completion:NULL];

self.pageViewController.dataSource = self.modelController;

[self addChildViewController:self.pageViewController];
[self.view addSubview:self.pageViewController.view];

// Set the page view controller's bounds using an inset rect so that self's view is visible around the edges of the pages.
CGRect pageViewRect = self.view.bounds;
self.pageViewController.view.frame = pageViewRect;

[self.pageViewController didMoveToParentViewController:self];

// Add the page view controller's gesture recognizers to the book view controller's view so that the gestures are started more easily.
self.view.gestureRecognizers = self.pageViewController.gestureRecognizers;


- (void)didReceiveMemoryWarning

[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.


- (ModelController *)modelController

// Return the model controller object, creating it if necessary.
// In more complex implementations, the model controller may be passed to the view controller.
if (!_modelController) 
    _modelController = [[ModelController alloc] init];

return _modelController;


#pragma mark - UIPageViewController delegate methods

/*
- (void)pageViewController:(UIPageViewController *)pageViewController didFinishAnimating:    (BOOL)finished previousViewControllers:(NSArray *)previousViewControllers transitionCompleted:  (BOOL)completed



*/

- (UIPageViewControllerSpineLocation)pageViewController:(UIPageViewController *)pageViewController spineLocationForInterfaceOrientation:(UIInterfaceOrientation)orientation

// Set the spine position to "min" and the page view controller's view controllers array to contain just one view controller. Setting the spine position to 'UIPageViewControllerSpineLocationMid' in landscape orientation sets the doubleSided property to YES, so set it to NO here.
UIViewController *currentViewController = self.pageViewController.viewControllers[0];
NSArray *viewControllers = @[currentViewController];
[self.pageViewController setViewControllers:viewControllers direction:UIPageViewControllerNavigationDirectionForward animated:YES completion:NULL];

self.pageViewController.doubleSided = NO;
return UIPageViewControllerSpineLocationMin;



@end

孩子 (DataViewController.h)

#import <UIKit/UIKit.h>

@interface DataViewController : UIViewController
@property (strong, nonatomic) id dataObject;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@end

DataViewController.m

#import "DataViewController.h"

@interface DataViewController ()

@end

@implementation DataViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil

self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) 
    // Custom initialization

return self;


- (void)viewDidLoad

[super viewDidLoad];
// Do any additional setup after loading the view.


- (void)didReceiveMemoryWarning

[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.


- (void) viewWillAppear:(BOOL)animated

[super viewWillAppear:animated];
self.imageView.image = _dataObject;


@end

再一次,有问题的代码在这里我试图将视图控制器添加到数据源作为最后一页:

_pageData = [[NSArray alloc] initWithObjects:

                [UIImage imageNamed:@"tutorial1.png"],
                [UIImage imageNamed:@"tutorial2.png"],
                [UIImage imageNamed:@"lastWishes.png"],
                [UIImage imageNamed:@"todo.png"],
                [UIImage imageNamed:@"web.png"],
             (LoginViewController*)[[UIViewController alloc] init],

                 nil];

在运行时出现无法识别的选择器错误。我也试过这个:

- (id)init

self = [super init];
if (self)

    LoginViewController *viewController = [self.storyboard instantiateViewControllerWithIdentifier:@"LoginViewController"];
    // Create the data model
    _pageData = [[NSArray alloc] initWithObjects:

                    [UIImage imageNamed:@"tutorial1.png"],
                    [UIImage imageNamed:@"tutorial2.png"],
                    [UIImage imageNamed:@"lastWishes.png"],
                    [UIImage imageNamed:@"todo.png"],
                    [UIImage imageNamed:@"web.png"],
                     viewController,

                     nil];

return self;

任何建议都会很棒。谢谢!!

【问题讨论】:

【参考方案1】:

您的想法是 100% 正确的,但您的实施却不是。

这一行:

dataViewController.dataObject = self.pageData[index];

非常可疑,因为在您的登录屏幕的情况下,这将返回一个 UIViewController。我建议您 type-check 您的页面数据,如果它已经是 UIViewController 子类,只需返回它,如果它(在您的情况下)是 UIImage,请将其添加为数据对象。

【讨论】:

嘿,保罗。非常感谢您回复我的帖子。关于您的建议,您能否使用一些示例代码进行更新?我只是想知道类型检查是否应该在您所指的方法中进行,或者是否应该在我创建页面数据之前进行。请原谅我的无知哈哈

以上是关于页面视图控制器 - 从图像到另一个视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

快速将图像从一个视图控制器传递到另一个视图控制器

在 Swift 中将图像视图从一个视图控制器转移到另一个视图控制器

将 ImageData 从一个视图控制器传递到另一个视图控制器

将图像从集合视图控制器快速传递到另一个视图控制器

当数据从一个视图控制器传递到另一个视图控制器时,我如何能够传递图像?

将变量从页面视图控制器传递到另一个