What is the difference between Adding UIView on Storyboard OR on Storyboard Upper Bar? - uiview

When i drag and drop a UIView on storyboard and when i do the same on the Storyboard Upper BAR. (where we generally find 3 options)
A. Name of the class.
B. First Responder.
C. Exit.
So it seems it is used just to provide a good symmetry in storyboard and to keep the things nice and clean.
I have been looking for it for many days but no where i find anything about this particularly.
I have done it like below:
from assistant editor i create an object named ScoreCardView. (there is one more view, due to scrollview, and then tableView).
_ScoreCardView.frame = CGRectMake(0, 10, ScreenWidth, ScreenHeight-50);
_ScoreCardView.backgroundColor = [UIColor greenColor];
_ScoreCardView.transform = CGAffineTransformMakeRotation(M_PI/2);
[self.view addSubview:_ScoreCardView];
[self.view bringSubviewToFront:_ScoreCardView];
I want it to rotate landscape(even in portrait mode), but tab bar would remain as it is.
Its working fine if a use UIView on the storyboard itself, but not with (UIView extension view ?)
Kindly Help.

The only difference is when you add view on your controller you need not to add view to the controller's view. On the other hand if you add that view on the top bar of the controller you have to add that view as subview using code:
self.view.addSubview(viewToAdd)
Thanks.

Related

TLYShyNavBar extension view doesn't work with Storyboard

I'm using the TLYShyNavBar library for my Table View Controller in order implement the navigation bar dynamic contraction when scrolling the table elements. I would like to have an extension view containing a Search Bar plus two additional labels underneath it. Following the examples reported in the guide, the extension view is generated by code (which works fine):
[self.shyNavBarManager setExtensionView:self.toolbar];
but when I use the Storyboard for creating this view the contraction doesn't work properly (To be precise the nav bar contraction behaves correctly but the extension view just disappears where it should instead be contracting progressively).
I would prefer not generating this view programmatically as this makes defining the Auto Layout constraints much more complicated (a bit easier using the Storyboard instead).
How are you providing the extension view to self.shyNavBarManager? If you are using an IBOutlet it will already be part of the view controller's view hierarchy, so you'd need to remove it from that first. Also if you are using Auto Layout in your Storyboard then you will need to turn on autoresizing mask translation for the extension view before you add it to the bar manager:
[self.toolbar removeFromSuperview];
[self.toolbar setTranslatesAutoresizingMaskIntoConstraints:YES];
[self.shyNavBarManager setExtensionView:self.toolbar];
This is still an issue in the latest version of TLYShyNavBar. The solution below works:
topTrayView.translatesAutoresizingMaskIntoConstraints = true
shyNavBarManager.extensionView = topTrayView

Accessing and manipulating parent view controllers views from a container view IOS

