Admob Banner at the top of the screen - swift

I want to have the Admob banner at the top of the screen instead of the bottom. This is what i copied from the Admob Documentations.
func addBannerViewToView(_ bannerView: GADBannerView) {
bannerView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(bannerView)
view.addConstraints(
[NSLayoutConstraint(item: bannerView,
attribute: .bottom,
relatedBy: .equal,
toItem: bottomLayoutGuide,
attribute: .top,
multiplier: 1,
constant: 0),
NSLayoutConstraint(item: bannerView,
attribute: .centerX,
relatedBy: .equal,
toItem: view,
attribute: .centerX,
multiplier: 1,
constant: 0)
])
}
I don't know how to work with contraints programmatically. Can anybody please help how I can put the banner at the top. Thanks!

This will work for you.
func addBannerViewToView(_ bannerView: GADBannerView) {
bannerView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(bannerView)
view.addConstraints(
[NSLayoutConstraint(item: bannerView,
attribute: .top,
relatedBy: .equal,
toItem: topLayoutGuide,
attribute: .bottom,
multiplier: 1,
constant: 0),
NSLayoutConstraint(item: bannerView,
attribute: .centerX,
relatedBy: .equal,
toItem: view,
attribute: .centerX,
multiplier: 1,
constant: 0)
])
}

Related

A layout issue (NSLayoutConstraint) in an iOS app

In an iOS app I have an autolayout issue.
The 2 following screenshots show the problem.
The switch (UISwitch object) on the right is displaced horizontally, when it should be fixed. Can anyone see what is happening?
It is true that the string on the left is changing length, but I think (according to the way I have set the constraints up) the font should be resized or the string split in 2 lines; but not the switch displaced.
Here is the relevant swift code:
import UIKit
class My_ViewController: UIViewController {
let xPanel = UILabel(), yPanel = UILabel(),
khToggle = UISwitch(), khLabel = UILabel()
....
override func viewDidLoad() {
super.viewDidLoad()
layOutUI()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
.....
toggleKeepHide(khToggle)
}
func layOutUI() {
for component in [xPanel,yPanel,khLabel,khToggle] {
component.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(component)
}
...........
khLabel.numberOfLines = 0
khLabel.adjustsFontSizeToFitWidth = true
khToggle.addTarget(self,
action: #selector(toggleKeepHide(_:)),
for: .valueChanged)
view.addConstraints([
.........
NSLayoutConstraint(item: khToggle, attribute: .right, relatedBy: .equal,
toItem: view, attribute: .right, multiplier: 1.0, constant: -30.0),
NSLayoutConstraint(item: khToggle, attribute: .top, relatedBy: .equal,
toItem: yPanel, attribute: .bottom, multiplier: 1.0,
constant: 50.0),
NSLayoutConstraint(item: khLabel, attribute: .right, relatedBy: .equal,
toItem: khToggle, attribute: .left, multiplier: 1.0, constant: -23.0),
NSLayoutConstraint(item: khLabel, attribute: .centerY, relatedBy: .equal,
toItem: khToggle, attribute: .centerY, multiplier: 1.0, constant: 0.0),
NSLayoutConstraint(item: khLabel, attribute: .left, relatedBy: .equal,
toItem: view, attribute: .left, multiplier: 1.0, constant: 30.0)])
}
#objc func toggleKeepHide(_ sender: UISwitch) {
if sender.isOn {khLabel.text = "Hide this object from the wyxoug list."}
else {khLabel.text = "Keep this object in the wyxoug list."}
}
}
You haven't provided sufficient information to reproduce the problem. Here's a reduction of your code, in my view controller's viewDidLoad (I eliminated everything but the label and the switch, fixed your left and right (you should never use those), and changed the alignment between the two views to top instead of center):
khToggle = UISwitch()
khToggle.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(khToggle)
khLabel = UILabel()
khLabel.text = String(repeating: "word ", count: 40)
khLabel.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(khLabel)
// Do any additional setup after loading the view.
khLabel.numberOfLines = 0
view.addConstraints([
NSLayoutConstraint(item: khToggle!, attribute: .trailing, relatedBy: .equal,
toItem: view, attribute: .trailing, multiplier: 1.0, constant: -30.0),
NSLayoutConstraint(item: khToggle!, attribute: .top, relatedBy: .equal,
toItem: view, attribute: .top, multiplier: 1.0,
constant: 50.0),
NSLayoutConstraint(item: khLabel!, attribute: .trailing, relatedBy: .equal,
toItem: khToggle, attribute: .leading, multiplier: 1.0, constant: -23.0),
NSLayoutConstraint(item: khLabel!, attribute: .top, relatedBy: .equal,
toItem: khToggle, attribute: .top, multiplier: 1.0, constant: 0.0),
NSLayoutConstraint(item: khLabel!, attribute: .leading, relatedBy: .equal,
toItem: view, attribute: .leading, multiplier: 1.0, constant: 30.0)])
The result displays fine; there are no constraint conflicts or ambiguities, and it looks as one would expect:
The horizontal constraints for the label and the toggle are competing against each other.
(If you step in to Xcode's visual debugger, you'll find that there is a warning: the UISwitch instance has an ambiguous width and horizontal position.)
Solution
You have provided absolute values to AutoLayout, and it cannot resolve the requirements. To fix this, introduce some flexibility in to the requirements by setting the compression resistance of the label to a lower value:
khLabel.setCompressionResistance(.defaultLow, for: .horizontal)

