Auto Layout: چیست، طراحی تطبیقی رابط‌های iOS

نویسنده: IT Sectr منتشر شده: 2026-02-21 زمان مطالعه: 9 دقیقه

Auto Layout — سیستم موقعیت‌یابی تطبیقی عناصر رابط کاربری از اپل، مبتنی بر محدودیت‌های ریاضی (constraints). طراحی شده برای iOS 6 (2012)، Auto Layout به شما امکان ایجاد رابط‌هایی را می‌دهد که در تمام دستگاه‌ها — از iPhone SE (4.7″) تا iPad Pro (12.9″) و Dynamic Island — به درستی نمایش داده می‌شوند. به گفته Apple WWDC Session 202 (2024)، بیش از 90٪ برنامه‌های App Store از Auto Layout یا جایگزین اعلانی آن — SwiftUI layout system استفاده می‌کنند. Constraints وابستگی‌های بین عناصر UI را از طریق معادلات خطی توصیف می‌کنند: view1.leading = view2.trailing + 8.

مهم

  • Auto Layout — سیستم طراحی تطبیقی اپل از طریق محدودیت‌های ریاضی (constraints) برای تمام اندازه‌های صفحه.
  • Constraints — معادلات خطی به شکل view1.attribute = multiplier × view2.attribute + constant که با الگوریتم Cassowary حل می‌شوند.
  • UIStackView — کانتینری که به طور خودکار constraints را برای view‌های تو در تو مدیریت می‌کند (horizontal/vertical, alignment, distribution).
  • NSLayoutConstraint — API برنامه‌نویسی برای ایجاد محدودیت‌ها در کد با فعال‌سازی از طریق isActive = true.
  • Safe Area و Layout Margins — حاشیه‌های داخلی Auto Layout که از تداخل با Dynamic Island، Notch و Home Indicator جلوگیری می‌کنند.

Auto Layout چیست؟

Auto Layout — سیستم طراحی تطبیقی اپل است که از محدودیت‌های ریاضی (constraints) برای موقعیت‌یابی عناصر UI استفاده می‌کند. بر خلاف طراحی قاب‌محور (frame-based layout) که در آن هر عنصر مختصات ثابت x، y، width، height دارد، Auto Layout روابط بین عناصر را توصیف می‌کند: «دکمه در 8pt از لبه راست والد قرار دارد» یا «عرض فیلد متنی برابر با نصف عرض صفحه است». این مکانیزم بر اساس الگوریتم Cassowary است که در University of Washington (Greg J. Badros، 1999) توسعه یافته و توسط اپل در iOS 6 پیاده‌سازی شده است. Cassowary سیستم نابرابری‌های خطی با اولویت‌ها را حل می‌کند — Required (1000)، Default High (750)، Default Low (250) — که امکان مدیریت تضادهای محدودیت‌ها را فراهم می‌کند. Auto Layout از سه نوع اندازه پشتیبانی می‌کند: intrinsic (اندازه طبیعی عنصر که توسط محتوا تعیین می‌شود)، explicit (constraint صریحاً تعیین شده) و compressible/stretchable (حالت الاستیک از طریق Content Hugging Priority و Compression Resistance Priority).

Intrinsic Content Size و اولویت‌ها

هر عنصر UI در Auto Layout دارای Intrinsic Content Size — اندازه طبیعی تعیین شده توسط محتوای خود است. برای UILabel این به متن و فونت بستگی دارد، برای UIImageView — به ابعاد تصویر. Content Hugging Priority (مقاومت در برابر کشیده شدن) و Compression Resistance Priority (مقاومت در برابر فشرده شدن) رفتار عنصر را هنگام تغییر فضای موجود مدیریت می‌کنند. مقادیر استاندارد: 251 برای hugging و 749 برای compression resistance. اگر دو عنصر برای فضا رقابت کنند، اولویت تعیین می‌کند کدام یک ابتدا کشیده می‌شود. درک این اولویت‌ها کلید رفع Ambiguous Layout (طرح‌بندی مبهم) است که Xcode در دیباگر برجسته می‌کند.

آناتومی Constraint

