Can't place UIImageView behind UITableView in storyboard - ios

I can't seem to position a UIImageView behind a UITableView on my Table View Controller. I'm trying to do this within the storyboard designer. Moving a UIImageView onto the View Controller just stacks the imageview onto the tableview. In previous versions of XCode I had a window that allowed me to change the stack order of views within a view controller. Is this still possible?? I've tried dragging the views around in the jump bar and this doesn't work. So how do I accomplish this using XCode 5?
Thanks!

Use UIViewController for parent of UITableView!
Or if you want to set Background of tableView, can use this code
self.tableView.backgroundView = [[UIImageView alloc] initWithImage:
[UIImage imageNamed:#"bg"]];

UITableView has a backgroundView property. You will need to set it in code.
In your example, you're probably using a UITableViewController in your storyboard. This means that the root view is a UITableView and you can't add a UIImageView as a subview to a UITableView and put it behind the superview. Doesn't make sense.
In a previous version that you've made, I suspect that you had a UIViewController with a UIView root view, which you added a UIImageView subview and a UITableView subview on top of that.

Every UIViewController is associated with a UIView, i.e. [viewController view]. In the case of UITableView, [viewController view] is of type UITableView, so when you add subviews to it, you're adding to the UITableView, not a superview of type UIView as you seem to expect.
I would recommend using a UIViewController to control that view, adding subviews of types UIImageView and UITableView.

Related

Attaching UIButton on top of UIScrollView or UITableView

What is the best approach for attaching a UIButton on top of UIScrollView or UITableView so when the view is scrolled, the button stays in its place.
Here examples below:
UIButton stays in the right bottom corner when the view is scrolled.
google+ app example
yahoo mail app example
I think this should work. Lay Out your button in a view that is outside of the tableviewcontroller. Then drag an outlet to the tableviewcontroller file. Then add it in code. This code would hold it at the top of the screen.
#IBOutlet var buttonView: UIView!
override func viewDidLayoutSubviews() {
self.view.addSubview(buttonView)
}
override func scrollViewDidScroll(scrollView: UIScrollView) {
var rect = self.buttonView.frame
rect.origin.y = max(0,scrollView.contentOffset.y + scrollView.contentInset.top)
self.buttonView.frame = rect
}
Thank you all for great answers!
I got it worked through storyboard by moving the button from scrollView to View itself. That way it's attached on UIView and it's independent of scrollview.
storyboard snapshot
So now the structure is:
- View
- ScrollView
- Button
Before it was:
- View
- ScrollView
- Button
There are many ways to go about doing this but two that I use most often are as follows.
One approach is embedding the view controller within a navigation controller. This will set a bar on the top and bottom if you choose that you can place bar button items upon.
Another approach is to place a UIView along the top and snap the constraints to the left, right, and top with 0 no-margin. Then set the height. I usually use 40px for the height but you can use what is applicable to your needs. After that you can place a button in that UIView and then set constraints on it to keep in in place.
In my experience, this isn't reliably possible to do with the scrollView itself.
My solution is usually to put anything that needs to float above the tableView/scrollView in a plain ViewController that also contains the tableView/scrollView parent.
If you're using storyboards with a UITableViewController scene, this will likely mean you need to use another scene with UIViewController with a container that has your UITableViewController.
For UITableView use tableHeaderView. For UIScrollView you need to create a separate view not in the scroll view's hierarchy.
Another solution is to put your UIButton in a UIToolbar, and then make the toolbar a child of the UINavigationController's view. After that, in viewDidLayoutSubviews, you can set the rect of the toolbar to sit just below the navigation bar and offset the top of the UIScrollView or UITableView.
Add button which you want in the storyboard.
Design your scrollview
self.view.sendSubviewToBack(scrollViewObj)(in the code)
This worked for me.

How to properly add a UITableView inside a nav and tab controller?

I have a navigation setup where at the top there is a UITabBarController. I then have a tab, which is instantiated by creating a UIViewController placed into a UINavigationController like so:
UIViewController *testVC = [UIViewController new]; // Has UITableView as subview
UINavigationController *testNavVC = [[UINavigationController alloc] initWithRootViewController:testVC];
[self setViewControllers:#[testNavVC]];
The problem that arrises is with the UITableView inside the testVC UIViewController. The table displays properly at the top and is correctly situated underneath the UINavController's nav bar. When you scroll the table view to the bottom, however, the final rows in the table view will be cut off at the bottom of the screen. I found out that I can set the bottom content inset to 100(value will differ based on row height) to correctly display the content. I don't feel like I should need to do that though, and am looking for a better solution.
How can I properly add a UITableView that is nested in this way?
As a side note this all works correctly when using a UITableViewController rather than a UIViewController with the added UITableView. In my case I am needing to use the latter option.
You can try to adjust UITableView bottom inset without hardcoding, by using bottomLayoutGuide property:
tableView.contentInset = UIEdgeInsetsMake(0.0, 0.0, self.bottomLayoutGuide.length, 0.0);
It indicates lowest vertical extent for content, and can be used from iOS 7.
As an alternative you can create bottom NSLayoutConstraint for UITableView with this value.
All of my code was done programmatically and the problem ended up being that I setup the UITableView with the views frame. I switched it over to use autolayout instead and it worked great!

Reusing a UITableView footer view in multiple views

I have a footer for a UITableView which is a "complex" view (textView and a button).
I made a xib and added it to the footer of the UITableView.
The next stage is having referencing outlets in the ViewController of the UITableView
The thing is that I want to use this footer view in several ViewControllers (and not DRYing)
What can I do?
It sounds like you want to have a xib/.h/.m separate from the .xib used by your UIViewController. This is for your View that will be used as the footer of the UITableView. You can [[MyFooterView alloc] init] in the viewDidLoad of any controllers that are using a UITableView and assign the footer to that instance of MyFooterView. Is this what you're after? You can still have referencing outlets to the UITableView in any UIViewController, and keep a reference to MyFooterView that you instantiated in viewDidLoad
addTarget example:
myFooterView.button addTarget:self action:myCustomHandlerFunction forControlEvents: UIControlEventTouchUpInside

View added to superview disappearing when navigating tableview

I have a tableView that navigates to a detail view when the user selects one of the tableView cells. This main TableView is created in a UITableViewController class. (MasterViewController)
I used StoryBoard to create the master-detail tableviews.
Within MasterViewController, I lay a tableView over top of the main tableView when the user selects the To button. This second tableView allows the user to select multiple values from this list.
In order to prevent this second tableView from scrolling on the screen when the first (main) tableView scrolls, I have added this second tableView to the superView of the MasterViewController view. ([self.view.superview addSubview:_toView];)
So, in MasterViewController, I add a TableViewController (_toController). I instantiate a UIView (_toView), add a background image to it (_toViewBG) and then add a TableView to it (_toTableView). I then add _toView (which contains this second tableView) to the superview of the MasterViewController view.
_toController = [[ToTableViewController alloc] init];
_toView = [[UIView alloc] initWithFrame:CGRectMake(10,10,263,247)];
_toViewBG = [[UIImageView alloc] initWithFrame:CGRectMake(10,10,257,232)];
_toViewBG.image = [UIImage imageNamed:#"toViewBackground.png"];
[_toView addSubview:_toViewBG];
_toTableView = [[UITableView alloc] initWithFrame:CGRectMake(20,30,220,180) style:UITableViewStylePlain];
[_toTableView setDelegate:_toController];
[_toTableView setDataSource:_toController];
[_toView addSubview:_toTableView];
[self.view.superview addSubview:_toView];
[_toTableView reloadData];
This approach keeps the second tableView from scrolling when I scroll the main tableView. The second tableView stays on top and in place as the main tableView scrolls.
If I select a cell in the main TableView, I navigate to a detailed view. When I return to the main TableView, I am unable to get the second TableView (_toView) to be displayed.
I am not sure how to tell the _toView to come to the front. I realize it is added to the superview of the MasterViewController view. From some experimentation, this superview appears to be a CALayer.
Can anyone suggest how I would get this _toView to display in front of the MasterViewController view?
Thanks in advance for any assistance.
Solved
I ended up just adding the second tableview as a subview of the MasterViewController view.
[self.view addSubview:_toView];
I then disabled scrolling on the main tableview while my second tableview is visible.
Self.tableView.scrollEnabled = No;
Seems to be working fine.
Tim
It may be possible to make this work by calling [self.view.superview bringSubviewToFront:_toView], but my advice would be to make MasterViewController a subclass of UIViewController rather than UITableViewController, and then add both of your UITableView objects as subviews of the root view, (rather than referring to superview).

Insert image at top of UITableView when using UINavigationController?

I have a UINavigationController and UITableView in my MainWindow.xib. I'm trying to insert a non-touchable/non-movable image at the top of the view. (I don't want to simply change the UINavigationBar background, as from what I've experienced, the UINavigationBar height cannot be arbitrarily increased.)
As this is a root view, its behaviour is controlled by my RootViewController. When the view loads, I hide the navigation bar using self.navigationController.navigationBarHidden = YES;
I've tried adding a UIView to the top of the UITableView, but when the user scrolls through the table, the top image moves. How can I place a stationary image at the top of the UITableView without it moving as if it were a cell and without using a UINavigationBar background image?
Naively-Considered Possibilities:
Enclose the view in another view, the top of which contains the image?
Overlay an image mask at the top of the screen?
(HIG violation, anyone?)
If your view controller is a UITableViewController you can't easily add another view because the tableViewController just manages a single view which is the UITableView. I recommend using a plain UIViewController instead where you add a UIView for your top view and a UITableView for your content as subviews to the main viewController.view. Then, implement the UITableViewDelegate and UITableViewDataSource protocols in your UIViewController.
You can create another UIViewController which contains the UITableViewController and your static image on top. This way, you can even resize the table view so the static image is displayed above and not over your table.
UIViewController *middleViewController = [[UIViewController alloc] init];
[[middleViewController view] addSubview:tableView];
[[middleViewController view] addSubview:staticImageView];
...
[navigationController initWithRootViewController:middleViewController];
Has been a long time since I made my last cocoa application, so I cannot promise that it works.

Resources