I currently have a Parent ViewController which contains a child UIViewController (Child). The child UIViewController has a UITableView. On Child.viewDidAppear I invoke the TableView.flashScrollIndicators.
For some reason the scroll indicators are not flashing. I've noticed if I put a dispatch_after call, the second pass does a flash. I thought at first it was a size issue, but I don't think that's it. It seems to be a layout issue (I'm using Storybards, iOS 7, and no AutoLayout). Any ideas?
Here's my code for creating the Child.
- (void)viewDidLoad {
[super viewDidLoad];
// add it to the heirarchy
if ([[self childViewControllers] count] == 0) {
[self setViewControllers:[[NSMutableArray alloc] init]];
ProductSelectionViewController *destination = (ProductSelectionViewController *)[[self storyboard] instantiateViewControllerWithIdentifier:#"ProductSelectionViewController"];
[self addChildViewController:destination];
// present the child
[destination didMoveToParentViewController:self];
[[self containerView] addSubview:[destination view]];
[[self viewControllers] addObject:destination];
[destination setDelegate:self];
}
}
For me, it worked to call
[self performSelector: #selector(flashScrollIndicators) withObject: nil afterDelay: 0];
instead of
[self flashScrollIndicators];
in didMoveToWindow method of the view or in viewDidAppear of its view controller. Hope this helps people with the same issue.
Related
I have looked at the other answers to this question, and none of them have helped.
I have a UIScrollView in my very simple scene, embedded like this:
I use this code to make sure the scroll view will actually scroll, based off of this answer.
-(void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self resizeScrollView];
}
- (void) viewDidLayoutSubviews {
[self resizeScrollView];
}
- (void)resizeScrollView
{
_scrollView.scrollEnabled = YES;
[_scrollView setContentSize:_innerView.frame.size];
}
- (IBAction)cameraButtonPressed:(id)sender {
UIViewController *vc = [UIViewController new];
[self.navigationController pushViewController:vc animated:YES];
}
The problem is that scrolling doesn't work after I've pushed and popped the new ViewController (Which originally was an image picker btw).
I don't know why this worked, but I wrapped everything in another view, and it's perfect now.
I have written a custom view controller container that can replace the existing view controller (VC1) with a new view controller(VC2) i.e. a replace type segue rather than pop/push.
Everything worked fine until testing with iOS 8. It seems a second party I'm using causes a crash if the view controller is replaced before the previous view controller is dealloc
i.e. if [VC2 viewDidLoad] called before [VC1 dealloc].
It is my understanding that I have no control over the dealloc so this kind of behaviour is out of my control. However, I want to make sure that I am not causing this behaviour in the way I'm controlling my child view controllers.
The following is pseudo code for my view controller container:
- (void)replaceStackWithNewController:(UIViewController*)newVC {
for(UIViewController *vc in [self viewControllers]) {
[vc willMoveToParentViewController:nil];
if([vc isViewLoaded]
[[vc view] removeFromSuperview];
}
[vc removeFromParentViewController];
}
//self.viewControllers is my navigation stack
self.viewControllers = nil;
self.childVC = nil;
if(newVC != nil) {
self.childVC = newVC;
}
[self addChildViewController:newVC];
//this adds the view to a pre existing wrapper
[self addView:newVC.view ToWrapper:wrapper];
//add controller to stack
[self.viewControllers addObject:newVC];
[newVC didMoveToParentViewController:self];
}
I'm using a custom rootViewController, and am using the code below to access it from any UIViewController
#implementation UIViewController(CustomRootVC)
- (CustomRootVC*)customViewController
{
UIViewController *parent = self;
Class customClass = [CustomRootVC class];
while ( nil != (parent = [parent parentViewController]) && ![parent customClass] )
{
}
return (id)parent;
}
#end
If I call self.customViewController on viewDidLoad I get nil. If I call it on willAppear I get the reference I expect.
I'm guessing this is something to do with the order I add the view controllers to my view controller container (i.e. viewDidLoad is called before the view controller has been added to customViewController and so it isn't a parent), but I can't spot anything obvious. I add the view controllers as follows:
- (void)addViewController:(UIViewController*)controller toWrapper:(PLSliderView*)wrapper{
[self addChildViewController:controller];
[self addView:controller.view ToWrapper:wrapper];
[self.viewControllers addObject:controller];
[controller didMoveToParentViewController:self];
}
In particular, the issue seems to be with adding a new view controller and view as follows:
- (void)replaceTopOfStackWithViewController:(UIViewController *)newController animated: (BOOL)animated {
UIViewController *oldController = self.currentController;
[self addChildViewController:newController];
[self transitionFromViewController:oldController
toViewController:newController
duration:1.0
options:UIViewAnimationOptionTransitionCrossDissolve
animations:nil
completion:^(BOOL finished) {
[self.rightViewController didMoveToParentViewController:self];
[self removeViewController:oldController];
[self queryDimensions:#"REPLACE"];
[self.view setUserInteractionEnabled:YES];
self.currentController = newController
}];
}
The view controller hasn't been added to the view controller hierarchy at the time viewDidLoad is called, hence it has no parent view controller, hence your function returns nil as expected.
this piece of code (parent = [parent parentViewController]) sets parent equal to self.parentViewController. If self does not have a parent view controller at the time this is called, it would return nil as expected.
more broadly, I'm not sure what you're trying to accomplish with this code, or why you need to use a category. it seems like that sort of behavior would make more sense in a UIViewController subclass.
I am using AddChildViewController and adding a CalendarViewController, here is the code to add it
- (void)calButtonClicked
{
m_calViewController = [[CalendarViewController alloc]initWithNibName:#"CalendarViewController" bundle:nil];
[self addChildViewController:m_calViewController];
[[self view] addSubview:[m_calViewController view]];
[m_calViewController didMoveToParentViewController:self];
}
Now this CalendarViewController I have a function to create the calendarUI , I have written it in
- (void)viewDidLoad
{
[self createCalendarUI];
}
Now whenever I click on the button to open this ViewController , method viewDidLoad is called everytime and it takes time to create the UI. And because of that , my app is becoming slow.
So is their any way so that my UI is created only once, So that I can improve the efficiency
Regards
Ranjit.
if you just want to reuse CalendarViewController
try reuse CalendarViewController's view and do not alloc CalendarViewController in calButtonClicked each time.
- (void)calButtonClicked
{
if(!m_calViewController){
m_calViewController = [[CalendarViewController alloc]initWithNibName:#"CalendarViewController" bundle:nil];
[self addChildViewController:m_calViewController];
}
[[self view] addSubview:[m_calViewController view]];
[m_calViewController didMoveToParentViewController:self];
}
I'm trying to implement a page-scroll functionality in my project. I develop for iOS 5, with storyboards (and ARC). This is what I did in my storyboard :
The first viewController (on the left) has a scrollView and a pageControl. Its class is called GlobalDashboardViewController, and inherits from the class DashboardViewController (which inherits from UIViewController). The other 2 controllers are simple UIViewControllers with identifiers (MainDashboard and SecondaryDashboard).
In GlobalDashboardViewController.m, there is only a viewDidLoad, which gets the childViewControllers :
- (void)viewDidLoad
{
[super viewDidLoad];
[self addChildViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"MainDashboard"]];
[self addChildViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"SecondaryDashboard"]];
}
DashboardViewController.m is a bit more complex. Here are the most important methods :
- (void)viewDidLoad
{
// Calling the viewDidLoad above to populate the childViewControllers array
[super viewDidLoad];
[self.scrollView setPagingEnabled:YES];
[self.scrollView setScrollEnabled:YES];
[self.scrollView setShowsHorizontalScrollIndicator:NO];
[self.scrollView setShowsVerticalScrollIndicator:NO];
[self.scrollView setDelegate:self];
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
self.pageControl.currentPage = 0;
_page = 0;
[self.pageControl setNumberOfPages:[self.childViewControllers count]];
UIViewController *viewController = [self.childViewControllers objectAtIndex:self.pageControl.currentPage];
if (viewController.view.superview != nil) {
[viewController viewWillAppear:animated];
}
self.scrollView.contentSize = CGSizeMake(scrollView.frame.size.width * [self.childViewControllers count], scrollView.frame.size.height);
}
There are plenty of other methods, but I don't think they're relevant, because here is my problem: the app launches, and I see the scrollView and the pageControl. The background is dark gray, as I set it in the GlobalDashboard viewController. I can scroll correctly, and the pageControl is updated. But I don't see the other views. When I place a breakpoint at the if in viewWillAppear, and look at viewController, it's named correctly (Dashboard Page 1, which is the name I gave to the controller in the storyboard), but its _view property shows 0x00000000, as you can see here :
So, I never get inside the if, which is where some of the magic of actually showing the viewControllers happens...
My work is based on an example project you can find here : PageViewController. When I run it, it works perfectly. I have no clue why I can't make it work in my own project.
Any ideas ?
Thanks
You never add the view itself ([self.view addSubview:/*Your child controller's view*/]). The project you linked to does it in - (void)loadScrollViewWithPage:(int)page inside PagerViewController.m