UIScrollView does not propagate tap gesture to its children - ios

I am stuck on this and no other question on SO helped me...
I have view controller, which implements UIGestureRecognizerDelegate. There are a few views, one of them is contentView, and inside that contentView, there is a UIScrollView. Also inside that scroll view, there is a scrollContentView, which is simple UIView, but it contains more subviews which I didn't include in code sample just because of space. Everything works fine (after a lot of time), but it looks like no tap gestures are propagated throw UIScrollView to the child view..
I am not using storyboard.
I tried everything, any help would be appreciated.
class MyController: PopoverController, UITableViewDelegate, UIGestureRecognizerDelegate
{
var scrollPane: UIScrollView!
var myContentView: UIView!
var bottomPane: EditOrderItemBottomPaneView!
var quantityPaneView: QuantityPaneView!
var optionsTable: OptionsTableView!
var modificationsTable: ModificationsTableView!
var specialPricingsTable: SpecialPricingsTableView!
override func viewDidLoad()
{
super.viewDidLoad()
categoriesModel = DIContainer.get().getCategoriesModel()
activeOrderModel = DIContainer.get().getActiveOrderModel()
modificationModel = DIContainer.get().getProductModificationsModel()
orderItem = popoverModel.get("orderItem") as! OrderItem!
let category: ProductCategory = categoriesModel.getCategoryById(orderItem.categoryId)!
titleLabel.text = category.name
// scroll view
scrollPane = UIScrollView()
scrollPane.translatesAutoresizingMaskIntoConstraints = false
scrollPane.delegate = self
contentView.addSubview(scrollPane)
// bottom pane
bottomPane = EditOrderItemBottomPaneView()
contentView.addSubview(bottomPane)
contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[scrollView][bottomView]|", options: [], metrics: nil, views: ["scrollView": scrollPane, "bottomView": bottomPane]))
contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[scrollView]|", options: [], metrics: nil, views: ["scrollView": scrollPane]))
contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[bottomView]|", options: [], metrics: nil, views: ["bottomView": bottomPane]))
// scroll content view
myContentView = UIView()
myContentView.translatesAutoresizingMaskIntoConstraints = false
scrollPane.addSubview(myContentView)
scrollPane.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[content]|", options: [], metrics: nil, views: ["content": myContentView]))
scrollPane.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[content]|", options: [], metrics: nil, views: ["content": myContentView]))
contentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[content]|", options: [], metrics: nil, views: ["content": myContentView]))
contentView.addConstraint(NSLayoutConstraint(item: myContentView, attribute: NSLayoutAttribute.Trailing,
relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Trailing,
multiplier: 1, constant: 0))
contentView.addConstraint(NSLayoutConstraint(item: myContentView, attribute: NSLayoutAttribute.Leading,
relatedBy: NSLayoutRelation.Equal, toItem: contentView, attribute: NSLayoutAttribute.Leading,
multiplier: 1, constant: 0))
// quantity pane
quantityPaneView = QuantityPaneView()
myContentView.addSubview(quantityPaneView)
// options table
let optionsDataSource: OrderItemOptionsTableViewDataSource = DIContainer.get().getOrderItemOptionsTableViewDataSource()
optionsDataSource.orderItem = orderItem
if optionsDataSource.getNumberOfOptions() > 0 {
optionsTable = OptionsTableView(delegate: DIContainer.get().getOrderItemOptionsTableViewDelegate(),
dataSource: optionsDataSource, orderItem: orderItem)
myContentView.addSubview(optionsTable)
}
// modifications table
modificationsTable = ModificationsTableView(
delegate: DIContainer.get().getOrderItemModificationsTableViewDelegate(),
dataSource: DIContainer.get().getOrderItemModificationsTableViewDataSource(),
orderItem: orderItem)
myContentView.addSubview(modificationsTable)
// special pricing table
specialPricingsTable = SpecialPricingsTableView(
delegate: DIContainer.get().getOrderItemSpecialPricingsTableViewDelegate(),
dataSource: DIContainer.get().getOrderItemSpecialPricingsTableViewDataSource(),
orderItem: orderItem)
myContentView.addSubview(specialPricingsTable)
var views = [
"quantityPane": quantityPaneView,
"modifications": modificationsTable,
"specialPricings": specialPricingsTable
]
myContentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-25-[quantityPane]-25-|", options: [], metrics: nil, views: views))
myContentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-25-[modifications]-25-|", options: [], metrics: nil, views: views))
myContentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-25-[specialPricings]-25-|", options: [], metrics: nil, views: views))
if optionsDataSource.getNumberOfOptions() > 0 {
views["options"] = optionsTable
myContentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-25-[options]-25-|", options: [], metrics: nil, views: views))
myContentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[quantityPane]-25-[options]-25-[modifications]-25-[specialPricings]", options: [], metrics: nil, views: views))
}
else {
myContentView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[quantityPane]-25-[modifications]-25-[specialPricings]", options: [], metrics: nil, views: views))
}
}
override func viewDidLayoutSubviews()
{
super.viewDidLayoutSubviews()
var h: CGFloat = 0.0
for view: UIView in myContentView.subviews {
h += view.frame.size.height;
}
scrollPane.contentSize = CGSizeMake(myContentView.frame.size.width, h)
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool
{
return true
}
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool
{
if touch.view != scrollPane {
return false
}
return true
}
}

Implement UIGestureRecognizer delegate method.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if (touch.view != yourScrollView) {
return NO;
}
return YES;
}

