Adding viewController views to UIScrollView - ios

Despite the number of similar posts on this, I still am having trouble making this work correctly.
I have a two UIViewControllers which I have designed in IB with UILabels and imageviews, etc.
I would like to add these to a scroll view so they can be paged between.
I have outlets defined connecting each of the scrollViewcontrollers with their elements in IB, however, the controllers themselves, I am programatically creating from within the master view controller in viewDidLoad. After creating them, I assign some values from the master view controller than add it as a subview to the scrollViewController. However nothing displays. From the debugging i have done, when I set a break point after assigning the values, I can see that the elements are nil. They should be loaded from the xib file, but it does not seem to be read. Even as a test, I tried initializing one of the elements (eg. UILabel) and setting it to that sub view controller, but it nothing would display. Here is some code to explain a bit better.
In the master view controller
detailControllerA *tempA = [[detailControllerA alloc] initWithNibName:#"detailOverviewA" bundle:nil];
self.overviewA = tempA;
[tempA release];
self.overviewA.someLabel.text = #"Some Text";
detailScrollView.contentSize = CGSizeMake(scrollWidth, scrollHeight);
detailScrollView.pagingEnabled = YES;
[detailScrollView addSubview:self.overviewA.view];
In the detailControllerA implementation I set the frame in loadView:
-(void)loadView {
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 90)];
self.view = view;
[view release];
}
I also have the labels, etc defined with IBOutlets in detailControllerA.h and implemented to the elements in the xib file.
Any ideas why the xib is not loading correctly when created programatically?

Try in this way:
NSUInteger scrollContentCount = 0;
for (NSUInteger arrayIndex = 0;
arrayIndex < [contents count];
arrayIndex++) {
// set scorllview properties
CGRect frame;
frame.origin.x = self.mScrollView.frame.size.width * arrayIndex;
frame.origin.y = 0;
frame.size = self.mScrollView.frame.size;
myScrollView.autoresizingMask = YES;
// alloc - init PODetailsView Controller
myController = [[MyController alloc] initWithNibName:#"MyController" bundle:[NSBundle mainBundle]];
[myController.view setFrame:frame];
// add view in scroll view
[self.myScrollView addSubview:myController.view];
scrollContentCount = scrollContentCount + 1;
}
// set scroll content size
self.myScrollView.contentSize =
CGSizeMake(self.myScrollView.frame.size.width * scrollContentCount,
self.myScrollView.frame.size.height);
}
Don't release the content controller object which is in for-loop.
Set your scrollView contentSize according to your requirement.
Hope this would be helpful to you.

Interestingly enough, the -(void)loadView was the problem.
Since the view is being generated in interface builder (with the frame settings), when loadView fires, it was creating a new view, blowing away the one created in interface builder.

Related

Tableview frame issue when put in a scrollview

