I have a complicated storyboard that has ~20 controllers developed over several years which has been working great. However, with most recent versions of Xcode, each time I make any changes at all to anything in the Storyboard, Xcode goes through and removes ambiguous="YES" in all my controllers. Is there any way to stop Xcode from doing this?
It fully breaks my layouts. Yes, I'd love to go rewrite every controller to not have this issue, but in practical terms these layouts are battle-tested on every device and OS version and that isn't a high value rewrite for me.
sorry to hear you are running into issues with this. Could you provide more information about the storyboard or a view controller sample that is running into layout issues after the change in ambiguous=YES status?
Generally, ambiguity is caused when there are not enough constraints to specify a size or position. For something like an Image View, if an image is specified, then it will have an intrinsic size, and it will be enough to specify just positioning constraints. If ambiguous=YES is disappearing on a re-save, then could there be enough constraints to specify its position and determine its size? Deleting a positional constrain for the given view would put it back into “ambiguous”.
I know this might be too late to answer, but I run into the same issue and I wanted to let a guide to somebody else seeing the same issue in the future.
When a view frame position is ambiguous, the storyboard shows up a warning. Then some subviews include this ambiguous="YES" property in the storyboard file.
That means the view configurations for this Trait is not right. That doesn't mean that layout will not show properly when running the app since we might have Constraints that modify that frame positioning.
I don't know if this is showing up also for constraints ambiguity.
Related
I have already developed an IOS app in Objective C, Xcode 6 in which I have disabled the auto layouts and size classes.
Is it now possible to use auto layout after having disabled it earlier?
If yes, how can I implement it? When I enable the auto layouts and size classes and I implement the constraint on the label, the background colour of the label changes to white. When I do this for other object types, they become invisible.
To answer your first question, yes: it is indeed possible to use Auto Layout in an app after having disabled it. Each Xcode project template just gives you an initial starting point – nothing is set in stone.
For the second question, the best way of implementing Auto Layout in an app is to just take it one view at a time. You don't need to go all-or-nothing with Auto Layout; it's possible to just use it in certain cases but use frame based layout in others. Start on smaller, easier views and go from there.
The last issue around background colors is a little trickier without having screenshots or code samples. I have had views disappear on me after implementing Auto Layout and the issue always boiled down to bad constraints. The best solution I can give there is to just do the usual view-debugging work (as in, printing frames and manually setting bright colors to see where views actually are) and figure out what is going wrong.
Having the background color change to white is interesting, though... Auto Layout should not be affecting that at all. It sounds like the background color got changed somehow while the constraints were being created.
I have issue with autolayout.
I have three different views (could be n views as well). When I pin first one to top of super view and connect one next to the other everything seems fine. But if I want to change height of first one the other two does not follow (they stay on the same position). What I find weird about this is that if I connect only two views this works perfectly.
To have better understanding what I am trying to achieve I made simple, example solution with three views:
http://i.stack.imgur.com/cMwiB.png
So, when I set height of green view to 0 ( can be any other number as well ) and only red view is connected, this works fine, red will move as it should. Blue one is not connected and it remains where it is:
Here is screenshot when I connect blue to red:
What I tried to do:
connect blue one to green as well ( not working)
connect blue only to green ( not working )
"boxing": have boxes with views at the time ( ugly, hard to manage, not working in all cases)
What I would like to know:
what makes this happen? Can I change this kind of behavior?
What is the best practice to have flexible length for height (Besides UITableView)
Thanks in advance.
Ok, I think you're falling into the same trap I did, when I investigated autolayout some time ago. It's tricky to explain, but I'll do my best. When you work with autolayouts, you need to forget completely about setting a view's frame at all. And that, my friend, includes changing size and positioning. When you use autolayout, you define some constraints, some "rules", that the view tries to respect when rendering the screen, so the more specific the rules are, the less random will be the behavior of the view. I mean, if you just define the spacing between views, you're implying that the height of the views doesn't matter, so it's possible that some views grow or shrink when the re-layout is called (that is, if you don't specify a constraint for size. You probably want to always specify the size of some views in every layout...)
By the way, you're allowed to violate the constraints by manually changing the frame of an element AFTER a re-layout is called, but when the re-layout method is called again, the constraints will be forced so the size and positioning of the views will change. Quick tip: an easy way to force the re-layout method is to change orientation (command+left / command+right in the simulator).
So after saying that, I have to say that the layout you provided is completely working as intended, at least to me. When you change orientations the constraints you specified are ALWAYS being respected. If you want, you can try to apply some frame-setting in the viewDidAppear method, because this one is called AFTER the autolayout (and thus, you're able to violate the constraints temporally). After doing this, your view will be broken but once you change orientation the constraints should be respected again. Make sure it's that way.
From here I can only wish you luck ;) Oh, and refer to the documentation, it was a life saver to me when I looked at this half a year ago. https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/Introduction/Introduction.html It might seem a classic, but it's a pretty nice doc.
EDIT: one last thing. I have the impression that constraints are not designed to be dynamic. You define them once, and they're there always. Their main purpose is to ensure that subviews are rendered as intended in every screen resolution without fail, so if I were to make an application with moving views, I would leave them outside of the autolayout, or avoid using it at all. Just a personal impression though :)
how to give sizes for view(height or width) for a iPhone and iPad separately using auto layout via interface builder ?
This question is a bit old, but for everyone coming here, the answer is: You don't. If the reason wasn't very clear back in 2014 when this question was asked, it is very clear since iOS 9 and the introduction of Split View and Slide Over.
To be a bit more concrete:
Don't rely on separate storyboards or UIDevice.current.userInterfaceIdiom. This tells you if you are on an iPhone or iPad, but since an app can now be in split view, it doesn't give you ANY information about available screen real estate
Don't rely on UIScreen.main.bounds - if an app is in split view, the screen bounds might not equal your app's size, so this information is useless for layout decisions
Don't blindly rely on self.view.bounds in your view controller. If the user moves the app into split view, the size of your view might change at any time. You CAN use this if you're monitoring the bounds (e.g. by overriding bounds and using didSet), but I would argue there is almost always a better way, and this doesn't help you if you are not in a view controller.
Apple recommends using size classes. While this does seem a bit limiting at first and takes some getting used to, almost all layout decisions these days can be solved using size classes and proper auto layout. The great thing about size classes is that, if the size class changes, for example because an app moves into split view, the system will automatically take care of removing the auto layout constraints of old size class and adding the appropriate ones for the new size class.
I've always done my UIs in code but have decided that I should use storyboards and auto layout for a current project. Everything had been going well until I built a complex scene with about 50 views with lots of hierarchy and some grid of views.
The problem is that my auto layout is getting muddled on some devices and orientations. I'm finding it challenging to use IB to try fixing the dozens (hundreds?) of constraints or to track down the problems and resolve them. The situation is such that I'm not getting errors or warnings, just some unpleasant layouts at times. And IB can be a pain with all the clicking and changing settings you need to do to track down constraint information, let alone get a full idea of how they all relate in a scene.
I've just spent a day reading docs and background material on auto layout and constraints and it seems my best solution is to use the visual format to specify constraints in code and create some custom code to help. However, I can't seem to find anything on how to make the transition from IB to code.
Specifically, should I wipe all IB constraints and do them all by hand or is it possible to be selective? I ask because I have some groups of views in containing views where the content views have a perfect layout.
Secondly, where best do I put my code? I want to coexist storyboards and just want to selectively modify some complex scenes. Is a view controller's viewWillAppear: the right place to modify or remove/add constraints for the view it controls?
Connect an IBOutlet for the NSLayoutConstraint you want to be able to modify in the storyboard/xib file to your controller/view class.
Once you have the layout object connected, you can modify the .constant property and animate the view:
[self.containerView layoutIfNeeded]; //make sure all layout operations are done
self.containerViewBottomLayoutConstraint.constant = 200.0; //change the layout
[UIView animateWithDuration:duration animations:^{
[self.containerView layoutIfNeeded]; //animate the changes
}];
updated: you can add your modification code in viewDidLoad, awakeFromNib, viewDidAppear, or event based. It really depends on your intentions.
Sorry to take so so long to get back to this while other projects intruded.
I had to do a lot of refactoring to simplify my scenes so that auto layout could do the right thing, and yet I am not fully satisfied with the results. The problem seems to be that IB is just not easy to use with lots of items, and that auto layout is complicated, by necessity.
With that said, the best results I've seen so far are drawn from this article by Justin Driscoll: http://themainthread.com/blog/2014/02/building-a-universal-app.html
He advocates building custom views to encapsulate reusable UI components. I have taken this approach but have extended the idea to also bundle up related components that are not going to layout very differently as the layout changes. For example, I have a progress bar with button and two labels, so even though I am not reusing them as a group, they need to be adjacent and conceptually are related, so I've made a custom view for them which handles the auto layout as Justin suggests.
I'm now taking the approach that each level of auto layout should only have a handful of elements. If one level gets too complex, I'll bundle up some related items in a custom view and push some auto layout inside that new view. So far it isn't too bad.
Auto layout can be really tricky when using that many views. I have used similarly complex views structures, and I find that it is best to try to keep all of the constraints in code or in IB. Right now we are keeping them in IB. The only time that we move a constraint into code is when we are supporting a different screen size, and we need to modify a single constraint for the view to work right. I have always modified the constraints in viewDidLoad myself.
When something gets messed up I almost always have to nuke all of the constraints on that view and start over. It sucks, but it's often quicker than tracking down the problem. One thing that we do that makes it easier to deal with that sort of thing is to use .xibs along with your storyboard. That way, each view can handle it's own layout, and you can pull that into a view that is sitting in a storyboard.
If anyone have Google+ App can certainly understand what I'm trying to implement.
(explained here: UIViewController Containment with animation like Google+)
I think it has something related with the new effect in iOS 7 Calendar App.(explained here: Recreating iOS 7 Calendar UIView Animation)
-
This is a common animation effect that I'm seeing in many apps these days.
Months ago, the fellow Rob tried to help me with this his answer:
Now I was trying to implement it but there's a problem. Images explains better:
INITIAL STATE
WHAT HAPPEN WITH CURRENT IMPLEMENTATION
WHAT SHOULD HAPPEN
I've created a super simple project that shows the implementation (few lines).
Can someone help me to find where's the problem?
REPO: https://github.com/socksz/MovingTableViewCellContent
The problem is that you're trying to change the view's frame with Auto Layout on. You can't do that. The Auto Layout system will overwrite your changes. Try turning off Auto Layout in your storyboard and you'll see that it works.
So your options are:
Don't use Auto Layout
Use/manipulate constraints instead of frames.
For (2) you can just go into the storyboard and set up width and height constraints on the container view and it will work. If fixed size isn't the exact behavior you want, you'll need to be more explicit in your requirements.
The default constraints you're getting now are attached to the parent view and aren't getting carried along for the ride when you move the view to a new parent.