UIScrollView with NSLayoutConstraint

UIScrollView is not scrolling the subviews but it does show a scroll-bar.
Here is what I am trying to do
class SetupViewController: UIViewController {
let scrollView = UIScrollView()
let pageLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
self.setupViews()
self.setupConstraints()
self.setText()
}
func setupViews() {
self.scrollView.backgroundColor = .red
self.scrollView.translatesAutoresizingMaskIntoConstraints = false
// Page Label
self.pageLabel.font = UIFontLocalized(englishFontSize: 22, arabicFontSize: 22)
self.pageLabel.textAlignment = .center
self.pageLabel.translatesAutoresizingMaskIntoConstraints = false
}
func setupConstraints() {
// Add To Sub Views
self.view.addSubview(self.pageLabel)
self.view.addSubview(self.scrollView)
// Page Label
NSLayoutConstraint(item: self.pageLabel, attribute: .top, relatedBy: .equal, toItem: self.topLayoutGuide, attribute: .bottom, multiplier: 1.0, constant: 30.0).isActive = true
NSLayoutConstraint(item: self.pageLabel, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1.0, constant: 20.0).isActive = true
NSLayoutConstraint(item: self.pageLabel, attribute: .width, relatedBy: .equal, toItem: self.view, attribute: .width, multiplier: 1.0, constant: -40.0).isActive = true
NSLayoutConstraint(item: self.pageLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 36.0).isActive = true
// Scroll View
NSLayoutConstraint(item: self.scrollView, attribute: .top, relatedBy: .equal, toItem: self.line1, attribute: .bottom, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: self.scrollView, attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leading, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: self.scrollView, attribute: .width, relatedBy: .equal, toItem: self.view, attribute: .width, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: self.scrollView, attribute: .height, relatedBy: .equal, toItem: self.view, attribute: .height, multiplier: 1.0, constant: -100.0).isActive = true
self.scrollView.contentSize.height = 2000
// NSLayoutConstraint for rest of elements are removed in this example code.
}
}
I can confirm UIScrollView is added in the view because I checked by giving background red color to scrollview and it does show the background red color in correct position. My issue is the subviews does not move only the scroll bar is moving.
What could be the possible issue here?
Note: NSLayoutConstraint exist for all UIKit elements, I have not added it in the code.
I got this issue sorted our. As pointed out in the comment, the issue was related to superview in constraint which was set to self.view changing it to self.scrollView solved the issue.

Adding constraints to in image within scrollView breaks panning

Using swift 3.0 iOS 10.x
Need an image within a scrollView to stick to the sides when I go from landscape to portrait and put this NSLayout rules into place.
let imageViewRight = (NSLayoutConstraint(item: self.image2P, attribute: .right, relatedBy: .equal, toItem: self.view, attribute: .right, multiplier: 1.0, constant: 0))
let imageViewLeft = (NSLayoutConstraint(item: self.image2P, attribute: .left, relatedBy: .equal, toItem: self.view, attribute: .left, multiplier: 1.0, constant: 0))
let imageViewTop = NSLayoutConstraint(item: self.image2P, attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .top, multiplier: 1, constant: 0)
let imageViewBot = NSLayoutConstraint(item: self.image2P, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1, constant:0)
self.view.addConstraints([imageViewBot,imageViewTop,imageViewRight,imageViewLeft])
NSLayoutConstraint.activate([imageViewBot,imageViewTop,imageViewRight,imageViewLeft])
They work, but of course if I zoom into the image I find they break panning.
I thought I might be able to get around it by activating and deactiving them, but even if I simply add them it breaks... is this correct behaviour?

Swift UIWebView constraints full screen