I wanted to post a gif but apparently I don't have enough reputation. Oh well, whatever; I was using UIPageViewController, but for some reason I decided to go with a more manual solution by using UIScrollView and adding the views of UITableViewControlllers to the corresponding offsets (pages). I have 4 UItableViewControllers on each page (the views of table view controllers) and all of these are added to the container view controller (which has the UIScrollView) as child view controllers.
The actual problem is when I made the switch, table views began refusing to go all the way down and part of the final table view cell stays trimmed by the end of the screen when the scrolling ends.
So, wanted to ask if anyone came across something like this before of know how to get rid of this. I know I could always use a library, but I want to learn. Here is some code:
_containerScrollView = [[UIScrollView alloc] initWithFrame:self.view.frame];
_containerScrollView.contentSize = CGSizeMake(_containerScrollView.frame.size.width * 4, 0.0f);
_containerScrollView.pagingEnabled = YES;
[self.view addSubview:_containerScrollView];
UITableViewController *vc1 = [[UIViewController alloc] init];
UITableViewController *vc2 = [self.storyboard instantiateViewControllerWithIdentifier:#"trendingViewController"];
UITableViewController *vc3 = [self.storyboard instantiateViewControllerWithIdentifier:#"placesViewController"];
UITableViewController *vc4 = [self.storyboard instantiateViewControllerWithIdentifier:#"favoritesViewController"];
self.rallyViewControllers = [NSArray vc1, vc2, vc3, vc4, nil];
[self addViewControllers];
Other methods;
- (void)addViewControllers{
if (self.rallyViewControllers == nil) {
return;
}
for (int i = 0; i < [self.rallyViewControllers count]; i++) {
UIViewController* viewController = [self.rallyViewControllers objectAtIndex:i];
[self addChildViewController:viewController];
[viewController didMoveToParentViewController:self];
[_containerScrollView addSubview:viewController.view];
}
}
This is called in viewDidLayoutSubviews
- (void)configureFrames{
if (self.rallyViewControllers == nil) {
return;
}
CGFloat width = _containerScrollView.frame.size.width;
CGFloat height = _containerScrollView.frame.size.height;
for (int i = 0; i < [self.rallyViewControllers count]; i++) {
UIViewController *viewController = [self.rallyViewControllers objectAtIndex:i];
viewController.view.frame = CGRectMake(i * width, 0.0f, width, height);
}
}
I should state upfront that I didnt completely understand your description of
"table views began refusing to go all the way down and part of the
final table view cell stays trimmed by the end of the screen when the
scrolling ends."
My answer is based on an issue I faced before. My setup is a uitableview in the storyboard container view ( without any parent scrollview)
I faced this issue where part of the tableview was cut off and I could not see about 5 bottom rows.
Turns out I did not have any constraints setup between the parent container view and the tableview.
To determine if your tableviews are rendering fine, get your project running in XCode and then press on the below button
This button will then pause your app and give you a visual stack of the the different views that are currently rendered in your app. You can then see if any of the children ( in your case tableviews) are rendered outside the frame of the parent view in which case that portion will not be visible. This indicates that you either dont have constraints (or) the current constraints you have are incorrect.
I got it. The problem was when I added the view controllers views to the scroll view, they returned dimensions as if there was no navigation bar. But they were still positioned under the navigation bar, which caused total view to have 64 pt more height than the screen could show. when I manually subtracted 64 pt from views, and it was fixed. But since that is a very crude way of doing this, I then tried to fix it by fiddling with auto-layout, which ended up fine.

Adding multiple views to a container view

I am looking at adding numerous TableViews to an existing UI View Controller.
I have seen https://developer.apple.com/library/ios/featuredarticles/ViewControllerPGforiPhoneOS/CreatingCustomContainerViewControllers/CreatingCustomContainerViewControllers.html which seems to be the way I'm meant to go.
However, my question is can I embed more than one TableView to a single ContainerView?
My app does a variety of tests for which there are results. After each test completes I want to add a TableView so they appear underneath each other neatly.
Is this possible?
Yes you can. You can do two things:
ONE View Controller - MANY Table Views (as subview of the root view)
or
ONE Container Controller - MANY ChildViewControllers using VC containment (and each has one Table View )
This is what you could do in ViewDidLoad for a UIViewController subclass.
// Do any additional setup after loading the view, typically from a nib.
CGRect frame = self.view.frame;
// this container shall hold the two tables that I am going to add later
// container shall share the same size as view controller's "view"
UIView *container = [[UIView alloc] initWithFrame:frame];
frame.size.height = frame.size.height / 2; // I want to fit two table view vertically to cover the container view
UITableView *tableView1 = [[UITableView alloc] initWithFrame:frame];
tableView1.backgroundColor = [UIColor redColor];
// ...
// ...
// Assign more table view properties here
// ...
// ...
[container addSubview:tableView1];
frame.origin.y = frame.size.height; // update coordinates for the second table view
UITableView *tableView2 = [[UITableView alloc] initWithFrame:frame];
tableView2.backgroundColor = [UIColor greenColor];
// ...
// ...
// Assign more table view properties here
// ...
// ...
[container addSubview:tableView2];
[self.view addSubview:container];
you shall have to set Delegates for all tableviews to make them work properly, but this should give you something to get going. (I have added some different background colors to distinguish between both the tableviews)

viewWillAppear not called in subordinate view

I have a UIViewController which loads a subview from a nib and adds it to a subview in its view hierarchy. Now this is working all fine in the iPhone story board, but in the iPad one although I do see the view but as the viewWillAppear is not called the UIImageView on the view is not initialised.
Here's the code from the main viewcontroller (the one that loads the subview)
SubViewController *controller = [[SubViewController alloc] init];
NSArray *bundle = [[NSBundle mainBundle] loadNibNamed:#"x"] owner:controller options:nil];
UIView *subView = bundle[0];
[self addChildViewController:controller];
if (isPhone)
{
CGRect frame;
frame.origin.x = 0;
frame.origin.y = 0;
frame.size = self.scrollView.frame.size;
view.frame = frame;
[self.scrollView addSubview:view];
}
else
{
view.frame = self.viewSlot.frame;
[self.viewSlot addSubview:view];
}
The only difference is on the iPhone it is added to a UIScrollView whereas on the iPad it is added to a UIView.
viewSlot and scrollView are both outlets which are properly initialised and work. Even on the iPad I do see my view (I've changed its background colour) it's only the initialisation (viewWillAppear) that does not run.
After a bit of playing I've managed to get to the bottom of this. First of all I chose to initialise the controller in a different manner:
SubViewController *controller = [[SubViewController alloc] initWithNibName:[#"X" stringByAppendingString:idiom] bundle:nil];
I've got an exception that revealed the problem: the view outlet wasn't set. Lesson of this story: don't just alloc - init a controller, use the initWithNibName initialiser. It's still weird that due to some not yet discovered difference between iPhone/iPad the earlier approach still worked on the iPhone.

view from xib won't autoresize

I have a custom split view controller, designed to work as much like apple's as possible.
I use this split view in three different places. Two of these places, the master is a view simply a UIViewController with a UIView attached, and created programmatically.
The third example however is a UIViewController with a XIB.
The problem is that the first two split views adjust their widths correctly. However the screen with the XIB does not. I'm not doing anything fancy, just trying to set the content view of my master with a view that is passed in to it. And setting the autoresizing masks as such:
// create container views
masterView = [[VS_MasterView alloc] init];
masterView.frame = CGRectMake(0, 0, masterViewWidth, self.view.frame.size.height);
masterView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
[self.view addSubview:masterView];
// get the views
UIViewController *masterViewController = (UIViewController *)[_viewControllers objectAtIndex:0];
UIViewController *detailViewController = (UIViewController *)[_viewControllers objectAtIndex:1];
// set their bounds
[masterViewController willMoveToParentViewController:self];
[self addChildViewController:masterViewController];
[masterViewController didMoveToParentViewController:self];
masterViewController.view.frame = masterView.bounds;
masterViewController.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[masterView addSubview:masterViewController.view];
is there some sort of special case with XIB files and resizing them in this situation? I don't feel like there should be.
thanks

Replacing self.view with new UIView shows black view

I want to change the existing view in a UIViewController to a new view. The new view contains the old view and a little banner view.
Doing this fairly simple change leaves me with a black view.
My code looks like this
UIView *existingView = self.view;
UIView *newView = [[UIView alloc] initWithFrame:existingView.frame];
UIView *bannerView = [[UIView alloc] initWithFrame:CGRectMake(0, (self.view.frame.size.height - 50), 320, 50)];
CGRect existingViewFrame = existingView.frame;
existingViewFrame.size.height -= 50;
existingView.frame = existingViewFrame;
[newView addSubview:existingView];
[newView addSubview:bannerView];
self.view = newView;
However when switch Tabs and come back to the view which changed the view is shown just like I want. I guess I need to set a flag or something to tell the controller to redraw it's (new) view.
Edit
I wrote an simple example for this problem. You can find it on GitHub: https://github.com/Oemera/ChangeView
You did not say where you do this. It may be that you need to save the original view's super view, then add the new view to that views subViews array. I'm betting that is the problem.

Resources