需要帮助在故事板上推送UIScrollView / UIPageControl中的视图 [英] Need help for pushing a view in UIScrollView / UIPageControl on storyboard

查看:84
本文介绍了需要帮助在故事板上推送UIScrollView / UIPageControl中的视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在故事板上使用UIPageControl实现UIScrollView以显示多个视图。我发现的所有示例,教程或信息都使用的是xib而不是故事板。我试图改编Apple的示例代码,但我遗漏了一些东西。如您所见,它非常简单。

I'm trying to implement UIScrollView with UIPageControl on storyboard to display multiple views. All the examples, tutorials or informations I found are using xib and not storyboard. I tried to adapt Apple's sample code but I'm missing something. As you can see, it is quite simple.

但是,我在ContentController.m中遇到错误 - [NSNull view]:无法识别的选择器发送到实例0x129acd8 当我测试 if(controller.view.superview == nil) 我推送视图时(见上半部分代码后见下文) 。

However, either I get an error in ContentController.m -[NSNull view]: unrecognized selector sent to instance 0x129acd8 when I test if (controller.view.superview == nil) where I push the view (see below after the first half of code).

或者只有UIScrollView和UIPageControl正在工作,我无法在UIScrollView中推送视图:

Or only the UIScrollView and UIPageControl are working and I am not able to push the view in the UIScrollView:

我知道这是一个简单的问题,但我花了很多时间在这上面,任何帮助将不胜感激。

I know it's a simple question, however I spent many hours on this and any help will be appreciated.

我发布了完整的代码,因为它可以帮助某人解决像一种教程。如果需要,我会根据贡献更正代码。

I post the full code as it may help someone when resolved like a kind of tutorial. I will correct the code if/when needed according to contributions.

提前致谢

AppDelegate .h

// Nothing special as I don't want to manage it through application delegate
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end

AppDelegate.m

// Nothing special as I don't want to manage it through application delegate
#import "AppDelegate.h"

@implementation AppDelegate

@synthesize window = _window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    return YES;
}

- (void)applicationWillResignActive:(UIApplication *)application { }

- (void)applicationDidEnterBackground:(UIApplication *)application { }

- (void)applicationWillEnterForeground:(UIApplication *)application { }

- (void)applicationDidBecomeActive:(UIApplication *)application { }

- (void)applicationWillTerminate:(UIApplication *)application { }

@end

ContentController.h

// From Apple's PageControl sample code
#import <UIKit/UIKit.h>

@interface ContentController : UIViewController <UIScrollViewDelegate> {
    UIScrollView *scrollView;
    UIPageControl *pageControl;
    NSMutableArray *viewControllers;
    BOOL pageControlUsed;
}

@property (nonatomic, retain) IBOutlet UIScrollView *scrollView;
@property (nonatomic, retain) IBOutlet UIPageControl *pageControl;
@property (nonatomic, retain) NSMutableArray *viewControllers;

- (IBAction)changePage:(id)sender;

@end

ContentController.m

// From Apple's PageControl sample code

#import "AppDelegate.h"
#import "ContentController.h"
#import "MyViewController.h"

// Private methods
@interface ContentController (PrivateMethods)
- (void)loadScrollViewWithPage:(int)page;
- (void)scrollViewDidScroll:(UIScrollView *)sender;
@end

@implementation ContentController

@synthesize scrollView, pageControl, viewControllers;

static NSUInteger kNumberOfPages = 6;

- (void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.
    self.navigationController.navigationBar.hidden=YES;

    // view controllers are created lazily in the meantime, load the array with
    // placeholders which will be replaced on demand
    NSMutableArray *controllers = [[NSMutableArray alloc] init];
    for (unsigned i = 0; i < kNumberOfPages; i++) {
        [controllers addObject:[NSNull null]];
    }
    self.viewControllers = controllers;

    // a page is the width of the scroll view
    scrollView.pagingEnabled = YES;
    scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * kNumberOfPages, scrollView.frame.size.height);
    scrollView.showsHorizontalScrollIndicator = NO;
    scrollView.showsVerticalScrollIndicator = NO;
    scrollView.scrollsToTop = NO;
    scrollView.delegate = self;

    pageControl.numberOfPages = kNumberOfPages;
    pageControl.currentPage = 0;

    // pages are created on demand
    // load the visible page
    // load the page on either side to avoid flashes when the user starts scrolling
    [self loadScrollViewWithPage:0];
    [self loadScrollViewWithPage:1];
}

- (void)viewDidUnload {
    [super viewDidUnload];

    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
    self.pageControl=nil;
    self.pageControl = nil;
    self.viewControllers = nil;
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
}

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

