How to implicitly set UITextView contentSize? (Swift 3/xCode8) - ios

I have a need to set the contentSize of a non-scrolling UITextView exactly to it's superview's frame. I need to do this for the purpose of getting the range of characters that fit, and while I know there's better methods for doing this, or even better views to be using, I need to use this custom UITextView for it's specific capabilities. Simply doing:
textView?.contentSize = superView.frame.size
doesn't seem to set anything, and it's contentSize is still as long as it's content. I want to simply truncate the content at where it just wont fit anymore. I'm on Swift 3 and xCode 8 if that makes a difference.

You can do so using .bounds:
textView?.bounds = superView.bounds
That should set all the properties you want to be the same as the super view.

Figured it out. Scrolling was enabled. Disabling scrolling seems to have fixed it.

Related

Autolayout UITextfield

I have been trying to achieve following layout in autolayout
I want to acheive this
may be i am doing something wrong due to which i am getting following result.I get this
can anyone correct me ?
This kind of layout is easily accomplished by using UIStackView, Please use UIStackView either in storyboard or in code.
Please check Apple documentation on it
https://developer.apple.com/documentation/uikit/uistackview?changes=_6
If you are using storyboard for Textfield then simply give leading and trailing to Textfield. Dont give the fixed width to textfield, it will work for all devices.
Same logic if you are setting textfield programatically. Dont give fixed width
As said above, use your element inside a horizontal stackview. Unfortunately, if you’ve a iOS target iOS 9.0, you will have to use another trick. Your stackview will become a normal view which will contain your elements to align. After that, you can the element width to be equal to their superview with the multiplier use.
Per example if you have 3 elements inside your view but you want that the first one being larger than the two others by setting the multiplier with a certain ratio like 2:4 for the first one and 1:4 for the last ones :-)

What is the proper way of animate views when constraints applied?

I have to animate a couple of UIViews which I have added in a UIViewController inside the UIStoryboard. I have attached them with proper constraints so that they will always visible in a way I am looking. This is fine.
I am using https://github.com/satoshin21/Anima library to animate those views as per my need.
But the problem is they don't work as expected means, they are not animating in a direction or position it should be. I believe this is because of the constraints I have applied.
What is the best way to achieve this even if the constraints applied?
Setting, myView.translatesAutoresizingMaskIntoConstraints = true is coming up with lots of warning messages in console.
P.S. I am aware of taking references to the constraints in form of NSLayoutConstraints but this is not I am looking at as the above library is simply providing good chaining functions though we can do it without having references to the constraints.
The problem here, is that NSLayoutConstraint toggling works like properties in the sense that they are nothing but values which can be switched on/off, and alternated by playing with this toggling and other references to other possible values they can have. There's no real way of going around this that I know of unfortunately, and in fact i myself have built a small library similar to Anima, and it works rather well if you respect the NSLayoutConstraints' nature.
The proof of this is that under the hood of this Anima library, it's simply storing the animation points declared inside of the chain (inside Enum values in fact), and applying them as the animation moves along. Regardless, you should never re-set translatesAutoResizingMaskIntoConstraints to true when working with NSLayoutConstraints.
The second reason for this is that Constraints are the basis for all iOS frame operations, including .frame, and animations (which is why Anima works so well from the looks of it).
I wrote a post on this recently, but as I explain by referencing Apple:
Your problem is that when translatesAutoresizingMaskIntoConstraints is
called, methods like .frame or .frame.size are ignored/overriden
(depending on when you use them, before or after
translatesAutoresizingMaskIntoConstraints). As described by Apple:
Note that the autoresizing mask constraints fully specify the view’s
size and position; therefore, you cannot add additional constraints to
modify this size or position without introducing conflicts. If you
want to use Auto Layout to dynamically calculate the size and position
of your view, you must set this property to false, and then provide a
non ambiguous, nonconflicting set of constraints for the view.
UPDATED
Otherwise, try not to set translatesAutoResizingMaskIntoConstraints to true with these views, by doing that you basically tell your controller to ignore your constraints, and to try to apply constraints based on the .frame or .frame.size or position values set on the UIView. Thus, making your custom constraints obsolete. If by stopping this, you still get the issue, it's probably a constraint value issue, of which i can't give you much more advice without any code unfortunately.
First, you shouldn't set translatesAutoresizingMaskIntoConstraints to true if you have set suitable constraints on a view already. Setting this property to true will add more constraints to the view which leads to conflicts.
The general code for animation with constraints is
aConstraint.constant = 1234
anotherConstraint.isActive = false
thirdConstraint.isActive = true // thirdConstraint replaces anotherConstraint
UIView.animatewithDuration: 0.25) {
self.view.layoutIfNeeded()
}
Hope this helps. ;)
My solution is to remove constraints for that UIViewController and set the frame programmatically as per my needs. This works fine and no need to do this patchy thing with the usage of AutoLayout.

How can I change the height of a button with Swift?

