Can't change a labels coordinates in viewDidAppear() method (swift) - ios

I am trying to change the position of a label in my viewDidAppear() method using the following code:
self.StartTextLabel.text = self.starttext
self.StartTextLabel.center.x = ChangeStart.center.x
The text in the label changes just find but the labels position does not change.
I have tried doing this with and without the code being within
dispatch_async(dispatch_get_mail_queue()){
}
The label was originally build in the IntefaceBuilder and is linked to my controller via
#IBOutlet weak var StartTextLabel: UILabel!
Does anyone have any idea why the label is not moving?
Thanks

Related

Add label to Image in Swift

Im new to swift and working on app which displays number of unread messages like below image within the app
Counter will increase/decreases as the new messages gets added/read
In order to display that, I have Image with mail icon and wanted to add that green label as badge which shows the number of unread messages
I was thinking to add circular label to image but couldnt figure out how to add that or find any references. Please assist
I was thinking to add circular label to image but couldnt figure out
how to add that or find any references. Please assist.
Welcome to Stackoverflow. There are lots of resources out there on how to round a view, like: https://www.appcoda.com/ios-programming-circular-image-calayer/
You are correct, one way to do what you want is to add a circular label. That's it. Now how to add a circular label? You round the corner of your view by giving its cornerRadius the half of its height.
Position the label to your desired position (with constraints) referencing your message icon.
For example:
class ViewController: UIViewController {
#IBOutlet weak var label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Corner radius to 25 height / 2
self.label.layer.cornerRadius = 12.5
self.label.clipsToBounds = true
// Border
self.label.layer.borderWidth = 2
self.label.layer.borderColor = UIColor.black.cgColor
}
}
Result:

Remove empty space of UILabel with autolayout

I am trying to create a UIView in a library project and use it in my application. I have added auto layout constraints as follows:
But it produces the following result:
The labels have numOfLines as 0 but still, empty labels are displaying empty space.
I have only given the height of the white view in the center (56px)
Edit:
I am using the view from library as following:
One solution with Storyboard, where UILabel heights are dynamic based on its's text,
Or,
you can try using NSLayoutConstraint for the UILabel hights, for the ones you want to hide when the value is not there for the label,
#IBOutlet weak var errorLabelHeight: NSLayoutConstraint!
then,
if errorLabel.text.isEmpty {
errorLabelHeight.isActive = true
errorLabelHeight.constant = 0
} else {
errorLabelHeight.active = false
//works as usual
}
view.layoutIfNeeded()

Xcode/IB - Autolayout, multiple Containers View and Scroll View