- (void)loadScrollViewWithPage:(int)page {
    if (page < 0)
        return;
    if (page >= kNumberOfPages)
        return;

    // replace the placeholder if necessary
    MyViewController *controller = [viewControllers objectAtIndex:page];

    if ((NSNull *)controller == [NSNull null]) // <== *** HERE SEEMS TO BE THE ERROR ***
    {
        controller = [[MyViewController alloc] initWithPageNumber:page
                                                  initWithNibName:nil
                                                           bundle:nil];

        [viewControllers replaceObjectAtIndex:page withObject:controller];
    }

    // add the controller's view to the scroll view
    if (controller.view.superview == nil)
    {
        CGRect frame = scrollView.frame;
        frame.origin.x = frame.size.width * page;
        frame.origin.y = 0;
        controller.view.frame = frame;
        [scrollView addSubview:controller.view];
    }
}

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    // We don't want a "feedback loop" between the UIPageControl and the scroll delegate in
    // which a scroll event generated from the user hitting the page control triggers updates from
    // the delegate method. We use a boolean to disable the delegate logic when the page control is used.
    if (pageControlUsed) {
        // do nothing - the scroll was initiated from the page control, not the user dragging
        return;
    }

    // Switch the indicator when more than 50% of the previous/next page is visible
    CGFloat pageWidth = scrollView.frame.size.width;
    int page = floor((scrollView.contentOffset.x - pageWidth / 2) / pageWidth) + 1;
    pageControl.currentPage = page;

    // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
    [self loadScrollViewWithPage:page - 1];
    [self loadScrollViewWithPage:page];
    [self loadScrollViewWithPage:page + 1];

    // A possible optimization would be to unload the views+controllers which are no longer visible
}

// At the begin of scroll dragging, reset the boolean used when scrolls originate from the UIPageControl
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    pageControlUsed = NO;
}

- (IBAction)changePage:(id)sender {
    int page = pageControl.currentPage;

    // load the visible page and the page on either side of it (to avoid flashes when the user starts scrolling)
    [self loadScrollViewWithPage:page - 1];
    [self loadScrollViewWithPage:page];
    [self loadScrollViewWithPage:page + 1];

    // update the scroll view to the appropriate page
    CGRect frame = scrollView.frame;
    frame.origin.x = frame.size.width * page;
    frame.origin.y = 0;
    [scrollView scrollRectToVisible:frame animated:YES];

    // Set the boolean used when scrolls originate from the UIPageControl. See scrollViewDidScroll: above.
    pageControlUsed = YES;
}

@end

MyViewController.h

#import <UIKit/UIKit.h>

@interface MyViewController : UIViewController {
    UILabel *pageNumberLabel;
    int pageNumber;
}

@property (nonatomic, retain) IBOutlet UILabel *pageNumberLabel;

- (id)initWithPageNumber:(int)page initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil;

@end

MyViewController.m

#import "MyViewController.h"

@implementation MyViewController

@synthesize pageNumberLabel;

- (void)loadView {
}

- (void)viewDidLoad {
    [super viewDidLoad];

    // Set the label and background color when the view has finished loading
    pageNumberLabel.text = [NSString stringWithFormat:@"Page %d", pageNumber + 1];
}

- (void)viewDidUnload {
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

// Load the view nib and initialize the pageNumber ivar
// classic initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
// class adapted to init the page number
// /!\ be careful, I'm not sure it's working properly
- (id)initWithPageNumber:(int)page initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    pageNumber = page;
    NSLog(@"pageNumber = %i", pageNumber);
}

- (void)didReceiveMemoryWarning {
// Releases the view if it doesn't have a superview.
[super didReceiveMemoryWarning];
// Release any cached data, images, etc that aren't in use.
}

@end


推荐答案

发生了无法识别的选择器错误,因为您在loadScrollViewWithPage的if语句中重新声明了本地变量controller:因为您这样做,新的控制器变量只存在于if语句的范围内,并且当您退出if语句,该范围之外的控制器变量仍为NSNull。

The unrecognized selector error is happening because you are redeclaring your local variable "controller" within the if statement in loadScrollViewWithPage: Because you are doing so, the new controller variable only exists within the scope of the if statement, and when you exit the if statement the controller variable outside that scope is still NSNull.

您可以通过删除if语句中的变量定义来解决:

You can fix by removing the variable definition inside the if statement:

if ((NSNull *)controller == [NSNull null])
{
    controller = [self.storyboard instantiateViewControllerWithIdentifier:@"MVC"];
    [controller initWithPageNumber:page];

    [viewControllers replaceObjectAtIndex:page withObject:controller];
}

这篇关于需要帮助在故事板上推送UIScrollView / UIPageControl中的视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