I realized that the whole screen was designed really badly. I didn't solve the issue, but I reimplemented the whole controller. I still think that it is possible to solve that problem, but there is much easier way.
The point is, that I had more table views inside that scroll content view. But of course, it is possible to create just one table with more sections. Side effect of this would be that that one table view itself is scrollable and so there is no need for using custom UIScrollView.
So for everyone beginning with iOS development, use UITableView with more sections wherever possible.

Related

UIButton inside a UIView subclass is not working, Swift

I've seen similar SO questions, the most promising ones advised to set .isUserInteractionEnabled = true and .bringSubview(toFront: subView) however both these don't seem to work in my case (not sure if I am using it correctly). I am neither able to set the backgroundColor and border for the view.
Please advise where I am going wrong.
I would like to call a function on click of a editButton which is inside a subview.
This is what I get when I run the code:
Here is the code:
class ProfilePhotoView: UIView{
var profileImage = UIImageView()
var editButton = UIButton()
var currentViewController : UIViewController
init(frame: CGRect, viewController : UIViewController){
self.currentViewController = viewController
super.init(frame: frame)
self.isUserInteractionEnabled = true
setup()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setup(){
profileImage.image = #imageLiteral(resourceName: "profilePlaceHolder")
editButton.setTitle("edit", for: .normal)
editButton.setTitleColor(Colors.curieBlue, for: .normal)
editButton.isUserInteractionEnabled = true
editButton.addTarget(self, action: #selector(editPhoto), for: .touchUpInside)
profileImage.translatesAutoresizingMaskIntoConstraints = false
editButton.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(profileImage)
self.addSubview(editButton)
let viewsDict = [ "profileImage" : profileImage,
"editButton" : editButton
] as [String : Any]
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[profileImage]", options: [], metrics: nil, views: viewsDict))
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-10-[profileImage]", options: [], metrics: nil, views: viewsDict))
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[editButton]", options: [], metrics: nil, views: viewsDict))
self.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[profileImage]-10-[editButton]", options: [], metrics: nil, views: viewsDict))
}
func editPhoto(){
Utils.showSimpleAlertOnVC(targetVC: currentViewController, title: "Edit Button Clicked", message: "")
}
}
ViewController using ProfilePhotoView
class ProfilePhotoViewVC: UIViewController {
var profilePhotoView : ProfilePhotoView!
//let imagePickerController = UIImagePickerController() // Initializing imagePicker
//var imagePickerDelegate = ProfilePhotoDelegate()
override func viewDidLoad() {
super.viewDidLoad()
let profilePhotoFrame = CGRect(x: 0, y: 0, width: 300, height: 800)
profilePhotoView = ProfilePhotoView(frame: profilePhotoFrame, viewController: self)
profilePhotoView.isOpaque = false
profilePhotoView.backgroundColor = Colors.lightGrey
profilePhotoView.layer.borderWidth = 1
profilePhotoView.layer.borderColor = Colors.iOSBlue.cgColor
profilePhotoView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(profilePhotoView)
view.bringSubview(toFront: profilePhotoView)
view.isUserInteractionEnabled = true
let viewsDict = [ "profilePhotoView" : profilePhotoView] as [String : Any]
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[profilePhotoView]", options: [], metrics: nil, views: viewsDict))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-10-[profilePhotoView]", options: [], metrics: nil, views: viewsDict))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
As soon as you set this:
profilePhotoView.translatesAutoresizingMaskIntoConstraints = false
your profilePhotoView's width and height get set to 0, and you need to specify them with constraints. Add (==300) and (==800) to your visual formats to set them:
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[profilePhotoView(==300)]", options: [], metrics: nil, views: viewsDict))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-10-[profilePhotoView(==800)]", options: [], metrics: nil, views: viewsDict))
Also, consider using NSLayoutConstraint.activate() to activate the constraints instead of adding them to the view. iOS will add the constraints to the correct views for you. Also, options has a default value of [], so you can leave that off:
NSLayoutConstraint.activate(NSLayoutConstraint.constraints(
withVisualFormat: "H:|-10-[profilePhotoView(==300)]",
metrics: nil, views: viewsDict)
)
NSLayoutConstraint.activate(NSLayoutConstraint.constraints(
withVisualFormat: "V:|-10-[profilePhotoView(==800)]",
metrics: nil, views: viewsDict)
)

