如何停用我的约束?

Posted

技术标签:

【中文标题】如何停用我的约束?【英文标题】:How to deactivate my constraints? 【发布时间】:2018-02-07 04:52:21 【问题描述】:

我在 swift 中以编程方式创建了一个 UITextView,这就是我在 viewDidLoad() 中为我的控制器所拥有的。

let isPortrait = UIInterfaceOrientationIsPortrait(UIApplication.shared.statusBarOrientation)
if isPortrait 
    searchTextView.widthAnchor.constraint(equalToConstant: view.frame.width * 0.7).isActive = true
 else 
    searchTextView.widthAnchor.constraint(equalToConstant: view.frame.width * 0.1).isActive = true

这就是 searchTextView 的设置方式

func setupView() 
    self.layer.cornerRadius = 8.0
    self.translatesAutoresizingMaskIntoConstraints = false
    self.textContainerInset = UIEdgeInsets(top: 12, left: 10, bottom: 0, right: 10)
    self.textContainer.maximumNumberOfLines = 1
    self.textContainer.lineBreakMode = .byTruncatingHead
    self.autocorrectionType = .no
    self.text = ""
    self.font = Constants.fonts().largeFont
    self.backgroundColor = UIColor.white
    self.adjustsFontForContentSizeCategory = true
    self.textColor = UIColor.black

    self.layer.borderColor = UIColor.gray.cgColor
    self.layer.borderWidth = 0.25

    // Need clipsToBounds = false to show shadow

    self.clipsToBounds = false
    self.layer.shadowRadius = 20.0
    self.layer.shadowColor = UIColor.gray.cgColor
    self.layer.shadowOffset = CGSize(width: 2.0, height: 2.0)
    self.layer.shadowOpacity = 0.5

    self.tintColor = Constants.colors().primaryLightColor


这会根据设备方向为 searchTextView 提供不同的 widthAnchor。这很好用,但是,稍后我会检查设备方向何时会更改并删除并添加相应的 widthAnchors。

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) 
    sideMenuLauncher.dismissSideMenu(duration: 0)

    let toPortraitMode = self.view.frame.size.width > size.width
    searchTextView.widthAnchor.constraint(equalToConstant: view.frame.width * 0.7).isActive = toPortraitMode
    searchTextView.widthAnchor.constraint(equalToConstant: size.width * 0.1).isActive = !toPortraitMode


    for constraint in view.constraints 
        print("\(constraint)\n")
    

    searchTextView.updateConstraints()
    searchTextView.layoutIfNeeded()


但这实际上并没有停用任何约束,正如它在此控制台输出中所说:

(
"<NSLayoutConstraint:0x60c000896170 PickupApp.SearchBarView:0x7f7ee1016a00.width == 56.8   (active)>",
"<NSLayoutConstraint:0x604000c9c6b0 PickupApp.SearchBarView:0x7f7ee1016a00.width == 397.6   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x604000c9c6b0 PickupApp.SearchBarView:0x7f7ee1016a00.width == 397.6   (active)>

我不明白为什么即使添加了约束也没有停用这些约束。

【问题讨论】:

When can I activate/deactivate layout constraints?的可能重复 @HarshalValanda 我相信该帖子是使用 @IBOutlets 回答的,这需要使用情节提要,但我不使用情节提要。 【参考方案1】:

希望下面的代码对你有帮助,

1) 声明全局变量

var searchTextViewPortraitWidthConstraint: NSLayoutConstraint?
var searchTextViewLandscapeWidthConstraint: NSLayoutConstraint?
let searchTextView = UITextView()

2) viewDidLoad()

    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        setupSearchTextView()
        let isPortrait = UIInterfaceOrientationIsPortrait(UIApplication.shared.statusBarOrientation)
        if isPortrait 
            searchTextViewPortraitWidthConstraint = searchTextView.widthAnchor.constraint(equalToConstant: view.frame.width * 0.7)
            searchTextViewLandscapeWidthConstraint = searchTextView.widthAnchor.constraint(equalToConstant: view.frame.width * 0.1)

            searchTextViewPortraitWidthConstraint?.isActive = true
         else 
            searchTextViewLandscapeWidthConstraint = searchTextView.widthAnchor.constraint(equalToConstant: view.frame.width * 0.1)
            searchTextViewPortraitWidthConstraint = searchTextView.widthAnchor.constraint(equalToConstant: view.frame.width * 0.7)
            searchTextViewLandscapeWidthConstraint?.isActive = true
        
    

配置文本视图

func setupSearchTextView()
        searchTextView.frame = CGRect(x: <#T##CGFloat#>, y: <#T##CGFloat#>, width: <#T##CGFloat#>, height: <#T##CGFloat#>)
        /*
         .
         .
         .
         .
         .
         .*/
    

3) 要根据设备方向激活或停用宽度约束,请使用以下任一方法(即viewWillLayoutSubviews()viewDidLayoutSubviews())。

override func viewWillLayoutSubviews() 
    super.viewWillLayoutSubviews()
    let isPortrait = UIInterfaceOrientationIsPortrait(UIApplication.shared.statusBarOrientation)
    if isPortrait
        searchTextViewPortraitWidthConstraint?.isActive = true
        searchTextViewLandscapeWidthConstraint?.isActive = false
    else
        searchTextViewPortraitWidthConstraint?.isActive = false
        searchTextViewLandscapeWidthConstraint?.isActive = true
    


override func viewDidLayoutSubviews() 
    super.viewDidLayoutSubviews()
    let isPortrait = UIInterfaceOrientationIsPortrait(UIApplication.shared.statusBarOrientation)
    if isPortrait
        searchTextViewPortraitWidthConstraint?.isActive = true
        searchTextViewLandscapeWidthConstraint?.isActive = false
    else
        searchTextViewPortraitWidthConstraint?.isActive = false
        searchTextViewLandscapeWidthConstraint?.isActive = true
    

【讨论】:

谢谢!您的代码进行了一次更改。在代码块 #2 中,我必须将 searchTextViewPortraitWidthConstraintsearchTextViewLandscapeWidthConstraint 都设置为 ifelse 中的约束值。如果没有这个改变,当设备旋转时,searchTextView 似乎根本没有宽度。 @SiddhaTiwari 是的,这是很好的识别,我也更新了我的答案。【参考方案2】:
searchTextView.translatesAutoresizingMaskIntoConstraints = false

【讨论】:

【参考方案3】:

您需要存储该约束以便稍后将其停用。

取一个全局变量来存储约束。

var cons:NSLayoutConstraint?

如下更改 viewDidLoad() 以便稍后访问相同的约束:

override func viewDidLoad() 
    super.viewDidLoad()
    let isPortrait = UIInterfaceOrientationIsPortrait(UIApplication.shared.statusBarOrientation)
    if isPortrait 
        self.cons = searchTextView.widthAnchor.constraint(equalToConstant: view.frame.width * 0.7)

     else 
        self.cons = searchTextView.widthAnchor.constraint(equalToConstant: view.frame.width * 0.1)
    
    self.cons?.isActive = true

【讨论】:

以上是关于如何停用我的约束?的主要内容,如果未能解决你的问题,请参考以下文章

iOS如何激活/停用某个尺寸类(方向)的布局约束?

如何强制 uitableview 调整单元格的大小(在停用高度约束后)?

UICollectionReusableView 约束未更新

自动旋转时自动布局约束更新

用函数停用在 viewdidload 中声明的 nslayoutconstraint

NSLayoutConstraint 激活/停用