I am trying to build an interface with the IB under Xcode with some Containers View.
I will try to do my best to explain the problem:
I have a main scene which contains two controllers. The first one, at the top of the scene, contains a "Last Post View", which retrieves the last post from a Wordpress website and displays the cover image, the post's date and the title.
The second one contains a Collection View which leads to other views.
Functionally and independently, everything seems to work fine. The problem is that I can not figure how to make work this "stack" with autolayout and fit on portrait and landscape modes and different devices.
Here is my Storyboard
The Home Controller's constraints
The Last Post View's constraints
The Collection View's constraints
..and finally, what I get
After hours of searching and attempts, I found that the Scroll View, contained in my Home Controller, must have only one direct child. But I don't know how to put the different constraints. Plus, I always get the message: Scrollable content size is ambiguous for "Scroll View".
Another problem that I have, is when I am in landscape mode, I can't scroll the "whole view". At best, I can scroll the Collection View only (when I can display it) but not the entire screen.
(Maybe it can help if I said that I am using Swift 2)
Does anyone have a suggestion? It will be much appreciated!
Many thanks!
EDIT 1
I tried to apply the Xingou's solution and I think I am quite close the goal but I obviously miss something.
Here is my HomeViewController
class HomeViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var containerViewHeightConstrait: NSLayoutConstraint!
#IBOutlet weak var lastPostContainerView: UIView!
#IBOutlet weak var scrollContainerView: UIView!
#IBOutlet weak var mainCollectionContainerView: UIView!
/*************************/
/***** VIEW DID LOAD *****/
/*************************/
override func viewDidLoad() {
super.viewDidLoad()
self.automaticallyAdjustsScrollViewInsets = false
self.lastPostContainerView.setNeedsDisplay()
self.mainCollectionContainerView.setNeedsDisplay()
self.containerViewHeightConstrait.constant = UIScreen.mainScreen().bounds.height - 64
//END viewDidLoad
}
...
/********************************/
/***** SET CONTAINER HEIGHT *****/
/********************************/
func needSetContainerHeight( height: CGFloat ) {
self.containerViewHeightConstrait.constant = height + lastPostContainerView.bounds.height + 200
self.scrollView.contentSize.height = height + lastPostContainerView.bounds.height + 200
print( "View Height Constrait \( self.containerViewHeightConstrait.constant )" )
print( "Scroll View Height \( self.scrollView.contentSize.height )" )
//END needSetContainerHeight
}
...
...and my MainCollectionController
class MainCollectionViewController: UICollectionViewController {
/*************************/
/***** VIEW DID LOAD *****/
/*************************/
override func viewDidLoad() {
super.viewDidLoad()
collectionView!.autoresizingMask = [ .FlexibleWidth ]
//END viewDidLoad
}
/****************************************/
/****************************************/
/***************************/
/***** VIEW DID APPEAR *****/
/***************************/
override func viewDidAppear( animated: Bool ) {
super.viewDidAppear( animated )
( self.parentViewController as! HomeViewController ).needSetContainerHeight( self.collectionView!.contentSize.height )
//END viewDidAppear
}
...
If I well understood what was proposed, here is how constraints should look like :
(Main) View
Scroll View
Subviews Container
Last Post Container
Collection Container
List of all constraints
... and what I get
Portrait
Landscape
I made a few tests with different extra constraints and I found out that I had to tell the Scroll View to fill its whole parent to display something on the screen (otherwise, I just get the red background).
Another thing is if I add a constraint for the space between Last Post Container and Collection Container, things are "well" positioned but I cannot click on the collection's cells anymore. But, if I don't add this constraint, things are more messy (for example, the collection view overlaps the post view), but I am able to click on the cells.
Unfortunately, the screen seems to be cropped and there are some differences when I rotate the screen. But I think I have to recompute the heights when the device is rotated (am I right?). The margin at the top of screen still here, but not always: it depends in which mode I started the app and how many rotation I do.
Another thing I forgot to mention, is the last post is asynchronously retrieved. So, the cover image, which has a variable size, is displayed after the main screen is displayed. I moved this in the AppDelegate - didFinishLaunchingWithOptions and stocked the post in the Notification Center but unfortunately, there's still some delay.
Any suggestions? :)
SOLUTION
Like Xingou said, it is far easier to use the header section of the collection view (Accessories / Section Header).
you need to solve the following thing:
in you home sense, viewdidload , add the following code:
self.automaticallyAdjustsScrollViewInsets = false
this can make the red area between navagationbar and you picture disappear.
fixed the Scrollable content size is ambiguous for "Scroll View":
this is because the scrollview did not know the content size it would show。you need reset the constrain of the view( the two container view's super view ),i will call it scrollcontainerview:
scrollcontainerview.leading = scrollview.leading
scrollcontainerview.trailing = scrollview.trailing
scrollcontainerview.top = scrollview.top
scrollcontainerview.bottom = scrollview.bottom
scrollcontainerview.width = self.view.width
scrollcontainerview.height = 603 //we will chang this value through code
now the "the Scrollable content size is ambiguous for "Scroll View"" error should be disappeared.
change the scrollcontainerview.height in code :
in you home scene, drag the scrollcontainerview.height constraint into you view controller,and chang it to fit the screen:
#IBOutlet weak var contianerViewHeightConstrait:
NSLayoutConstraint!
override func viewDidLoad() {
super.viewDidLoad()
self.automaticallyAdjustsScrollViewInsets = false
//because we set the height at const 603,but height is different on different device,so we need chang it to the correct value
contianerViewHeightConstrait.constant = UIScreen.mainScreen().bounds.height - 64
}
and now you can see the two container view fill the screen。
need scroll the whole content, not only the collection view:
to solve this problem ,you need assign a correct height to the scrollview.contentsize.height .
in you collection view controller:
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
(self.parentViewController as! HomeScenceViewController).needSetContainerHeight(self.collectionView.contentSize.height)
}
then add a method in HomeScenceViewController
// set the containerview and scrollview height
func needSetContainerHeight(height:CGFloat){
//the 200 is your first container view's height
contianerViewHeightConstrait.constant = height + 200
scrollview.contentSize.height = height + 200
}
and now you should can scroll the whole content