Constraint با معادله توصیف می‌شود: view1.attribute = multiplier × view2.attribute + constant. ویژگی‌ها شامل leading، trailing، top، bottom، centerX، centerY، width، height، firstBaseline، lastBaseline هستند. Multiplier برای روابط تناسبی استفاده می‌شود (عرض view1 = 0.5 × عرض superview). Constant فاصله ثابت را تعیین می‌کند (leading = superview.leading + 16). ابزارهای Interface Builder امکان تعیین بصری constraints را از طریق کشیدن با Ctrl فراهم می‌کنند، اما طرح‌بندی‌های پیچیده نیاز به ایجاد برنامه‌نویسی از طریق NSLayoutConstraint یا VFL (Visual Format Language) دارند که اپل توصیه می‌کند از iOS 9 با NSLayoutConstraint جایگزین شود.

Constraints در iOS چگونه کار می‌کنند

سیستم constraints به عنوان یک مسئله برنامه‌ریزی خطی حل می‌شود: الگوریتم Cassowary مکان بهینه همه عناصر را پیدا می‌کند و تمام محدودیت‌ها را با در نظر گرفتن اولویت‌هایشان برآورده می‌کند. اگر constraints با یکدیگر تضاد داشته باشند، Unsatisfiable Layout رخ می‌دهد — استثنایی که Xcode با شرح دقیق تضاد ثبت می‌کند. اگر constraints برای تعیین موقعیت حداقل یک عنصر کافی نباشند، Ambiguous Layout رخ می‌دهد — عناصر در موقعیت دلخواه نمایش داده می‌شوند. اپل حداقل مجموعه را توصیه می‌کند: برای هر عنصر باید position (x، y) و size (width، height) — به صورت صریح یا از طریق intrinsic content size تعیین شود. Constraints می‌توانند first-class باشند: عنصر اصلی (مثلاً superview) و عنصر وابسته (view فرزند) سلسله‌مراتب ایجاد می‌کنند.

الگوریتم Cassowary و اولویت‌ها

Cassowary از روش Sequential Quadratic Programming برای حل سیستم‌های نابرابری‌های خطی استفاده می‌کند. هر constraint دارای اولویت از 1 تا 1000 است. Required (1000) — محدودیت اجباری؛ اگر قابل اجرا نباشد، برنامه با NSConstraintException crash می‌کند. Default High (750) — توصیه‌ای؛ Default Low (250) — کم اهمیت‌ترین. در صورت تضاد، Cassowary محدودیت‌های با اولویت پایین‌تر را تضعیف می‌کند. به عنوان مثال، اگر دو عنصر عرض ثابت نیاز داشته باشند و صفحه خیلی باریک باشد، constraint با اولویت پایین‌تر تضعیف می‌شود. در Xcode Debug View Hierarchy (ابزار دیباگ موجود از Xcode 6) فقط مشکلات مربوط به Required constraints را برجسته می‌کند — بقیه بدون خطا پردازش می‌شوند.

UIStackView: مدیریت خودکار Constraints

UIStackView — کانتینری که در iOS 9 (2015) معرفی شد و به طور خودکار constraints را برای arrangedSubviews تو در تو ایجاد و مدیریت می‌کند. UIStackView از دو محور پشتیبانی می‌کند: horizontal (چیدمان افقی) و vertical (عمودی). تنظیمات distribution نحوه توزیع فضا را تعیین می‌کند: fill (پر کردن متناسب با hugging priority)، fillEqually (اندازه‌های مساوی)، fillProportionally (متناسب با intrinsic content size)، equalSpacing (فاصله‌های مساوی)، equalCentering (فاصله مساوی بین مراکز). Alignment تراز کردن را در عرض محور تعیین می‌کند: fill، leading، center، trailing (برای horizontal) یا fill، top، center، bottom (برای vertical). UIStackView به طور خودکار spacing، baseline alignment و سازگاری با Dynamic Type را مدیریت می‌کند.

swift
import UIKit

class StackViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let stack = UIStackView()
        stack.axis = NSLayoutConstraint.Axis.vertical
        stack.distribution = .fillEqually
        stack.spacing = 8
        stack.translatesAutoresizingMaskIntoConstraints = false
        
        let label = UILabel()
        label.text = "راهنمای Auto Layout"
        label.font = UIFont.preferredFont(forTextStyle: .headline)
        
        let button = UIButton(type: .system)
        button.setTitle("اعمال", for: .normal)
        
        stack.addArrangedSubview(label)
        stack.addArrangedSubview(button)
        view.addSubview(stack)
        
        NSLayoutConstraint.activate([
            stack.centerXAnchor.constraint(equalTo: view.centerXAnchor),
            stack.centerYAnchor.constraint(equalTo: view.centerYAnchor),
            stack.leadingAnchor.constraint(greaterThanOrEqualTo: view.leadingAnchor, constant: 16),
            stack.trailingAnchor.constraint(lessThanOrEqualTo: view.trailingAnchor, constant: -16)
        ])
    }
}

کد یک UIStackView عمودی با دو عنصر (UILabel و UIButton) ایجاد می‌کند که به طور مساوی (fillEqually) با فاصله 8pt توزیع شده‌اند. Stack در مرکز صفحه با فاصله حداقل 16pt از لبه‌ها قرار می‌گیرد. translatesAutoresizingMaskIntoConstraints = false هنگام ایجاد برنامه‌نویسی constraints اجباری است — بدون آن Auto Layout کار نمی‌کند. در IT Sectr، UIStackView در 80٪ صفحات پروژه‌های iOS برای ساخت فرم‌های تطبیقی، لیست تنظیمات و کارت‌ها استفاده می‌شود.

Stack View‌های تو در تو

UIStackView‌ها می‌توانند تو در تو باشند: stack افقی داخل vertical — الگوی استاندارد برای طرح‌بندی‌های پیچیده. stack بیرونی ردیف‌ها را مدیریت می‌کند، stack داخلی — ستون‌های داخل ردیف. ترکیب axis، alignment و distribution در هر سطح عملاً انعطاف‌پذیری نامحدودی را بدون حتی یک constraint دستی فراهم می‌کند. اپل استفاده از UIStackView را به عنوان ابزار اصلی layout در UIKit توصیه می‌کند و تنها در مواردی که stack پوشش نمی‌دهد به NSLayoutConstraint دستی مراجعه می‌کند: view‌های همپوشان، موقعیت‌یابی دقیق پیکسلی، انیمیشن سفارشی bounds.

NSLayoutConstraint: ایجاد برنامه‌نویسی محدودیت‌ها

NSLayoutConstraint — API برنامه‌نویسی برای ایجاد محدودیت‌های فردی در کد. هر constraint از طریق مقداردهنده با پارامترها ایجاد می‌شود: item، attribute، relatedBy، toItem، attribute، multiplier، constant. از iOS 9 اپل Anchor API را معرفی کرد — نحو خواناتر از طریق ویژگی‌های view.leadingAnchor، view.trailingAnchor، view.topAnchor، view.bottomAnchor، view.centerXAnchor، view.centerYAnchor، view.widthAnchor، view.heightAnchor. Anchor API به طور خودکار relatedBy = .equal را تنظیم می‌کند و از First Item/Second Item از Anchor استفاده می‌کند و کد را 40٪ در مقایسه با NSLayoutConstraint کلاسیک کاهش می‌دهد.

swift
import UIKit

class ConstraintViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let childView = UIView()
        childView.backgroundColor = .systemBlue
        childView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(childView)
        
        NSLayoutConstraint.activate([
            childView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 24),
            childView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 16),
            childView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -16),
            childView.heightAnchor.constraint(equalToConstant: 120),
            childView.bottomAnchor.constraint(lessThanOrEqualTo: view.bottomAnchor, constant: -24)
        ])
    }
}

کد childView را با فاصله از safeAreaLayoutGuide (top) و لبه‌های صفحه (leading/trailing) قرار می‌دهد. lessThanOrEqualTo برای bottom تضمین می‌کند که view از مرز پایینی خارج نشود. Anchor API در مرحله کامپایل استثنا پرتاب می‌کند اگر anchorها ناسازگار باشند (مثلاً leadingAnchor با rightAnchor مخلوط شود)، که از خطاهای runtime جلوگیری می‌کند. اپل Anchor API را به عنوان استاندارد برای Auto Layout برنامه‌نویسی از iOS 9 توصیه می‌کند.