Scroll View not working iOS Swift

Below is the code where I am trying to set scroll view to my view controller. Could someone please suggest why I am unable to scroll down the view.
I have a most part of my day trying to resolve this. Any help would be greatly appreciated.
import UIKit
class ScrollViewTestVC: UIViewController {
// FOR SCREEN DIMENSIONS
let screenSize : CGRect = UIScreen.main.bounds
var screenWidth : CGFloat
var screenHeight : CGFloat
var scrollView = UIScrollView()
var contentView = UIView()
required init?(coder aDecoder: NSCoder) {
screenHeight = screenSize.height
screenWidth = screenSize.width
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
// Setting scroll view size
scrollView = UIScrollView(frame: view.bounds)
scrollView.isScrollEnabled = true
let firstName : UILabel = {
let label = UILabel()
label.text = "First Name"
return label
}()
let lastName : UILabel = {
let label = UILabel()
label.text = "Last Name"
return label
}()
let age : UILabel = {
let label = UILabel()
label.text = "Age"
return label
}()
let weight : UILabel = {
let label = UILabel()
label.text = "Weight"
return label
}()
let gender : UILabel = {
let label = UILabel()
label.text = "Gender"
return label
}()
// TEXT FIELDS
let firstNameText : UITextField = {
let tf = UITextField()
tf.placeholder = "Enter first name"
return tf
}()
let lastNameText : UITextField = {
let tf = UITextField()
tf.placeholder = "Enter last name"
return tf
}()
let ageText : UITextField = {
let tf = UITextField()
tf.placeholder = "Enter Age"
return tf
}()
let weightText : UITextField = {
let tf = UITextField()
tf.placeholder = "Enter weight"
return tf
}()
let genderText : UITextField = {
let tf = UITextField()
tf.placeholder = "Enter Gender"
return tf
}()
// ADDING SUB VIEWS
contentView.addSubview(firstName)
contentView.addSubview(lastName)
contentView.addSubview(age)
contentView.addSubview(weight)
contentView.addSubview(gender)
contentView.addSubview(firstNameText)
contentView.addSubview(lastNameText)
contentView.addSubview(ageText)
contentView.addSubview(weightText)
contentView.addSubview(genderText)
// Adding the content view to the scroll view
scrollView.addSubview(contentView)
//self.view.addSubview(contentView)
// Pinning the contentView to the scrollView
pinView(contentView, to: scrollView)
// Adding scroll view to the main view
self.view.addSubview(scrollView)
// Removing default constraints
firstName.translatesAutoresizingMaskIntoConstraints = false
lastName.translatesAutoresizingMaskIntoConstraints = false
age.translatesAutoresizingMaskIntoConstraints = false
weight.translatesAutoresizingMaskIntoConstraints = false
gender.translatesAutoresizingMaskIntoConstraints = false
firstNameText.translatesAutoresizingMaskIntoConstraints = false
lastNameText.translatesAutoresizingMaskIntoConstraints = false
ageText.translatesAutoresizingMaskIntoConstraints = false
weightText.translatesAutoresizingMaskIntoConstraints = false
genderText.translatesAutoresizingMaskIntoConstraints = false
// Views Dict
var viewsDict = [
"firstName" : firstName,
"lastName" : lastName,
"age" : age,
"weight" : weight,
"gender" : gender,
"firstNameText" : firstNameText,
"lastNameText" : lastNameText,
"ageText" : ageText,
"weightText" : weightText,
"genderText" : genderText
]
// Do any additional setup after loading the view.
// SETTING CONSTRAINTS
var space = 100
var edgeSpace = 10
// First Name
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-10-[firstName]", options: [], metrics: nil, views: viewsDict))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-\(edgeSpace)-[firstName]", options: [], metrics: nil, views: viewsDict))
// First Name Text
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[firstName]-5-[firstNameText]", options: [], metrics: nil, views: viewsDict))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-\(edgeSpace)-[firstNameText]|", options: [], metrics: nil, views: viewsDict))
// Last Name
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[firstNameText]-\(space)-[lastName]", options: [], metrics: nil, views: viewsDict))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-\(edgeSpace)-[lastName]", options: [], metrics: nil, views: viewsDict))
// Last Name Text
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[lastName]-5-[lastNameText]", options: [], metrics: nil, views: viewsDict))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-\(edgeSpace)-[lastNameText]|", options: [], metrics: nil, views: viewsDict))
// Age
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[lastNameText]-\(space)-[age]", options: [], metrics: nil, views: viewsDict))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-\(edgeSpace)-[age]", options: [], metrics: nil, views: viewsDict))
// Age Text
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[age]-5-[ageText]", options: [], metrics: nil, views: viewsDict))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-\(edgeSpace)-[ageText]|", options: [], metrics: nil, views: viewsDict))
// Weight
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[ageText]-\(space)-[weight]", options: [], metrics: nil, views: viewsDict))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-\(edgeSpace)-[weight]", options: [], metrics: nil, views: viewsDict))
// Weight Text
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[weight]-5-[weightText]", options: [], metrics: nil, views: viewsDict))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-\(edgeSpace)-[weightText]|", options: [], metrics: nil, views: viewsDict))
// Gender
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[weightText]-\(space)-[gender]", options: [], metrics: nil, views: viewsDict))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-\(edgeSpace)-[gender]", options: [], metrics: nil, views: viewsDict))
// Gender Text
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[gender]-5-[genderText]", options: [], metrics: nil, views: viewsDict))
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-\(edgeSpace)-[genderText]|", options: [], metrics: nil, views: viewsDict))
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
}
// The below function is used to pin one view to another view
public func pinView(_ view: UIView, to scrollView: UIScrollView) {
view.translatesAutoresizingMaskIntoConstraints = false
view.pin(to: scrollView)
}
public func pin(to view: UIView) {
NSLayoutConstraint.activate([
leadingAnchor.constraint(equalTo: view.leadingAnchor),
trailingAnchor.constraint(equalTo: view.trailingAnchor),
topAnchor.constraint(equalTo: view.topAnchor),
bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
}
Your bottommost item needs to be connected to the superview so that the scrollview can compute its height. Add "|":
self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[gender]-5-[genderText]|", options: [], metrics: nil, views: viewsDict))
You have to set the content size of scrollview.
See documentation

subview not showing in scrollview when using visual format constraint

I cannot understand why the blue view is not showing please take a look at my code. When i use view.addSubView(mapView) its shows in the main view but when I do scrollView.addSubView(mapView) it does not show.Everything appear to be correct with the constraint. I not sure why its not working.
import UIKit
class practiceViewController: UIViewController,UIScrollViewDelegate {
override func viewDidLoad() {
var allConstraint = [NSLayoutConstraint]()
let scrollView:UIScrollView = {
let v = UIScrollView()
v.backgroundColor = .red
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
let mapView:UIView = {
let v = UIView()
v.backgroundColor = .blue
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
//views
let views = [
"scrollView":scrollView,
"mapView":mapView
]
//add views
view.addSubview(scrollView)
scrollView.addSubview(mapView)
// constraints
let scrollviewHorizontalConstraint = NSLayoutConstraint.constraints(withVisualFormat: "H:|[scrollView]|", options: [], metrics: nil, views: views)
let scrollviewVerticleConstraint = NSLayoutConstraint.constraints(withVisualFormat: "V:|[scrollView]|", options: [], metrics: nil, views: views)
allConstraint += scrollviewVerticleConstraint
allConstraint += scrollviewHorizontalConstraint
let mapViewHorizontalConstraint = NSLayoutConstraint.constraints(withVisualFormat: "H:|[mapView]|", options: [], metrics: nil, views: views)
let mapViewVerticleConstraint = NSLayoutConstraint.constraints(withVisualFormat: "V:|[mapView]|", options: [], metrics: nil, views: views)
allConstraint += mapViewHorizontalConstraint
allConstraint += mapViewVerticleConstraint
NSLayoutConstraint.activate(allConstraint)
}
}
Your mapView needs a width and height. The scroll view doesn't know what the content size is until you set the size of your content so the scrollview defaults to zero. Try something like this instead:
let mapViewHorizontalConstraint = NSLayoutConstraint.constraints(withVisualFormat: "H:|[mapView(200)]|", options: [], metrics: nil, views: views)
let mapViewVerticleConstraint = NSLayoutConstraint.constraints(withVisualFormat: "V:|[mapView(200)]|", options: [], metrics: nil, views: views)

Center align Labels and images inside UIView programatically with Swift

Im working on an app and came across a problem that I cant seem to solve.
I am making a uiview with labels and images inside it. The content needs to be centered inside the view.
The problem is that the label will hold different lenght texts and the view itself will have different width depending on where it is used.
Here is how it should look:
And here with longer text:
As you can see there should be 1 label to the left, one uiimage in the middle and another label to the right all centered to the middle even though the text length could be different.
This is what I have so far in code. I need to do this programatically if possible. Im running a method to create the button depending on a value.
func cost(cost:Int){
costView = UIView()
costView?.setTranslatesAutoresizingMaskIntoConstraints(false)
self.costView?.clipsToBounds = true
self.addSubview(costView!)
self.costLabel.frame = CGRectMake(0, 0, 60, self.bounds.size.height)
self.costLabel.textAlignment = NSTextAlignment.Right
self.costLabel.textColor = UIColor.whiteColor()
self.costLabel.font = Services.exoFontWithSize(16)
self.costLabel.text = String(cost)
costView?.addSubview(costLabel)
self.costBrainImageView = UIImageView(frame: CGRectMake(0, 0, self.bounds.size.height, self.bounds.size.height))
self.costBrainImageView?.image = Graphics.maskImageNamed("CommonMediumBrain", color: UIColor.whiteColor())
self.costBrainImageView?.contentMode = UIViewContentMode.ScaleAspectFill
costView?.addSubview(costBrainImageView!)
self.label.adjustsFontSizeToFitWidth = true
self.label.setTranslatesAutoresizingMaskIntoConstraints(false)
self.label.numberOfLines = 1
self.label.minimumScaleFactor = 0.20
self.label.textAlignment = NSTextAlignment.Right
self.label.font = Services.exoFontWithSize(20)
//Constraints
var viewsDict = Dictionary <String, UIView>()
viewsDict["label"] = label
viewsDict["brainView"] = costView
self.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"V:|[label]|", options: nil, metrics: nil, views: viewsDict))
self.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"V:|[brainView]|", options: nil, metrics: nil, views: viewsDict))
self.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"H:|-[label]-5-[brainView]-|", options: NSLayoutFormatOptions.AlignAllCenterX, metrics: nil, views: viewsDict))
}
For the moment this breaks since this line
NSLayoutFormatOptions.AlignAllCenterX
'Unable to parse constraint format:
Options mask required views to be aligned on a horizontal edge, which is not allowed for layout that is also horizontal.
H:|-[label]-5-[brainView]-|
If i remove that everything is aligned to the left and not centered but im not sure this is the right way to accomplish what i want to do.
Any clues on how to solve this?
Thanks for any help
Firstly, change .AlignAllCenterX to .AlignAllCenterY, the reason is that"H:|-[label]-5-[brainView]-|" specifies how views position horizontally, you want label and brainView to have the same center Y position.
Secondly, make a subview that contains all 3 views, then center this subview inside the black rectangle. You can use costView as the subview.
Below is some modified code based on your existing code.
costView!.addSubview(label)
//Constraints
var viewsDict = Dictionary <String, UIView>()
viewsDict["label"] = label
viewsDict["brainView"] = costBrainImageView
viewsDict["costLabel"] = costLabel
costView!.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"V:|[label]|", options: nil, metrics: nil, views: viewsDict))
costView!.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"V:|[brainView]|", options: nil, metrics: nil, views: viewsDict))
costView!.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"V:|[costLabel]|", options: nil, metrics: nil, views: viewsDict))
costView!.addConstraints(
NSLayoutConstraint.constraintsWithVisualFormat(
"H:|-[label]-5-[brainView]-5-[costLabel]-|", options: NSLayoutFormatOptions.AlignAllCenterY, metrics: nil, views: viewsDict))
costView!.backgroundColor = UIColor.redColor()
// center costView inside self
let centerXCons = NSLayoutConstraint(item: costView!, attribute: .CenterX, relatedBy: .Equal, toItem: self, attribute: .CenterX, multiplier: 1, constant: 0);
let centerYCons = NSLayoutConstraint(item: costView!, attribute: .CenterY, relatedBy: .Equal, toItem: self, attribute: .CenterY, multiplier: 1, constant: 0);
self.addConstraints([centerXCons, centerYCons])

