在故事板上的UIScrollView / UIPageControl中推送视图需要帮助
我试图在故事板上用UIPageControl实现UIScrollView来显示多个视图。 我发现的所有示例,教程或信息都是使用xib而不是storyboard。 我试图适应苹果的示例代码,但我错过了一些东西。 正如你所看到的,这很简单。
然而,无论我在ContentController.m中得到一个错误– [NSNull视图]:无法识别的select器发送到实例0x129acd8当我testing如果(controller.view.superview ==零)我推视图(见下面的后半部分码)。
或者只有UIScrollView和UIPageControl正在工作,我无法在UIScrollView中推送视图:
我知道这是一个简单的问题,但是我花了很多时间在这个和任何帮助将不胜感激。
我发布完整的代码,因为它可以帮助某人,当解决像一种教程。 根据贡献,我会根据需要更正代码。
提前致谢
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. // eg 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. // eg 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
无法识别的select器错误正在发生,因为您正在loadScrollViewWithPage中的if语句中重新声明您的本地variables“controller”:因为您正在这样做,新的控制器variables只存在于if语句的范围内,并且当您退出if语句该范围之外的控制器variables仍然是NSNull。
您可以通过删除if语句中的variables定义来修复:
if ((NSNull *)controller == [NSNull null]) { controller = [self.storyboard instantiateViewControllerWithIdentifier:@"MVC"]; [controller initWithPageNumber:page]; [viewControllers replaceObjectAtIndex:page withObject:controller]; }
所以我一直有同样的问题,但我只是做了一些可能工作得很好。
简短的回答是对Jonkroll关于在if语句中启动控制器的回答的补充。 出于某种原因,我不能解释为什么空的占位符不是空的,所以if语句不会像您在代码中指出的那样执行。 所以我所做的是修改if和添加一个else if和从故事板加载ViewController。
if ((NSNull *)controller == [NSNull null]) { controller = [self.storyboard instantiateViewControllerWithIdentifier:@"MVC"]; [viewControllers replaceObjectAtIndex:page withObject:[controller initWithPageNumber:page]]; } else { controller = [self.storyboard instantiateViewControllerWithIdentifier:@"MVC"]; [viewControllers replaceObjectAtIndex:page withObject:[controller initWithPageNumber:page]]; }
其余的代码和你的一样。 我知道是不是有史以来最好的代码,我可以通过启动ViewController没有一个if / else语句一起,但我没有答案,为什么这是必要的或最糟糕的为什么实际上没有如我所料地工作。 如果有人知道,请分享。
首先,对于这个线程来说,它确实是一种教程或对我的引用。
我做了几乎完全像你所做的一切,除了在内容控制器我把以下代码(基于@ jonkroll的答案):
if ((NSNull *)controller == [NSNull null]){ controller = [[self.storyboard instantiateViewControllerWithIdentifier:@"MyViewController"] initWithPageNumber:page initWithNibName:nil bundle:nil]; [viewControllers replaceObjectAtIndex:page withObject:controller]; }
MyViewController(在我的例子中有不同的名字,但是不相关)从UITableViewControllerinheritance,因为它是我需要的东西。 我的initWithPageNumber方法如下所示:
- (id)initWithPageNumber:(int)page initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { pageNumber = page; NSLog(@"PageNumber = %i", pageNumber); return self;
}
加了return.self,注意。
最后一件事是,我通过编辑器 – >embedded – >导航控制器embedded了导航控制器中的ContentController。
这几乎是一切。 后来,我甚至设法从MyViewController导航到另一个视图,一切工作正常。
如果你需要进一步的帮助,你可以在这里自由地问。
问候。
当我尝试从Apple文档中遵循UIPageController的示例代码时,我遇到了同样的问题。 对于我编程MyViewController,所以我直接使用下面的代码
if ((NSNull *)controller == [NSNull null]) { MyViewController * controller = [[MyViewController alloc]init]; [viewControllers replaceObjectAtIndex:page withObject:controller]; }
而且我在MyViewController中没有任何改变。