如何在 Swift 中以编程方式添加约束:优化与性能

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

为什么编程约束是 iOS 开发者的必备技能?

\n

想象一下:你深夜在开发应用,Storyboard 卡顿,Interface Builder 中的冲突没完没了,而客户要求为所有 iPhone 添加自适应屏幕。熟悉吗?正是在这一刻,你开始搜索“How to add constraints programmatically using Swift”。这并非偶然——这是 Stack Overflow 上最热门的问题之一,拥有数千次浏览。但让我们深入探讨:我们不仅仅是翻译答案,而是分析如何 正确、快速且无痛地 做到这一点。

\n

编程约束让你对布局拥有 完全的控制权。没有 Storyboard 中的“粉红大象”,没有魔法数字——只有干净、可预测的代码。最重要的是性能。当你手动编写约束时,你确切地知道什么在何时被创建。没有多余的对象,没有来自 Interface Builder 的“惊喜”。今天,我们将像专业人士一样学习如何做到这一点。

\n\n

什么是编程约束,为什么需要它们?

\n

约束(或限制)是描述视图如何相对于彼此和父视图进行布局的规则。在 Swift 中,有三种主要方法可以以编程方式添加它们:

\n
    \n
  • NSLayoutConstraint — 经典但冗长的方法
  • \n
  • NSLayoutAnchor — 现代、可读且安全的 API(Apple 推荐)
  • \n
  • Visual Format Language (VFL) — 用于描述约束组的字符串格式
  • \n
\n

为什么需要它们?想象一下,你在构建一个 动态界面:聊天、新闻推送或带有可变字段的表单。Storyboard 在这里无能为力——你需要在应用运行时更改元素的大小和位置。或者你在一个团队中工作,代码审查者讨厌 XIB 文件中的冲突。编程约束解决了所有这些问题。

\n\n

NSLayoutAnchor:你的新好朋友

\n

让我们从最流行且正确的方法开始——NSLayoutAnchor。这个 API 在 iOS 9 中引入,并从此成为标准。它是类型安全的、可读的,并且不会让你意外混淆坐标轴。看这里:

\n
import UIKit\n\nclass ViewController: UIViewController {\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        \n        let myView = UIView()\n        myView.backgroundColor = .systemBlue\n        myView.translatesAutoresizingMaskIntoConstraints = false\n        view.addSubview(myView)\n        \n        // 通过 anchors 添加约束\n        NSLayoutConstraint.activate([\n            myView.centerXAnchor.constraint(equalTo: view.centerXAnchor),\n            myView.centerYAnchor.constraint(equalTo: view.centerYAnchor),\n            myView.widthAnchor.constraint(equalToConstant: 200),\n            myView.heightAnchor.constraint(equalToConstant: 200)\n        ])\n    }\n}\n
\n

请注意关键的一行:myView.translatesAutoresizingMaskIntoConstraints = false。这是一个 必要条件。如果遗漏了它,你的约束将与自动掩码冲突,应用会崩溃并报错。请永远记住:每次以编程方式添加约束时,都要禁用 autoresizing。

\n\n

为什么 anchors 更快更安全?

\n

在旧项目中,你可能会遇到带参数的 NSLayoutConstraint。它看起来令人望而生畏:

\n
NSLayoutConstraint(item: myView, attribute: .centerX, relatedBy: .equal, toItem: view, attribute: .centerX, multiplier: 1.0, constant: 0).isActive = true\n
\n

你得承认,这看起来像咒语。一个参数出错,你就会得到一个需要花半天时间查找的 bug。Anchors 解决了这个问题:你只需写 .centerXAnchor.constraint(equalTo: ...)。编译器检查类型,Xcode 提示选项——太棒了!

\n\n

博客

书籍推荐