Depending on the height of the screen, I would like to adjust the height of a button in a view. What is the easiest way to do this in Swift?
I tried it in this way and also with CGRectMake() but nothing changed:
self.myButton.frame.size.height = self.myButton.frame.size.height*scrOpt
How can I "update" the frame?
The reason why you see no changes may be because you're using AutoLayout, and the button has some constraints applied to it, and you need to change the height constraint to accomplish what you want.
Edited: Changing frame properties directly seems to be possible in Swift but was not possible in Objective C.
If you are using auto layout, you need to update its height constraint, else update its frame
NSLog(#"%#",NSStringFromCGRect(self.myButton.frame));
NSLog(#"%f",scrOpt);
self.myButton.frame = CGRectMake(self.myButton.frame.origin.x, self.myButton.frame.origin.y, self.myButton.frame.size.width, self.myButton.frame.size.height*scrOpt)
NSLog(#"%#",NSStringFromCGRect(self.myButton.frame));
Edited check this and see what is Print NSLog

iOS: Getting height of views with programatically added constraints as only indicator

Hello there fellow iOS programmers. While creating an app I've ran into a problem I can't seem to find an answer to. Let's lay it out:
I'm creating a UIViewController with a UIScrollView as it's only child. Inside this view I have a UIView, and inside of this there is a list of UIViews with UILabels inside them. As you all know you need to specify a contentSize for a UIScrollView.
The problem is that the list needs to be dynamic with it's content, and I therefore have no way to know the views heights beforehand. I'm adding all views with constraints where the height is set to ">=0".
When I later try to set the height of the UIScrollView I need to either get the height of the UIView that the list is inside, or get the origin.y and height of the last view in the list. This of course needs to be ready by the time the view is displayed to the user.
I've currently tried view.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize), which returned 0; view.systemLayoutSizeFittingSize(UILayoutFittingExpandedSize), which returned 10000; and view.origin.y + view.frame.height, which also returns 0. It seems to me like the constraints haven't taken effect yet.
I've tried setting both constraints and UIScollView.contentSize from viewDidLoad(). I've also tried to set constraints in viewDidLoad and setting contentSize in viewWillAppear; this yielded the same results. Setting constraints in viewWillAppear and setting contentSize in viewDidLoad only caused a crash.
Bottom-line: When should I set up the UIScrollView.contentSize if I want to get view.height or similar methods to return a correct result, while at the same time be ready by the time the user sees the view?
Btw, I'm making this app in Swift, so answers in this language is preferred, but I'm able to translate from Objective-C to Swift; post in whatever suits you best.
Thank you! :)
You say:
As you all know you need to specify a contentSize for a UIScrollView.
No, as TN2154 says, the constraints between the scroll view and its subviews are "interpreted as the content size of the scroll view" (emphasis added). This is a boon, because you no longer have to mess around with contentSize if doing auto-layout. Just set the constraints for the scroll view's subviews and the content size takes care of itself. This leverages the labels' intrinsic size (and make sure that the label's numberOfLines to zero).
The only trick is that it sometimes cannot figure out the correct width of the labels (because the trailing constraint is to the scroll view's content size, it will sometimes make the scroll view a horizontally scrolling one). You can remedy this by either manually setting preferredMaxLayoutWidth or by setting a width constraint between the label and the scroll view's superview.
Personally, while I understand the inclination to add the UIView containers between the scroll view and the labels, I'd suggest losing them unless you need them for some other reason. IMHO, it simply complicates the constraints unnecessarily. It's hairy enough as it is. Obviously, if these containers bear other utility for you, then go ahead and keep them (and they'll work fine), but if you're doing this simply for the sake of the constraints, you might consider eliminating them.

How to properly create a UIButton that resizes to the text length in Xcode 4?

In Xcode 4 you should be able to design UI interfaces that do resize based on their content. Still it looks that the are some missing pieces regarding how to obtain this.
I have a button that is configured in the XIB file to resize to the right and it has plenty of space to do that.
The problem is that it doesn't seam to resize the button when the label is updated.
This can be fixed by adding a [button sizeToFit]; after the label is changed.
Still I am looking for a solution that works without adding this manual step into the code.
I mention that there is enough space to expand the button further, still sizeToFit seams to to enlarge the button but still not enough to fit the entire text.
What am I missing?
[button sizeToFit] didn't work for me, but I've found a way using IB alone (xcode 4.5):
Click on the UIButton
in the Size inspector drag content hugging to 1 (both horizontal and vertical)
drag compression resistance to 999 (for both)
under the UIButton's constraints click on Width and change priority to 250
Do the same for Height
You can use the UIButton's inset to control padding for left/right/top/bottom
You need to call sizeToFit on the button after setting it's title to make it resize to fit the given title.
You can remove the manual step by subclassing UIButton, overriding the setTitle:forControlState: method and implementing the call to sizeToFit in there. Don't forget to call the super implementation, otherwise your title won't be set and bad things will happen.
In XCode 4.5 and above, this can now be done by using 'Auto-layouting / Constraints'.
Major advantages are that:
You don't need to programatically set frames at all!
If done right, you don't need to bother about resetting frames for orientation changes.
Also, device changes needn't bother you (read, no need to code separately for different screen sizes).
A few disadvantages:
Not backward compatible - works only for iOS 6 and above.
Need to get familiarised (but will save time later on).
Coolest thing is we get to focus on declaring an intent such as:
I want these two buttons to be of the same width; or
I need this view to be vertically centered and extend to a max entent of 10 pts from the superview's edge; or even,
I want this button/label to resize according to the label it is displaying!
Here is a simple tutorial to get introduced to auto-layouting:
http://www.raywenderlich.com/20881/beginning-auto-layout-part-1-of-2
For a more detailed look at things, go to:
http://www.techotopia.com/index.php/An_Introduction_to_Auto_Layout_in_iOS_6
It takes some time at first, but it sure looks like it will be well worth the effort.
Cheers!

Resources