Position UIView programatically not working - stuck to storyboard positioning

I have the following view with the following constraints:
#IBOutlet weak var square1ViewOutlet: UIView!
Which is inserted inside the following view using the storyboard:
#IBOutlet weak var holderView: UIView!
My problem is that I am not being able to override the positioning of square1ViewOutlet established by the storyboard. The following code does not have any effect. I've tried some variations as bellow, but nothing works and the view is really stuck to previous storyboard constraints. I am calling this with my viewDidLoad method.
square1ViewOutlet.frame.origin.y = self.holderView.frame.origin.y + 20
square1ViewOutlet.frame.origin.x = self.holderView.frame.origin.x + 20
square1ViewOutlet.frame = CGRectOffset(CGRect(origin: square1ViewOutlet.frame.origin, size: square1ViewOutlet.frame.size), 20, 20)
square1ViewOutlet.center = CGPointMake(150, 150)
square1ViewOutlet.frame = CGRectMake( 100, 200, square1ViewOutlet.frame.size.width, square1ViewOutlet.frame.size.height )
Any idea what am I doing wrong here?
When you use autolayout and you try to change frame dimensions or positions like your code, instead to correct the correct constraints involved, you can disable you constraints effect causing warnings and unexpected view dimensions and movements.
The correct way to do it is to link the constraints as IBOutlets in your code:
#IBOutlet weak var customViewTopConstraint: NSLayoutConstraint
#IBOutlet weak var customViewHeightConstraint: NSLayoutConstraint
#IBOutlet weak var customViewLeadingConstraint: NSLayoutConstraint
#IBOutlet weak var customViewWidthConstraint: NSLayoutConstraint
And work with these properties changing it's constant value (.constant).
These rules are valid for all the code where you have to change frame dimensions, so check all your code and change it to a constraints work.
Can you please try that code inside your viewDidAppear() method. please go to the link below iOS UIViewController Lifecycle.
Since you have placed your code inside viewDidLoad method, that may be the reason your frames are not applied.
If this not worked please try layoutIfNeeded method for your view after the frames are set. layoutIfNeeded forces the receiver to layout its subviews immediately if required.
By this way you can set your frames for your views. But doing this way will alter your constraints that you had set in your xib file. If you really want to change your view frames, then best way will be create outlet for your constraints and change the values for that constraints. Hope this will help :)

Xcode; Set a autolayout constraint to a defined variable value

Is it possible to define a variable, and set a constraints constant value to that variable?
Thereby making it possible to change many constraints by just changing the variable. I think I saw someone do this directly from interface builder ones?
EDIT:
There is a constraint between each label. I need a method to change all of these constraints, so they get a the same value. Is this possible?
If I use a outlet collection, I will have to iterate through all the constraints, and change the value for each. I'm looking for a method like this:
// SEUDO!!
lineSeperationWidth = 31 // changes all 4 constraints.
The NSLayoutContraints are all separate objects, and Xcode provides no way to set the constant value of multiple constraints with the same variable. The closest you can get is to use an #IBOutlet collection and then use the didSet property observer for your variable holding the common space value to update each of the constraints in the collection.
Here is an example I created which spaces out the labels based upon a random value that I set to the space property each time the Go button is pressed:
class ViewController: UIViewController {
#IBOutlet var spacers: [NSLayoutConstraint]!
var space: CGFloat = 20.0 {
didSet {
spacers.forEach { $0.constant = space }
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func spaceOut(sender: AnyObject) {
// set space to a random value
space = CGFloat(arc4random_uniform(30)) + 20.0
}
}
Each of the vertical space constraints between the labels is connected to the #IBOutlet collection spacers. Here is what the Connections Inspector shows:
Here it is in action:
Yes it is! You can use the document outline view to find the constraint you want to use as a variable. Once you have it, CTRL + Drag from the constraint in the document outline view to your code to make the outlet. Then you can change the constraints in code by using self.constraint.constant = 31.
To space all the views out equally, you can put UILayoutGuides in between each of the labels and constrain all their heights to be equal. Then you can change the height of one of the layout guides and they will all change to match it.

Resources