簡體   English   中英

以編程方式添加前導/頂部約束

[英]adding leading / top constraints programmatically

我有以下代碼適用於高度和寬度約束。 嘗試添加前導約束和頂部約束時它會崩潰。 我還有其他具有高度、寬度、前導、頂部約束的按鈕組,但它們都設置在故事板上,所以我認為這些是我必須添加到每個按鈕的僅有的 4 個約束。

我有 7 個按鈕,每個按鈕用於一周中的一天。 當我添加代碼來執行前導和頂部約束時,它會因下面的錯誤代碼而中斷。 它僅適用於高度/寬度。 我猜這與我添加子視圖的方式或按鈕與視圖控制器的關系有關,或者在以編程方式執行時,我需要的約束超過我一直使用的 4 個約束(前導、頂部、寬度、高度)在故事板上。

func setupWeekdayButtons() {
    self.weeklyButtons = [self.mondayButton, self.tuesdayButton, self.wednesdayButton, self.thursdayButton, self.fridayButton, self.saturdayButton, self.sundayButton]


    for i in 0...6 {
        print(i)

        self.weeklyButtons[i].translatesAutoresizingMaskIntoConstraints = false
        self.weeklyButtons[i].setTitle(self.weekdayLabels[i], for: .normal)
        self.weeklyButtons[i].layer.borderColor = UIColor.black.cgColor
        self.weeklyButtons[i].titleLabel?.textAlignment = .center
        self.weeklyButtons[i].layer.borderWidth = 1.0
        self.weeklyButtons[i].layer.cornerRadius = 6.0
        self.weeklyButtons[i].setTitleColor(.black, for: .normal)
        self.weeklyButtons[i].setTitleColor(.red, for: .selected)
        self.weeklyButtons[i].addTarget(self, action: #selector(selectedDailyButton), for: .touchUpInside)
        self.view.addSubview(self.weeklyButtons[i])

        let heightConstraint = NSLayoutConstraint(
            item: self.weeklyButtons[i],
            attribute: NSLayoutConstraint.Attribute.height,
            relatedBy: NSLayoutConstraint.Relation.equal,
            toItem: nil,
            attribute: NSLayoutConstraint.Attribute.notAnAttribute,
            multiplier: 1.0,
            constant: 30
        )
        let widthConstraint = NSLayoutConstraint(
            item: self.weeklyButtons[i],
            attribute: NSLayoutConstraint.Attribute.width,
            relatedBy: NSLayoutConstraint.Relation.equal,
            toItem: nil,
            attribute: NSLayoutConstraint.Attribute.notAnAttribute,
            multiplier: 1.0,
            constant: 30
        )
        let leadingConstraint = NSLayoutConstraint(
            item: self.weeklyButtons[i],
            attribute: NSLayoutConstraint.Attribute.leading,
            relatedBy: NSLayoutConstraint.Relation.equal,
            toItem: self.view,
            attribute: NSLayoutConstraint.Attribute.leading,
            multiplier: 1.0,
            constant: 100
        )

        let topConstraint = NSLayoutConstraint(
            item: self.weeklyButtons[i],
            attribute: NSLayoutConstraint.Attribute.top,
            relatedBy: NSLayoutConstraint.Relation.equal,
            toItem: self.view,
            attribute: NSLayoutConstraint.Attribute.top,
            multiplier: 1.0,
            constant: 100
        )
        self.weeklyButtons[i].addConstraint(heightConstraint)
        self.weeklyButtons[i].addConstraint(widthConstraint)
        self.weeklyButtons[i].addConstraint(leadingConstraint)
        self.weeklyButtons[i].addConstraint(topConstraint)
    }
}

2019-03-07 14:38:59.176638-0500 Daily[27852:1408014] [LayoutConstraints] 未為約束准備視圖層次結構:添加到視圖時,約束的項必須是該視圖(或視圖)的后代本身)。 如果在組裝視圖層次結構之前需要解決約束,這將崩潰。 中斷 -[UIView(UIConstraintBasedLayout) _viewHierarchyUnpreparedForConstraint:] 進行調試。

2019-03-07 14:38:59.177816-0500 Daily[27852:1408014] [LayoutConstraints] 視圖層次結構沒有准備好約束。 約束:容器層次結構:> | > 在容器層次結構中找不到視圖: > 該視圖的超級視圖:NO SUPERVIEW

2019-03-07 14:38:59.192176-0500 Daily[27852:1408014] *** 由於未捕獲的異常“NSGenericException”而終止應用程序,原因:“無法在視圖上安裝約束。 約束是否引用了視圖子樹之外的內容? 那是非法的。 約束:視圖:>'

自從我在代碼中添加約束以來已經有一段時間了,但是如果沒有記錯,您必須在添加約束之前將視圖添加到視圖層次結構中。 (這就是錯誤消息所暗示的。)

 self.weeklyButtons[i].addConstraint(leadingConstraint)

約束涉及weeklyButtons[i]self.view 如果使用addConstraint激活約束,則必須將約束添加到兩個視圖的共同祖先。 這就是此錯誤消息告訴您的內容:

添加到視圖時,約束的項必須是該視圖(或視圖本身)的后代。

由於self.viewweeklyButtons[i]weeklyButtons[i]視圖,它算作兩個視圖的共同祖先。 因此,在這種情況下,您可以將約束添加到self.view

self.view.addConstraint(leadingConstraint)

但不要那樣做。 從 iOS 8 開始,你可以直接激活一個約束,UIKit 會自動將它添加到正確的視圖中:

leadingConstraint.isActive = true

但不要那樣做。 由於您要連續添加四個約束,因此像這樣同時激活四個約束可能會更有效:

NSLayoutConstraint.activate([
    leadingConstraint,
    topConstraint,
    widthConstraint,
    heightConstraint])

但不要那樣做。 從 iOS 9 開始,有一種更具可讀性的方式來創建約束:

NSLayoutConstraint.activate([
    self.weeklyButtons[i].heightAnchor.constraint(equalToConstant: 30),
    self.weeklyButtons[i].widthAnchor.constraint(equalToConstant: 30),
    self.weeklyButtons[i].leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 100),
    self.weeklyButtons[i].topAnchor.constraint(equalTo: view.topAnchor, constant: 100),
    ])

但不要那樣做。 使用for / in循環代替索引變量i

func setupWeekdayButtons() {
    weeklyButtons = [mondayButton, tuesdayButton, wednesdayButton, thursdayButton, fridayButton, saturdayButton, sundayButton]

    for (button, title) in zip(weeklyButtons, weekdayLabels) {
        button.translatesAutoresizingMaskIntoConstraints = false
        button.setTitle(title, for: .normal)
        button.layer.borderColor = UIColor.black.cgColor
        button.titleLabel?.textAlignment = .center
        button.layer.borderWidth = 1.0
        button.layer.cornerRadius = 6.0
        button.setTitleColor(.black, for: .normal)
        button.setTitleColor(.red, for: .selected)
        button.addTarget(self, action: #selector(selectedDailyButton), for: .touchUpInside)
        view.addSubview(button)

        NSLayoutConstraint.activate([
            button.heightAnchor.constraint(equalToConstant: 30),
            button.widthAnchor.constraint(equalToConstant: 30),
            button.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 100),
            button.topAnchor.constraint(equalTo: view.topAnchor, constant: 100),
            ])
    }
}

去做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM