如何在单击按钮时在一个视图控制器中正确启用和禁用约束
How to properly enable and disable constraint in one view controller on button click
我在 Storyboard 上有一个 UIView 作为 ViewController 的子视图,我在该视图中有一些字段,必须在单击按钮时更改其位置。所以我改变了,所以我为每个 FiledsView 创建了一个出口,并以编程方式给了它们约束,但问题是当我点击其他按钮时,它们相互重叠和冲突。
这是我要制作的布局
这里我把所有字段放在另一个视图中
这是代码
import UIKit
class AddOfferTabViewController: UIViewController {
@IBOutlet weak var formBaseView: UIView!
@IBOutlet weak var titleFieldView: RoundView!
@IBOutlet weak var descriptionView: RoundView!
@IBOutlet weak var pointsView: RoundView!
@IBOutlet weak var startEndDateStackView: UIStackView!
@IBOutlet weak var maxCharLimitStackView: UIStackView!
@IBOutlet weak var amountView: RoundView!
@IBOutlet weak var textViewDescription: TextViewWithPlaceholder!
@IBOutlet weak var textFieldAmount: UITextField!
var buttonClicked:String!
override func viewDidLoad() {
super.viewDidLoad()
self.tabBarController?.tabBar.isHidden = true
// setupCashDiscountView(isLayoutActive: true)
setupFreebeView(isLayoutActive: true)
}
@IBAction func addOfferButtonsActions(_ sender: UIButton) {
switch sender.tag {
case 1: //FreeBe
print("Freebe")
buttonClicked = "Freebe"
setupCashDiscountView(isLayoutActive: false)
setupPercentDiscountView(isLayoutActive: false)
setupFreebeView(isLayoutActive: true)
case 2: //Cash Discount
print("Cash Discount")
buttonClicked = "Cash"
setupFreebeView(isLayoutActive: false)
setupPercentDiscountView(isLayoutActive: false)
setupCashDiscountView(isLayoutActive: true)
case 3: //% Discount
print("% Discount")
buttonClicked = "percent"
setupFreebeView(isLayoutActive: false)
setupCashDiscountView(isLayoutActive: false)
setupPercentDiscountView(isLayoutActive: true)
default:
print("there is something wrong")
}
}
//MARK:Setup FreebeView
func setupFreebeView(isLayoutActive:Bool){
amountView.isHidden = true
textViewDescription.placeholderText = "Any T&C"
setupInputFields(fieldView: titleFieldView, topConstraints: formBaseView.topAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 8, height: 44, isActive: isLayoutActive) //Title Input Field
setupInputFields(fieldView: descriptionView, topConstraints: titleFieldView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, height: 95, isActive: isLayoutActive) //Description View
setupMaxCharStackView(formStackView: maxCharLimitStackView, topConstraints: descriptionView.bottomAnchor, trailingSpace: 0, topSpace: 10, isActive: isLayoutActive) //Character Limit View
setupInputFields(fieldView: pointsView, topConstraints: descriptionView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 40, height: 44, isActive: isLayoutActive) //PointsView
setupStartEndDateStackView(formStackView: startEndDateStackView, topConstraints: pointsView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, isActive: isLayoutActive) //StartDate Endate
}
//MARK:Setup CashDiscount
func setupCashDiscountView(isLayoutActive:Bool){
amountView.isHidden = false
textViewDescription.placeholderText = "Description"
setupInputFields(fieldView: amountView, topConstraints: formBaseView.topAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 8, height: 44, isActive: isLayoutActive) //Amount View
setupInputFields(fieldView: pointsView, topConstraints: amountView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, height: 44, isActive: isLayoutActive) //Points View
setupStartEndDateStackView(formStackView: startEndDateStackView, topConstraints: pointsView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, isActive: isLayoutActive) //StartDate Endate
setupInputFields(fieldView: titleFieldView, topConstraints: startEndDateStackView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, height: 44, isActive: isLayoutActive) //Title View
setupInputFields(fieldView: descriptionView, topConstraints: titleFieldView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, height: 95, isActive: isLayoutActive) //Description View
setupMaxCharStackView(formStackView: maxCharLimitStackView, topConstraints: descriptionView.bottomAnchor, trailingSpace: 0, topSpace: 10, isActive: isLayoutActive) //Character Limit View
}
//MARK:Setup % Discount
func setupPercentDiscountView(isLayoutActive:Bool){
amountView.isHidden = false
textViewDescription.placeholderText = "Description"
setupInputFields(fieldView: amountView, topConstraints: formBaseView.topAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 8, height: 44, isActive: isLayoutActive) //Amount View
setupInputFields(fieldView: pointsView, topConstraints: amountView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, height: 44, isActive: isLayoutActive) //Points View
setupStartEndDateStackView(formStackView: startEndDateStackView, topConstraints: pointsView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, isActive: isLayoutActive) //StartDate Endate
setupInputFields(fieldView: titleFieldView, topConstraints: startEndDateStackView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, height: 44, isActive: isLayoutActive) //Title View
setupInputFields(fieldView: descriptionView, topConstraints: titleFieldView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, height: 95, isActive: isLayoutActive) //Description View
setupMaxCharStackView(formStackView: maxCharLimitStackView, topConstraints: descriptionView.bottomAnchor, trailingSpace: 0, topSpace: 10, isActive: isLayoutActive) //Character Limit View
}
//MARK: SetupInputFields function
func setupInputFields(fieldView:UIView,topConstraints:NSLayoutAnchor<NSLayoutYAxisAnchor>,leadingSpace:CGFloat,trailingSpace:CGFloat,topSpace:CGFloat,height:CGFloat,isActive:Bool){
fieldView.translatesAutoresizingMaskIntoConstraints = false //Make it false for working of constraints
fieldView.topAnchor.constraint(equalTo: topConstraints,constant: topSpace).isActive = isActive
fieldView.leadingAnchor.constraint(equalTo: formBaseView.leadingAnchor,constant: leadingSpace).isActive = isActive
fieldView.trailingAnchor.constraint(equalTo: formBaseView.trailingAnchor,constant: trailingSpace).isActive = isActive
fieldView.heightAnchor.constraint(equalToConstant: height).isActive = isActive
// fieldView.layoutIfNeeded()
}
//MARK: Setup MaxCharacter StackView function
func setupMaxCharStackView(formStackView:UIStackView,topConstraints:NSLayoutAnchor<NSLayoutYAxisAnchor>,trailingSpace:CGFloat,topSpace:CGFloat,isActive:Bool){
formStackView.translatesAutoresizingMaskIntoConstraints = false //Make it false for working of constraints
formStackView.topAnchor.constraint(equalTo: topConstraints,constant: topSpace).isActive = isActive
formStackView.trailingAnchor.constraint(equalTo: formBaseView.trailingAnchor,constant: trailingSpace).isActive = isActive
}
//MARK: Setup StartDate EndDate StackView function
func setupStartEndDateStackView(formStackView:UIStackView,topConstraints:NSLayoutAnchor<NSLayoutYAxisAnchor>,leadingSpace:CGFloat? = nil,trailingSpace:CGFloat,topSpace:CGFloat,isActive:Bool){
formStackView.translatesAutoresizingMaskIntoConstraints = false //Make it false for working of constraints
formStackView.topAnchor.constraint(equalTo: topConstraints,constant: topSpace).isActive = isActive
formStackView.leadingAnchor.constraint(equalTo: formBaseView.leadingAnchor,constant: leadingSpace!).isActive = isActive
formStackView.trailingAnchor.constraint(equalTo: formBaseView.trailingAnchor,constant: trailingSpace).isActive = isActive
}
}
问题是每次单击案例的按钮 1 时都会触发,最终会调用 setupInputFields
并导致重新添加可能与旧约束冲突的新约束,因此要么访问旧约束并删除它们,要么创建 2 个可能的变体数组并使用 activate/deactivate
我在 Storyboard 上有一个 UIView 作为 ViewController 的子视图,我在该视图中有一些字段,必须在单击按钮时更改其位置。所以我改变了,所以我为每个 FiledsView 创建了一个出口,并以编程方式给了它们约束,但问题是当我点击其他按钮时,它们相互重叠和冲突。
这是我要制作的布局
这里我把所有字段放在另一个视图中
这是代码
import UIKit
class AddOfferTabViewController: UIViewController {
@IBOutlet weak var formBaseView: UIView!
@IBOutlet weak var titleFieldView: RoundView!
@IBOutlet weak var descriptionView: RoundView!
@IBOutlet weak var pointsView: RoundView!
@IBOutlet weak var startEndDateStackView: UIStackView!
@IBOutlet weak var maxCharLimitStackView: UIStackView!
@IBOutlet weak var amountView: RoundView!
@IBOutlet weak var textViewDescription: TextViewWithPlaceholder!
@IBOutlet weak var textFieldAmount: UITextField!
var buttonClicked:String!
override func viewDidLoad() {
super.viewDidLoad()
self.tabBarController?.tabBar.isHidden = true
// setupCashDiscountView(isLayoutActive: true)
setupFreebeView(isLayoutActive: true)
}
@IBAction func addOfferButtonsActions(_ sender: UIButton) {
switch sender.tag {
case 1: //FreeBe
print("Freebe")
buttonClicked = "Freebe"
setupCashDiscountView(isLayoutActive: false)
setupPercentDiscountView(isLayoutActive: false)
setupFreebeView(isLayoutActive: true)
case 2: //Cash Discount
print("Cash Discount")
buttonClicked = "Cash"
setupFreebeView(isLayoutActive: false)
setupPercentDiscountView(isLayoutActive: false)
setupCashDiscountView(isLayoutActive: true)
case 3: //% Discount
print("% Discount")
buttonClicked = "percent"
setupFreebeView(isLayoutActive: false)
setupCashDiscountView(isLayoutActive: false)
setupPercentDiscountView(isLayoutActive: true)
default:
print("there is something wrong")
}
}
//MARK:Setup FreebeView
func setupFreebeView(isLayoutActive:Bool){
amountView.isHidden = true
textViewDescription.placeholderText = "Any T&C"
setupInputFields(fieldView: titleFieldView, topConstraints: formBaseView.topAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 8, height: 44, isActive: isLayoutActive) //Title Input Field
setupInputFields(fieldView: descriptionView, topConstraints: titleFieldView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, height: 95, isActive: isLayoutActive) //Description View
setupMaxCharStackView(formStackView: maxCharLimitStackView, topConstraints: descriptionView.bottomAnchor, trailingSpace: 0, topSpace: 10, isActive: isLayoutActive) //Character Limit View
setupInputFields(fieldView: pointsView, topConstraints: descriptionView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 40, height: 44, isActive: isLayoutActive) //PointsView
setupStartEndDateStackView(formStackView: startEndDateStackView, topConstraints: pointsView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, isActive: isLayoutActive) //StartDate Endate
}
//MARK:Setup CashDiscount
func setupCashDiscountView(isLayoutActive:Bool){
amountView.isHidden = false
textViewDescription.placeholderText = "Description"
setupInputFields(fieldView: amountView, topConstraints: formBaseView.topAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 8, height: 44, isActive: isLayoutActive) //Amount View
setupInputFields(fieldView: pointsView, topConstraints: amountView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, height: 44, isActive: isLayoutActive) //Points View
setupStartEndDateStackView(formStackView: startEndDateStackView, topConstraints: pointsView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, isActive: isLayoutActive) //StartDate Endate
setupInputFields(fieldView: titleFieldView, topConstraints: startEndDateStackView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, height: 44, isActive: isLayoutActive) //Title View
setupInputFields(fieldView: descriptionView, topConstraints: titleFieldView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, height: 95, isActive: isLayoutActive) //Description View
setupMaxCharStackView(formStackView: maxCharLimitStackView, topConstraints: descriptionView.bottomAnchor, trailingSpace: 0, topSpace: 10, isActive: isLayoutActive) //Character Limit View
}
//MARK:Setup % Discount
func setupPercentDiscountView(isLayoutActive:Bool){
amountView.isHidden = false
textViewDescription.placeholderText = "Description"
setupInputFields(fieldView: amountView, topConstraints: formBaseView.topAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 8, height: 44, isActive: isLayoutActive) //Amount View
setupInputFields(fieldView: pointsView, topConstraints: amountView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, height: 44, isActive: isLayoutActive) //Points View
setupStartEndDateStackView(formStackView: startEndDateStackView, topConstraints: pointsView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, isActive: isLayoutActive) //StartDate Endate
setupInputFields(fieldView: titleFieldView, topConstraints: startEndDateStackView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, height: 44, isActive: isLayoutActive) //Title View
setupInputFields(fieldView: descriptionView, topConstraints: titleFieldView.bottomAnchor, leadingSpace: 0, trailingSpace: 0, topSpace: 15, height: 95, isActive: isLayoutActive) //Description View
setupMaxCharStackView(formStackView: maxCharLimitStackView, topConstraints: descriptionView.bottomAnchor, trailingSpace: 0, topSpace: 10, isActive: isLayoutActive) //Character Limit View
}
//MARK: SetupInputFields function
func setupInputFields(fieldView:UIView,topConstraints:NSLayoutAnchor<NSLayoutYAxisAnchor>,leadingSpace:CGFloat,trailingSpace:CGFloat,topSpace:CGFloat,height:CGFloat,isActive:Bool){
fieldView.translatesAutoresizingMaskIntoConstraints = false //Make it false for working of constraints
fieldView.topAnchor.constraint(equalTo: topConstraints,constant: topSpace).isActive = isActive
fieldView.leadingAnchor.constraint(equalTo: formBaseView.leadingAnchor,constant: leadingSpace).isActive = isActive
fieldView.trailingAnchor.constraint(equalTo: formBaseView.trailingAnchor,constant: trailingSpace).isActive = isActive
fieldView.heightAnchor.constraint(equalToConstant: height).isActive = isActive
// fieldView.layoutIfNeeded()
}
//MARK: Setup MaxCharacter StackView function
func setupMaxCharStackView(formStackView:UIStackView,topConstraints:NSLayoutAnchor<NSLayoutYAxisAnchor>,trailingSpace:CGFloat,topSpace:CGFloat,isActive:Bool){
formStackView.translatesAutoresizingMaskIntoConstraints = false //Make it false for working of constraints
formStackView.topAnchor.constraint(equalTo: topConstraints,constant: topSpace).isActive = isActive
formStackView.trailingAnchor.constraint(equalTo: formBaseView.trailingAnchor,constant: trailingSpace).isActive = isActive
}
//MARK: Setup StartDate EndDate StackView function
func setupStartEndDateStackView(formStackView:UIStackView,topConstraints:NSLayoutAnchor<NSLayoutYAxisAnchor>,leadingSpace:CGFloat? = nil,trailingSpace:CGFloat,topSpace:CGFloat,isActive:Bool){
formStackView.translatesAutoresizingMaskIntoConstraints = false //Make it false for working of constraints
formStackView.topAnchor.constraint(equalTo: topConstraints,constant: topSpace).isActive = isActive
formStackView.leadingAnchor.constraint(equalTo: formBaseView.leadingAnchor,constant: leadingSpace!).isActive = isActive
formStackView.trailingAnchor.constraint(equalTo: formBaseView.trailingAnchor,constant: trailingSpace).isActive = isActive
}
}
问题是每次单击案例的按钮 1 时都会触发,最终会调用 setupInputFields
并导致重新添加可能与旧约束冲突的新约束,因此要么访问旧约束并删除它们,要么创建 2 个可能的变体数组并使用 activate/deactivate