I have these constraints for my UIWebView:
let horizontalConstraint = NSLayoutConstraint(item: webview, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)
view.addConstraint(horizontalConstraint)
let verticalConstraint = NSLayoutConstraint(item: webview, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: view, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0)
view.addConstraint(verticalConstraint)
let widthConstraint = NSLayoutConstraint(item: webview, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 100)
view.addConstraint(widthConstraint)
let heightConstraint = NSLayoutConstraint(item: webview, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: 100)
view.addConstraint(heightConstraint)
My question is, how do I get the width and height constraint to be full device screen? I have to do this programmatically
Use this constraints for a full screen mode:
let topConst = NSLayoutConstraint(item: self.webView, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.top, multiplier: 1, constant: 0)
let botConst = NSLayoutConstraint(item: self.webView, attribute: NSLayoutAttribute.bottom, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.bottom, multiplier: 1, constant: 0)
let leftConst = NSLayoutConstraint(item: self.webView, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.leading, multiplier: 1, constant: 0)
let rigthConst = NSLayoutConstraint(item: self.webView, attribute: NSLayoutAttribute.trailing, relatedBy: NSLayoutRelation.equal, toItem: self.view, attribute: NSLayoutAttribute.trailing, multiplier: 1, constant: 0)
NSLayoutConstraint.activate([topConst,botConst,leftConst,rigthConst])
self.webView.translatesAutoresizingMaskIntoConstraints = false
webview is the view that I wanted to be in full screen. Don't forget to set the translatesAutoresizingMaskIntoConstraints to false after activate the constraints.

Auto-Layout fit to parent via code in Swift

I have a view i'm creating via code and adding to another view as subview.
The new superview can change it's frame over time and I want the newly created subview to change it's frame accordingly.
How can I do that using Auto-Layout via code in Swift?
Here is an example:
let view = UIView() // existing view
let subview = UIView()
subview.setTranslatesAutoresizingMaskIntoConstraints(false)
view.addSubview(subview)
view.addConstraint(NSLayoutConstraint(item: subview, attribute: .Top, relatedBy: .Equal, toItem: view, attribute: .Top, multiplier: 1.0, constant: 0.0))
view.addConstraint(NSLayoutConstraint(item: subview, attribute: .Leading, relatedBy: .Equal, toItem: view, attribute: .Leading, multiplier: 1.0, constant: 0.0))
view.addConstraint(NSLayoutConstraint(item: view, attribute: .Bottom, relatedBy: .Equal, toItem: subview, attribute: .Bottom, multiplier: 1.0, constant: 0.0))
view.addConstraint(NSLayoutConstraint(item: view, attribute: .Trailing, relatedBy: .Equal, toItem: subview, attribute: .Trailing, multiplier: 1.0, constant: 0.0))
iOS 13, swift 5
First, you add this code
subview.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(subview)
Then, there are two ways of doing this in newer versions of iOS.
With NSLayoutConstraint class
NSLayoutConstraint(item: subview, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: subview, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: subview, attribute: .left, relatedBy: .equal, toItem: view, attribute: .left, multiplier: 1, constant: 0).isActive = true
NSLayoutConstraint(item: subview, attribute: .right, relatedBy: .equal, toItem: view, attribute: .right, multiplier: 1, constant: 0).isActive = true
With NSLayoutAnchor class (less verbose)
subview.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
subview.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
subview.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
subview.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
Either way, on iOS 8 and later Apple recommends using isActive() instead of adding constraints directly to a view.
Additionally, I believe the purpose of the NSLayoutAnchor method is to be more concise and readable compared to NSLayoutConstraint.
As #rjobidon mentioned you should use following code (Swift3)
let view = UIView() // existing view
let subview = UIView()
subview.setTranslatesAutoresizingMaskIntoConstraints(false)
view.addSubview(subview)
NSLayoutConstraint(item: subview, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: subview, attribute: .leading, relatedBy: .equal, toItem: view, attribute: .leading, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: view, attribute: .bottom, relatedBy: .equal, toItem: subview, attribute: .bottom, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: view, attribute: .trailing, relatedBy: .equal, toItem: subview, attribute: .trailing, multiplier: 1.0, constant: 0.0).isActive = true
You can also activate the constraints like that :
let view = UIView() // existing view
let subview = UIView()
subview.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(subview)
NSLayoutConstraint.activate([
view.leadingAnchor.constraint(equalTo: subview.leadingAnchor),
view.trailingAnchor.constraint(equalTo: subview.trailingAnchor),
view.topAnchor.constraint(equalTo: subview.topAnchor),
view.bottomAnchor.constraint(equalTo: subview.bottomAnchor)
])