Positioning of object programmatically in Swift - ios

I want to set a position of an object programmatically. For this I do:
youtubeIco.frame.origin.y = 100
but nothing. It doesn't change coordinates at all. What is the problem?
And a second question:
when I set in the XCode constraints of webView(for ex: 10(top, left, right, bottom) it disappears. But when I do not set constraints for it, it appears. What is the problem?
I want like this:

You need to set full frame like,
youtubeIco.frame = CGRectMake(youtubeIco.frame.origin.x, 100,youtubeIco.frame.size.width,youtubeIco.frame.size.height)
Only y-axis change will not do anything to it, you have to provide full frame for that. or set centre, or offset.

With AutoLayout you can't change a view's frame directly. The constraint puts the object right back where it was.
Instead, you should add constraints that position your views and add IBOutlets to those constraints. Then you use the outlet(s) to change the constant value of the constraint, and the constraint moves your view objects for you. (In this context anything you can display on the screen is a view {a descendant of UIView} including buttons.)

Related

How to set up my constraint perfectly to the bottom in Storyboard

I am using AutoLayout in Storyboard. I have set translateAutoResizingMasksToConstraints to false. I have created a constraint like so:
The superView takes up the whole screen's frame. When I run the App, the bottom bar view doesn't appear. However, if in the picture I change constant to 50, it jumps up to about where it should be expected.
I have had a previous branch where I did not set it to 50 but due to some other constraints it appeared as expected. But it's not exact and I don't know why it's behaving this way all of a sudden. I've used the View Debugger feature and the bottom bar view straight up doesn't appear at all.
How can I set it so that the constraint has a constant of 0 and still appears? What might be a reason for this bug? Thanks!
When you are trying to add constraints to two items, you try an easier way by choosing two of them(even super view) like this:
Then click 'add new constraints' on the right bottom of storyboard/xib,
Then you can choose different types of align constraints as you like.
If you only choose one item to add new constraint, then align will be disabled cause it needs two items.
Try printing the bar's frame in view did appear, if you are not sure whether the bar is just outside the visible field. Have you set constraints to the sides and a height as well? As a rule of thumb you can say that a view needs 4 constraints before iOS knows exactly where you meant for the view to be placed.

Remove one view's layout constraints but keep its subviews'?

Working on a project in iOS 8 using storyboard and auto layout:
In storyboard, specified constraints for this view and its subviews
In code, in response to touch events, I'm going to change this view's size by setting its frame
To make both 1 and 2 warning free, I'm doing the following when first changing its size with code:
[theView removeConstraints:theView.constraints];
theView.translatesAutoresizingMaskIntoConstraints = YES;
theView.frame = CGRectMake(0,0,width,height);
If not doing the first line, Xcode will complain a whole bunch about constraint conflicts, however adding this line will remove all its subview's constraints as well. So my question is: is there way to just remove this uiview's constraints but not its subview, say a button on it still wants to center its self relative to this view's size and position?
First, you don't need to resize the view by setting frame otherwise what is the point of keeping the constraint at first place. You could have position that by simply having a correct initial frame.
Secondly, you have a mis-conception about "TO-WHOM" a constraint has been applied to.
say a button on it still wants to center its self relative to this view's size and position?
When you apply a position related constraint to a view you normally apply it to it's superview. Means if you want to position a subview in the horizontal centre of a view then the constraint is added on view not on the subview. That's why when you called a removeContraints: message on view that position constraint was removed and now your subview isn't bound to any constraint. However the width and height constraints are applied to subviews itself.
To solve this you need to make IBOutlets for constraint that you need to modify, which in your case should be width, height, horizontal x and top constraint; and then change the constant values for them respectively.
theView.widthConstraint.constant = newValue;

Why does UIButton resize when I access titleLabel property?

I'm trying to adjust the size of a button to (it's intrinsic size + a little bit more) in order to draw a custom background. However, every time I access self.titleLabel within the button, the size and position resnaps to that of the storyboard. I don't have to do anything with the label to reproduce this, just retrieve it from the button.
I've put logging code all over my button and view controller in order to find where this is happening. It's not coming from a relaying-out of subviews or any other notification I see to get within the view controller. The line before accessing titleLabel, the position and size are correct. The line after, it has snapped back to the storyboard position. Commenting out the access prevents the size/position snapping. Can someone tell me where or why this is happening?
I have no constraints set (that I can tell), but am I fighting against auto-layout here? Should I be doing this a different way like composing controls or something?
Something similar (or the same?) has been asked before at UIButton modifying titlelabel seems to change its frame and UIButton titleLabel resizes on press?, but both were left unanswered or explained away with just "maybe a bug."
If the project has auto-layout enabled, then YES, you're fighting auto-layout. You have two choices, either subclass UIButton so that you can override the intrinsic size calculation, or modify the constraints so that the intrinsic size is not used in any constraint. If you do the latter, then you probably want to create an IBOutlet to the constraint for the width, so that you can adjust the constant property as needed.
This isn't a bug, it's a consequence of auto layout. When using auto layout, you shouldn't set any frames. Instead, you should change the size or position by modifying the constraints. What's happening, is that whenever the view needs to be redrawn, the frame reverts to the frame that's defined by the constraints.

How do you override a storyboard element/view on iOS?

I have a UITextView set in my storyboard at a certain position. When the app first loads up, I would like the textView to be at a different position then where it is in the storyboard. I do this programmatically by setting its frame to a different frame with a different origin (later the textView will be animated back to the original position). But no matter how I do it, the app always starts up with the textView in its storyboard assigned position. I can't seem to do this anywhere... viewDidLoad:, viewWillAppear:, nothing works. How can I override it?
One other thing... lets say the textView has a different origin then it does in its storyboard (the frame was reset at some point in the app). If I add a subview to the textview using addSubView:, the textView resets to its original position in the storyboard. Why?! Any way to stop this?
If you want to change the position of the textView when it starts up, I'd suggest that you do not have it in the storyboard and instead add it to the subview with its correct frame.
Especially with Autolayout in effect, having it there already means you would have to modify its constraints and if you're modifying its position programmatically already anyway, you might as well add it to the view programmatically too where you have more control over its constraints programmatically as well.
Under auto layout you can't set frames - well, you can, but as soon as another layout pass takes place, the frame will be reset to that defined by the constraints.
The simplest way to change the size or position of views you've laid out in interface builder using auto layout is to create outlets to the various constraints, and then edit their constant properties. If that doesn't give you enough flexibility, you still need outlets to the constraints, but when you want to move things you'll have to delete those constraints and add new ones.

Auto Layout is preventing me from changing a view's center

One feature of my app is something that does automatic cropping of an image.
The basic idea is that someone would take a picture of a piece of paper (think: receipt), and then the image could get cropped automatically, after the borders of the paper are determined.
I'm able to determine the paper's border by using OpenCV. So, the next thing I do is to change the "center" property of each of my guides (just 2 horizontal and 2 vertical "lines" that can get dragged around manually).
Then, sometime shortly after I make all my calls to change each of the 4 guides, something else comes along and sets the "center" again. (I've overridden "setCenter" to prove this). The center seems to be reset by this: [UIView(Geometry) _applyISEngineLayoutValues].
I can't figure out why this is happening, or how to stop it, but it probably has to do with constraints. My view is a simple UIButton. When the user taps & drags on it with their finger, an action routine gets called that just changes the center. This works.
But in another case, I'm bringing up a UIImagePickerController. After they choose the picture, I determine the paper-bounds, change the "guides" centers, and then later on "_applyISEngineLayoutValues" sets them all back.
Any idea what's going on in this case? Or how I can set the center of a view, and have it actually stay?
The first rule of AutoLayout is that you can't update the frame, bounds or center of a view directly.
You must update the constraints related to the view so that the constraints update the view.
For instance, you first vertical line will have horizontal constraints something like...
1. Leading edge to superview = some value.
2. Width = some value.
This is enough (horizontally) to place this line on the screen.
Now, if you want to move this line to the right you can't just change the center you must do this...
1. Create a property in you view controller like this...
#property (nonatomic, weak) IBOutlet NSLayoutConstraint *verticalLine1LeadingConstraint;
// or if you're coding the constraint...
#property (nonatomic, strong) NSLayoutConstraint *verticalLine1LeadingConstraint;
2. Save the constraint in to that property...
// either use IB to CTRL drag the constraint to the property like any other outlet.
// or something like...
self.verticalLine1LeadingConstraint = [NSLayotuConstraint ... // this is the code adding the constraint...
[self.view addConstraint:self.verticalLine1LeadingConstraint];
Now you have a property pointing to this constraint.
Now, when you need to "update the center" of the vertical line 1...
// Calculate the distance you want the line to be from the edge of the superview and set it on to the constraint...
float distanceFromEdgeOfSuperview = // some calculated value...
self.verticalLine1LeadingConstraint.constant = distanceFromEdgeOfSuperview;
[self.view layoutIfNeeded];
This will update the position of the view and you won't get any errors.
You're using auto layout, so Fogmeister's answer is the right one, but not everyone can use auto layout - e.g. people who have to support the iPad 1 - so I'll leave this answer here.
If you need to use a view's frame but the system is adding constraints, then there is a workaround; but it's not pretty.
_applyISEngineLayoutValues sets your view's center and bounds, but doesn't touch frame. If you override setCenter: and setBounds: to do nothing, and then always use setFrame: in your own code, then _applyISEngineLayoutValues will leave you alone.
I'm not happy with this approach, but it's the only way I've found so far to stop _applyISEngineLayoutValues from pooing all over my layout logic.

Resources