Safe Area و Layout Margins در Auto Layout

Safe Area — ناحیه‌ای از صفحه که توسط عناصر سیستمی پوشانده نشده است: Dynamic Island، Notch، Status Bar، Home Indicator، گوشه‌های گرد. در iOS 11 اپل topLayoutGuide/bottomLayoutGuide را با safeAreaLayoutGuide جایگزین کرد که به طور خودکار با جهت دستگاه و وجود بریدگی صفحه سازگار می‌شود. Layout Margins — حاشیه‌های داخلی پیش‌فرض view (16pt در iOS، 20pt در iPadOS). برای UILayoutGuide می‌توان directionalLayoutMargins سفارشی با در نظر گرفتن بومی‌سازی RIGHT-TO-LEFT تنظیم کرد. Auto Layout هنگام استفاده از safeAreaLayoutGuide در anchorها به طور خودکار safe area را در نظر می‌گیرد.

سازگاری با Dynamic Island و Notch

در دستگاه‌های دارای Dynamic Island (iPhone 14 Pro و جدیدتر) و Notch (iPhone X–13) Safe Area 44pt از بالا در حالت عمودی (59pt با Dynamic Island در حالت فعال) را مستثنی می‌کند. Home Indicator 34pt از پایین اضافه می‌کند. برای سازگاری صحیح، همه top-constraints باید به safeAreaLayoutGuide.topAnchor متصل شوند، نه به view.topAnchor. Bottom-constraints — به safeAreaLayoutGuide.bottomAnchor یا view.bottomAnchor با احتساب Home Indicator. در IT Sectr همه صفحات را روی شبیه‌سازهای iPhone SE (2022)، iPhone 14 Pro Max و iPad Pro 12.9″ آزمایش می‌کنیم — سه دستگاهی که همه انواع safe area را پوشش می‌دهند.

اشتباهات رایج Auto Layout

رایج‌ترین اشتباهات هنگام کار با Auto Layout: translatesAutoresizingMaskIntoConstraints = false فراموش شده، تضاد Required constraints (اولویت 1000)، Ambiguous Layout (constraints ناکافی برای تعیین موقعیت)، Content Hugging Priority نادرست برای UILabel با متن چندخطی و مخلوط کردن leading/trailing با left/right anchors. Xcode 15+ مشکلات layout را در Runtime Issue Navigator نمایش می‌دهد و اصلاحات خودکار ارائه می‌دهد. برای طرح‌بندی‌های پیچیده از Debug View Hierarchy استفاده کنید: برچسب‌های زرد نشان‌دهنده ambiguous layout، قرمز — unsatisfiable هستند.

خطاعلتراه‌حل
translatesAutoresizingMaskIntoConstraints = trueAuto Layout برای view فعال نیستبرای همه view‌های برنامه‌نویسی false تنظیم کنید
Unsatisfiable Layoutتضاد Required (1000) constraintsاولویت یکی را به Default High (750) کاهش دهید
Ambiguous Layoutconstraints کافی برای x/y/w/h نیستconstraint缺失 اضافه کنید یا intrinsic size را بررسی کنید
برش متن در UILabelContent Hugging Priority پایین‌تر از رقیبhugging priority را به 252+ افزایش دهید
مخلوط کردن anchorهای LTR/RTLleadingAnchor با rightAnchorفقط از leading/trailing برای پشتیبانی RTL استفاده کنید

سوالات متداول

Auto Layout چه تفاوتی با طراحی قاب‌محور دارد؟

طراحی قاب‌محور مختصات ثابت x، y، width، height را برای هر عنصر تعیین می‌کند. Auto Layout از محدودیت‌های ریاضی (constraints) استفاده می‌کند — روابط بین عناصر: «label.leading = button.trailing + 8». طراحی قاب‌محور با اندازه صفحه سازگار نمی‌شود؛ Auto Layout به طور خودکار موقعیت‌ها را هنگام چرخش، Split View یا تغییر Dynamic Type دوباره محاسبه می‌کند.