I am making an app where I have a container view that is half the screen of my view controller. From the container view controller's class I am trying to access and manipulate a view that sits out side of the container view. (picture below)
I am trying to access and add items to the scroll view from the container view class like so:
parent = (GFProfileViewController*)[self parentViewController];
UIScrollView *scroll = (UIScrollView *)[parent.view viewWithTag:222];
parent.titleHolders.contentSize = CGSizeMake(320 * 4,60);
UILabel *testLabel = [[UILabel alloc] init];
[testLabel setFrame:CGRectMake(0, 0, 100, 40)];
[testLabel setText:#"My Test label"];
[parent.titleHolders addSubview:testLabel];
scroll.backgroundColor = [UIColor blueColor];
how ever does not work. I tried even accessing the view from the parents "view with tag" method.
neither works.
I know the code is fine because when I move it to the parent vc all works as expected. I need to be able to manipulate the view from the container though. Can anyone help?
As nhgrif says, don't do that.
You should treat another view controller's views as private.
Again, as nhgrif says, create a public method in the parent view controller that takes the information needed and does the displaying itself.
If the view controllers are just being initialized then the parent view controller's view hierarchy may not exist yet. In that case you'd want to set properties to hold the value(s) you want to display, and then display them in your viewWillAppear method.
With storyboards and iOS >= 6, you can set up the child view controller using an embed segue, and then in your prepareForSegue method you can set the parent view controller up as the child view controller's delegate. That's a clean way to have the child communicate back to the parent. (I have a sample app on github that demonstrates this technique if you need a more detailed explanation.)
As far as programming ethics, correctness, good practices and whatnot, I think others have that covered. What you want to do surely isn't the clean way to go, but I often find myself going for such shortcuts, but you really need to know what you're doing, and if it isn't coming back to bite you later. The good thing is that it takes one line of code to achieve and has very low overhead. The problem is that such approach is highly dependent on the view structure, so if you change it, it will no longer work.
With that being said. What you tried doesn't work because the 'parentViewController' property isn't set on any arbitrary view. It should only be defined on the main view of the view controller, the one you can access from 'viewController.view'.
I will assume from your comment that your view structure is something like:
UIView
UIView
UIScrollView
Container
So basically starting from Container you need to go up one level and then down to UIScrollView like this:
UIScrollView = [((UIView*)[self.superview.subviews objectAtIndex:0]).subviews objectAtIndex:0];
I am unsure if you can search by tag from the upper view, since the one you're searching for is somewhere nested inside, farther than one level down. Assuming you can actually do that, this should also work and be more fail proof.
UIView *upperView = self;
while([upperView superview]){
upperView = [upperView superview];
}
UIScrollView *scroll = [upperView viewWithTag:222];

How do I make my iOS7 UITableViewController NOT appear under the top status bar?

My root controller is a TabBarController (tabbed application). One of the tabs, is a UITableViewController. When I switch to that and scroll through the items, they show up under the status bar at the top (signal, battery, etc). I don't want that. I want that to be opaque or... something. It's visually jarring with the text of the table cells underlapping the status stuff.
Can I fix this from my Storyboard with some attributes setting that I don't understand? Or do I need to add some methods to my subclasses? Or maybe I need to wrap my UITableViewController with some other kind of controller?
I've tried numerous variations of the ViewController Layout and Extend Edges settings in the Storyboard attributes page, but none of them seem to change it for the better.
Update: I think my problem is very similar to iOS 7: UITableView shows under status bar. The only difference, is that I'm embedded in a TabBarController, and that case is as the root view. I tried the solution listed there of embedding in a NavigationController and setting Show Navigation Bar to False, but it didn't make any difference.
Screen Shots:
My storyboard (shrunk) showing a tabbed controller, with 2 children, one single view, and the other the table view.
Settings for the tab bar controller
Settings for the table view controller
What the app ends up looking like on my phone
How the Story Ended
Despite lots of answers below, none of them really worked. Some kind of a little, but not really. I tried the Embed in NavigationController approach as well, and that also had issues. What did work though, was this:
Add UIViewController
Set child controller relationship with it and tab bar controller (just like the other two I already had)
Add a TableView (not controller) to the new UIViewController, position as desired, it'll snap to the bottom of the status bar
Set the TableView's delegate and tableSource as the new controller
Create a custom UIViewController subclass and update the class type of the controller in the storyboard
Copy the table related methods from my custom UITableViewController subclass to my new subclass
Select my prototype table cell from the original, and command+drag it to the new table view
Happily delete the original TableViewController (and wrapper NavigationController) too
Update the tab bar item to match the previous
Chock another one up for "you're trying to hard"
Try this in viewDidLoad:
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0);
20 px being the height of the status bar. If you have a navigation bar use 64 instead of 20
In case anyone is still reading this thread:
What worked for me is to also uncheck the "Extend Edges" options in the parent tab bar controller. That gives a consistent behaviour in iOS7 as well as iOS6.
I was having the same problem when using the SWRevealController.
Using the comments above and below I was able to get it to work by putting this in the
-(void)viewWillAppear instead of ViewDidLoad
self.tableView.contentInset = UIEdgeInsetsMake(20, 0, 0, 0);
Have you tried adding something like this to the view controller's viewWillAppear method:
if ([self respondsToSelector:#selector(setEdgesForExtendedLayout:)])
{
self.edgesForExtendedLayout = UIRectEdgeNone;
}
In case anyone misses the How the story ended section at the end of the (now long) question, the short answer is: Use a simple UIViewController with a TableView, instead of a TableViewController if you want to achieve the stated goal.
I added the following to viewWillAppear
self.tableView.contentInset = UIEdgeInsetsMake(22, 0, 0, 0);
You can also solve this through Storyboard.
Select the Table View from the Project Outline (left side of the editor) and then go to Properties (right side) > Size inspector tab > Scroll View > Content Insets > Top
suppose your table's #IBOutlet is
#IBOutlet var tableView: UITableView!
create a function prepareTable(). add the below line into that method
tableView.contentInset.top = UIApplication.shared.statusBarFrame.height
call this method from ViewDidLoad()
Looks like you just want to make the NavBar nonTranslucent, you could try using
[self.navigationController.navigationBar setTranslucent:NO];
I encountered the same problem and the solution that worked for me was to add a section header view:
-(UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
I then added 20 to the origin.y of my text on the header.
I then changed the header height by adding 20 to the original height using the
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return myHeight+20;
}
For me an easy solution was (code is in C# that's because appears to be invalid)...
Just in the UITableViewController constructor create a new UIView (set same dimension of the TableView).
Add the TableView to the new created view.
Set new created View to the UITableViewController's View property...
On the constructor of the UITableViewController
var view = new UIView ();
view.Frame = this.TableView.Frame;
view.AddSubview (this.TableView);
this.View = view;
As of iOS 8.4 I didn't get anywhere with the various storyboard options listed in other answers.
I worked around this without resorting to any dimensional constants by putting a regular view in my tab controller, then filling that with a "Container View" which I then connected to my UITableViewController with an "embed" segue.
My table now respects both my navigation bar and the tab bar at the bottom.
Let's say your Outline view, or Storyboard, is a Tab Bar Controller that currently has a Table View Controller. When you run the app, your table view cells are running under the status bar that seems to have a transparent background. This sucks!
If you spent hours trying everything you could find on StackOverflow to no avail, felt like maybe it really was time to consider a new career and were preparing to dial 1-800-LUV-TRUK or 1-800-SHT-KIKR, give yourself a pat on the back, open up whatever elixir you drink in times such as this, because it's not your fault. Really. Travis is absolutely right that no amount of code in viewDidLoad, viewWillAppear, or viewDidAppear or button selecting/deselecting in IB will help in this situation.
Travis' solution above will certainly work, but it's a bit long, there's copying and pasting of code, I have a short attention span such that an episode of Bugs Bunny feels like a full-length movie to me, so I just know that I'll screw-up anything that complicated. But, hey, your mileage may, nay likely will, vary. Anyhoo...
In Xcode 7.3 for an app running iOS 9 (I assume 7 and 8 but I don't know this for certain and am currently too lazy to check) there is an easier way that doesn't require one to write any code. And it's done all within Xcode's Interface Builder.
(Caveat: Sorry if any of the terms aren't accurate. Please let me know where I was mistaken and I'll correct any mislabeling.)
Go to the Utilities area of Interface Builder and select the Object library from the library pane.
Select a Navigation View Controller object and drag it into your Storyboard scene. You'll notice that two scene items appear while you're dragging–these are a Navigation Controller Scene and a Table View Controller Scene.
Delete the duplicate Table View Controller Scene that came-along with your Navigation Controller Scene.
Select the relationship connection between your Tab Bar Controller and your Table View Controller and hit "Delete".
Reposition the Navigation Controller and your Table View Controller the way you want in your storyboard.
Control-drag from your Tab Bar Controller Scene to the Navigation Controller Scene and select "Relationship Segue, view controller".
Control-drag from your Navigation Controller Scene to your Table View Controller Scene and select "Relationship Segue, root view controller".
Lastly, in the Utilities' Objects library, drag a Navigation Item object into your Table View Controller Scene's Table View.
Now when you run your app, you will have a navigation bar and your table view cells will no longer appear under a transparent status bar.
Hope this helps.

Possible to have a UINavigationController for a UITableView that doesn't fill the entire super UIView

This is on iOS5 w/ a storyboard.
I'd like to have a UINavigationController on the UITableView below but when I try the "embed in" option, it adds it to the Red UIView, not on the table itself. For lots of reasons this is not optimal. Is what I want to do not possible: to have a table subview with its own nav controller?
Oh - while I am here - what is the deal with UINavigationControllers not being able to be resized in a storyboard? I can only set "form" "page" or "full" - when I set it to "freeform" I am not able to enter any values to resize it
For lots of reasons this is not optimal
Actually, for lots of reasons what you are trying to do makes no sense. A UINavigationController has embedded within it (in Storyboard terms) an instance of a UIViewController. In other words, the nav controller's root view controller must be a view controller. Since UITableView is a subclass of UIView, you can't embed it inside a UINavigationController. And besides, you would never want to. A UINavigationController manages a hiearchy of view controllers. What are you trying to achieve that you think you need to put a UITableView inside of a UINavigationController? What you are probably trying to achieve is to place the view controller that the table view sits on inside a UINavigationController, in which case the result you're seeing in IB is the correct result.
UINavigationController is a view controller, not a view, so you can't embed it inside a view.
You should be able to get what you want with a little code: you can't embed it inside Xcode, but you can set up the UINavigationController and the red view separately, then write a few lines like this:
navigationController.view.frame = CGRectMake(20, 20, 280, 300);
[redView addSubview:navigationController.view];

Custom views with Storyboard

In complex screens (View Controllers) I used to separate the whole thing in smaller pieces (I call them widgets). These widgets consist basically of a MyWidget.h and a MyWidget.m file as well as a MyWidget.xib file, where the root element is a UIView and the MyWidget class is the File Owner of the UIView. In the init of this widget I do a loadNibNamed.
In my View Controller I then do a [[MyWidget alloc] init], which I add to View's Controller main view as a sub view. This, so far, works perfectly.
I'm now wondering, how to do the same with storyboard, because I cannot really start to drag in a UIView somewhere, I always have to start with an UIViewController, which I don't want to.
If there is no possible way doing this with a Storyboard, can I simply do it the old way, by using the Storyboard for my main screens and segues, and use a separate .xib file to define custom views?
Putting the widget/view in a separate .xib file works, and is appropriate especially if you might want to reference that same view from multiple View Controllers.
However, sometimes you do want to see the additional view/widget within the same storyboard, and it is possible. Here's how you do it:
Select your view controller in IB (click on the black bar below the view), then drag a UIView from the Object Library into the black bar:
When a view is in the black bar, it's instantiated like any other view in IB but just isn't added to your view hierarchy until you do so in code. Change the view's class to match your own subclass if necessary:
You can hook it up to your view controller like you would hook up any other view:
The added view shows up in your Document Outline and you can hook up actions and references there too:
Now, the problem that remains is that you can't actually see the view no matter how many times you try to click or double click, which would defeat the whole purpose of putting it in the same storyboard. Fortunately there are two workarounds that I know of.
The first workaround is to drag the view from the black bar back into your view controller's view, edit it, then drag it back into the black bar once you're done. This is troublesome but reliable.
The other workaround is more finicky, but I prefer it because it lets me see all my views at the same time:
Drag a UITableView from the Object Library into your newly added view.
Then drag a UITableViewCell into that UITableView.
Once you do that, your view pops out magically by the side, but you have a UITableView that you don't want. You can either resize that to 0x0, or you can delete it and your UIView will (usually) still stay visible.
Occasionally the secondary view will become hidden again in IB. You can repeat the above steps if you deleted the UITableView, or if the UITableView is still in the hierarchy you just need to click on the UITableViewCell and the view will appear again.
The second method works for UIViews but not so well for UIToolbars and is impossible for UIButtons, so the cleanest solution I've found when you need to include lots of different subviews is to attach a single secondary UIView to your view controller as a container that never gets shown, put all your secondary views in there, and use the UITableViewCell trick to make everything visible. I resize my dummy UITableView to 0x0 to make that invisible. Here's a screenshot of how it all looks like together:
If you're just looking to make your view controllers else-where(and not in your story-board), then there's a pretty simple way to accomplish this:
1) Create your CustomViewControllers(abcdController in the code I tried) with their individual xibs as usual.
2) Add a UIViewController(or whatever was the superclass of your CustomViewController) to the story-board.
3) Set the CustomClass to CustomViewController instead of UIViewController as shown here:
4) Finally, in your viewDidLoad, load the custom xib and you're done.
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSBundle mainBundle] loadNibNamed:#"abcdController" owner:self options:nil];
// Do any additional setup after loading the view from its nib.
}
I think you can do something like this to get instance of specific viewcontroller from Storyboard and use view on top of it.
ex:
MyViewController* myViewController = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"myViewController"];
UIView* view = myViewController.view; //Get the view from your StoryBoard.
Hope this helps
Thanks
Vijay

Resources