UISegmentedControl is hidden under the titleBar

i guess i am missing something with the UISegmentedControl and auto layout.
i have a TabbedApplication (UITabBarController), and i created a new UIViewController to act as tab.
to the new view i added UISegmentedControl, and place it to top using auto layout.
i guess i don't understand completely something ,
cause the UISegmentedControl is hiding under the titleBar
. can u help me understand what i am missing ?
thank you .
import Foundation
import UIKit;
class ViewLikes:UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
title = "some title";
var segmentControl:UISegmentedControl = UISegmentedControl(items:["blash", "blah blah"]);
segmentControl.selectedSegmentIndex = 1;
segmentControl.setTranslatesAutoresizingMaskIntoConstraints(false)
self.view.addSubview(segmentControl)
//Set layout
var viewsDict = Dictionary <String, UIView>()
viewsDict["segment"] = segmentControl;
//controls
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[segment]-|",
options: NSLayoutFormatOptions.AlignAllCenterX,
metrics: nil,
views: viewsDict))
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[segment]",
options: NSLayoutFormatOptions(0),
metrics: nil,
views: viewsDict))
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Your top space vertical constraint has to be related to your Top Layout Guide, not to your container margin. The following code should fix this problem:
override func viewDidLoad() {
super.viewDidLoad()
let segmentControl = UISegmentedControl(items:["blash", "blah blah"])
segmentControl.selectedSegmentIndex = 1
segmentControl.setTranslatesAutoresizingMaskIntoConstraints(false)
self.view.addSubview(segmentControl)
//Horizontal constraints
view.addConstraint(NSLayoutConstraint(item: segmentControl, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.topLayoutGuide, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 10))
//Horizontal constraints
let viewsDict = ["segment" : segmentControl]
self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[segment]-|", options: NSLayoutFormatOptions(0), metrics: nil, views: viewsDict))
}
Note that the horizontal constraints setting has also been rewritten.

Resources