کی باید از UIStackView به جای NSLayoutConstraint استفاده کرد؟

UIStackView برای طرح‌بندی‌های خطی بهینه است: ردیف‌ها، ستون‌ها، فرم‌ها، لیست پارامترها. NSLayoutConstraint برای view‌های همپوشان، موقعیت‌یابی دقیق پیکسلی، انیمیشن سفارشی bounds و مواردی که توزیع فضا نابرابر است و توسط distribution UIStackView پوشش داده نمی‌شود ضروری است. در عمل 80٪ طرح‌بندی‌ها با UIStackView و 20٪ با constraints دستی حل می‌شوند.

Content Hugging Priority در Auto Layout چیست؟

Content Hugging Priority (مقاومت در برابر کشیده شدن) — اولویتی که تعیین می‌کند عنصر چقدر در برابر افزایش اندازه خود فراتر از Intrinsic Content Size مقاومت می‌کند. مقدار پیش‌فرض — 251. اگر دو عنصر برای فضای خالی رقابت کنند، عنصر با hugging priority بالاتر در اندازه خود باقی می‌ماند و دومی کشیده می‌شود. Compression Resistance Priority (پیش‌فرض 749) به طور مشابه برای فشرده‌سازی عمل می‌کند.

Auto Layout با Dynamic Type چگونه کار می‌کند؟

Auto Layout به طور خودکار با Dynamic Type سازگار می‌شود، اگر constraints از intrinsic content size برچسب‌ها استفاده کنند. با افزایش اندازه فونت، UILabel گسترش می‌یابد و عناصر مجاور را از طریق constraints جابجا می‌کند. UIStackView با distribution = fillProportionally فضا را متناسب با intrinsic size جدید توزیع می‌کند. Safe Area و Layout Margins نیز تنظیمات دسترس‌پذیری را در نظر می‌گیرند.

چرا Unsatisfiable Layout رخ می‌دهد؟

Unsatisfiable Layout زمانی رخ می‌دهد که دو Required (priority = 1000) constraints با یکدیگر تضاد داشته باشند: مثلاً view.leading = superview.leading + 16 و view.trailing = superview.leading + 200 با superview به عرض 100pt. الگوریتم Cassowary نمی‌تواند راه‌حلی پیدا کند و برنامه با NSConstraintException crash می‌کند. راه‌حل — اولویت یکی از constraints متضاد را به Default High (750) کاهش دهید.

خلاصه

  • Auto Layout — سیستم طراحی تطبیقی اپل مبتنی بر الگوریتم Cassowary که سیستم محدودیت‌های خطی با اولویت‌ها را حل می‌کند.
  • Constraints — معادلات به شکل view1.attribute = multiplier × view2.attribute + constant با اولویت‌های 1 تا 1000 (Required).
  • UIStackView — کانتینری که به طور خودکار constraints را برای arrangedSubviews با پشتیبانی از محورها، distribution و alignment مدیریت می‌کند.
  • NSLayoutConstraint با Anchor API — استاندارد برنامه‌نویسی از iOS 9، کد را 40٪ در مقایسه با API کلاسیک کاهش می‌دهد.
  • Safe Area — ناحیه بدون Dynamic Island، Notch، Home Indicator؛ برای اتصال top/bottom constraints اجباری است.
  • اشتباهات رایج — translatesAutoresizingMaskIntoConstraints فراموش شده، تضاد Required، Ambiguous Layout، مخلوط کردن anchorهای LTR/RTL.
  • Intrinsic Content Size و اولویت‌ها (hugging 251، compression 749) رفتار عناصر را هنگام تغییر فضای موجود مدیریت می‌کنند.

ما یک اپلیکیشن موبایل به صورت کلید در دست توسعه خواهیم داد

IT Sectr از سال 2017 برنامه‌های iOS و Android را برای استارتاپ‌ها و کسب‌وکارها ایجاد می‌کند. ما به شما مشاوره می‌دهیم و بهترین راه‌حل را پیشنهاد خواهیم کرد.

بحث درباره پروژه

همچنین بخوانید