فهرست — چیست، کامپوننت فهرست در SwiftUI

نویسنده: IT Sectr منتشر شده: 2026-06-25 زمان مطالعه: 7 دقیقه

List — یک View کانتینری در SwiftUI برای نمایش داده‌ها به صورت یک فهرست عمودی قابل پیمایش، مشابه UITableView در UIKit است. بر اساس Apple Developer Documentation, 2024، List از بخش‌های ایستا و پویا، عملیات کشیدن، جابجایی ردیف‌ها و pull-to-refresh پشتیبانی می‌کند. بر خلاف UITableView، List از API اعلامی مبتنی بر SwiftUI و ForEach استفاده می‌کند و به طور خودکار استفاده مجدد از سلول‌ها و عملکرد را در تعداد زیاد ردیف‌ها مدیریت می‌نماید.

نکات کلیدی

  • List — کانتینری برای فهرست قابل پیمایش داده‌ها در SwiftUI
  • ForEach — روش اصلی نمایش پویای داده‌ها در List
  • بخش‌ها — Section View برای گروه‌بندی ردیف‌ها با عنوان
  • عملیات کشیدن — swipeActions برای iOS 15+
  • Pull-to-refresh — .refreshable برای iOS 15+

List در SwiftUI چیست؟

List — یک View است که دنباله‌ای از عناصر را در یک فهرست عمودی قابل پیمایش نمایش می‌دهد. این View همراه با iOS 13 و SwiftUI معرفی شد و روش اصلی نمایش فهرست‌های داده‌ها است که جایگزین UITableView در UIKit می‌شود. List به طور خودکار استفاده مجدد از سلول‌ها، پیمایش و عملکرد را مدیریت می‌کند.

List از lazy-loading استفاده می‌کند: سلول‌ها در حین پیمایش ایجاد می‌شوند، نه یکباره. این آن را از VStack با ForEach درون ScrollView متمایز می‌کند، جایی که همه سلول‌ها هنگام رندر ایجاد می‌شوند. List همچنین پشتیبانی داخلی از عملیات کشیدن، pull-to-refresh، ویرایش (حذف/انتقال) و انتخاب ردیف‌ها را فراهم می‌کند.

بر اساس Apple WWDC 2021 (Session 10072)، List در iOS 15+ به لطف مکانیزم diffing جدید در سطح مجموعه‌ها، بهبودهای عملکردی قابل توجهی دریافت کرد. این کار List را در به‌روزرسانی داده‌ها، به ویژه برای فهرست‌های با صدها ردیف، کارآمدتر ساخت.

List در مقابل ScrollView + VStack

توسعه‌دهندگان اغلب بین List و ScrollView با VStack برای نمایش مجموعه‌ای از View‌ها انتخاب می‌کنند. تفاوت کلیدی: List از استفاده مجدد سلول‌ها (مانند UITableView) استفاده می‌کند، در حالی که ScrollView + VStack همه View‌ها را یکباره ایجاد می‌کند. برای فهرست‌های با تعداد ثابت عناصر (تا ۲۰) تفاوت ناچیز است. برای فهرست‌های پویا با ۵۰+ ردیف، List از نظر عملکرد ترجیح داده می‌شود.

فهرست‌های ایستا و پویا

فهرست ایستا (Static List) — فهرستی با تعداد ثابت ردیف‌ها است که مستقیماً در بدنه List تعریف می‌شوند. برای منوها، تنظیمات و فرم‌هایی با مجموعه عناصر مشخص استفاده می‌شود. هر ردیف به صراحت و بدون حلقه یا ForEach اعلام می‌شود.

swift
// فهرست ایستا (برای منوها و تنظیمات)
List {
    Text("پروفایل")
    Text("تنظیمات")
    Text("درباره")
}

// فهرست پویا (برای داده‌ها)
struct UserList: View {
    let users: [User]

    var body: some View {
        List(users) { user in
            HStack {
                Text(user.name)
                Text(user.role)
                    .foregroundColor(.secondary)
            }
        }
    }
}

فهرست پویا (Dynamic List) از مقداردهنده List(data:rowContent:) یا ForEach درون بدنه List استفاده می‌کند. گزینه اول زمانی مناسب است که هر ردیف با یک عنصر داده مطابقت دارد. گزینه دوم — زمانی که بخش‌ها یا عناصر اضافی بین داده‌ها وجود دارد.

شناسایی (Identifiable): برای فهرست‌های پویا، عناصر داده باید با پروتکل Identifiable مطابقت داشته باشند یا در تاپل data:id باید KeyPath به شناسه یکتا مشخص شود. SwiftUI از شناسه‌ها برای ردیابی تغییرات استفاده می‌کند: افزودن، حذف و جابجایی ردیف‌ها.

بخش‌ها و گروه‌بندی داده‌ها

Section — یک View برای گروه‌بندی ردیف‌ها در List با عنوان و پاورقی اختیاری است. Section header و footer را به عنوان ViewBuilder می‌پذیرد و امکان استفاده از نه تنها متن، بلکه View‌های سفارشی برای عناوین بخش‌ها را فراهم می‌کند.

swift
struct SettingsView: View {
    var body: some View {
        List {
            Section(header: Text("حساب")) {
                Text("نام")
                Text("ایمیل")
            }
            Section(header: Text("اعلان‌ها")) {
                Toggle("Push", isOn: $pushEnabled)
                Toggle("Email", isOn: $emailEnabled)
            }
        }
        .listStyle(.insetGrouped)
    }
}

// بخش‌های پویا با ForEach
List {
    ForEach(groupedData.keys.sorted(), id: \.self) { key in
        Section(header: Text(key)) {
            ForEach(groupedData[key]!) { item in
                Text(item.title)
            }
        }
    }
}

سبک‌های List: SwiftUI چندین سبک داخلی را از طریق اصلاح‌کننده .listStyle() ارائه می‌دهد. .insetGrouped — استاندارد برای iOS Settings، .plain — مینیمال، .inset — با فاصله، .sidebar — برای Sidebar در iPad.

بر اساس SwiftUI Cookbook (2024)، Section با بخش‌های پویا و ForEach درون آن، الگوی استانداردی برای گروه‌بندی داده‌ها در برنامه‌های با ساختار پیچیده است. قانون کلیدی: Section را درون Section قرار ندهید و از مقداردهنده List(data:) همراه با Section استفاده نکنید — از ForEach درون بدنه List استفاده کنید.

عملیات کشیدن و pull-to-refresh

.swipeActions(edge:allowsFullSwipe:content:) — اصلاح‌کننده برای iOS 15+ که عملیات کشیدن را به ردیف‌های List اضافه می‌کند. امکان نمایش دکمه‌ها هنگام کشیدن به چپ (پیش‌فرض) یا راست، با رنگ‌ها و نقش‌های مختلف (destructive, cancel) را فراهم می‌کند.

swift
struct TaskList: View {
    @Binding var tasks: [Task]

    var body: some View {
        List {
            ForEach($tasks) { $task in
                Text(task.title)
                    .swipeActions(edge: .trailing) {
                        Button("حذف", role: .destructive) {
                            tasks.removeAll { $0.id == task.id }
                        }
                    }
                    .swipeActions(edge: .leading) {
                        Button(task.isDone ? "برگردان" : "انجام شد") {
                            task.isDone.toggle()
                        }
                        .tint(.green)
                    }
            }
        }
        .refreshable {
            // بارگذاری ناهمزمان داده‌ها
            await loadTasks()
        }
    }
}

.refreshable — اصلاح‌کننده برای iOS 15+ که pull-to-refresh را اضافه می‌کند. یک closure ناهمزمان (async) می‌پذیرد که وقتی کاربر فهرست را به پایین می‌کشد اجرا می‌شود. SwiftUI به طور خودکار نشانگر بارگذاری را نمایش می‌دهد. پس از اتمام عملیات، نشانگر پنهان می‌شود.

.onDelete و .onMove — اصلاح‌کننده‌هایی برای iOS 13+ که پشتیبانی از حذف و جابجایی ردیف‌ها را اضافه می‌کنند. برای استفاده از آن‌ها، داده‌ها را در ForEach با Binding بپیچید یا closure‌ها را از طریق .onDelete(perform:) روی List یا ForEach ارسال کنید.

عملکرد List و بهینه‌سازی

عملکرد List به تعداد ردیف‌ها، پیچیدگی هر سلول و فراوانی به‌روزرسانی داده‌ها بستگی دارد. SwiftUI از lazy-loading و استفاده مجدد از سلول‌ها (مشابه UITableView.dequeueReusableCell) استفاده می‌کند، اما بهینه‌سازی‌های اضافی ممکن است برای فهرست‌های با ۵۰۰+ ردیف لازم باشد.

بهینه‌سازیتوضیحنسخه iOS
Identifiableشناسه یکتا برای هر عنصرiOS 13+
EquatableViewجلوگیری از رندر مجدد در داده‌های برابرiOS 13+
id(_:)بازآفرینی اجباری View هنگام تغییر IDiOS 13+
.equatable()مقایسه دقیق بر اساس EquatableiOS 15+
Diffable datadiff خودکار در تغییراتiOS 15+

مشکل ۱: به‌روزرسانی‌های مکرر. اگر داده‌های فهرست مکرراً به‌روزرسانی شوند (مثلاً هر ثانیه)، List ممکن است سلول‌های قابل مشاهده را در هر تغییر وضعیت دوباره رندر کند. راه‌حل: از struct (value types) برای داده‌ها استفاده کنید — SwiftUI آن‌ها را بر اساس مقدار مقایسه می‌کند و فقط ردیف‌های تغییر یافته را دوباره رندر می‌کند.

مشکل ۲: سلول‌های سنگین. اگر هر ردیف شامل سلسله‌مراتب پیچیده View، تصاویر و انیمیشن‌ها باشد، پیمایش ممکن است کند شود. راه‌حل: سلول‌ها را به View‌های جداگانه منتقل کنید، از EquatableView برای جلوگیری از رندر مجدد اضافی استفاده کنید. بر اساس SwiftUI Lab (2024)، تقسیم یک ردیف پیچیده به زیر مؤلفه‌ها زمان رندر را ۳۰–۵۰٪ کاهش می‌دهد.

مشکل ۳: تعداد زیاد ردیف‌ها. در ۱۰۰۰+ ردیف، List به لطف lazy-loading همچنان کارآمد کار می‌کند، اما بارگذاری اولیه ممکن است به دلیل محاسبه layout کند شود. راه‌حل: از LazyVStack فقط برای فهرست‌های با ردیف‌های همگن که به قابلیت‌های List (کشیدن، بخش‌ها) نیاز ندارند استفاده کنید. برای فهرست‌های کاملاً کاربردی، List بهترین گزینه باقی می‌ماند.

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

List در SwiftUI چیست؟

List — یک View کانتینری برای نمایش فهرست قابل پیمایش داده‌ها در SwiftUI. مشابه UITableView در UIKit با API اعلامی. از بخش‌ها، عملیات کشیدن، pull-to-refresh، ویرایش و سفارشی‌سازی از طریق .listStyle() پشتیبانی می‌کند.

تفاوت List با ScrollView + VStack چیست؟

List از lazy-loading و استفاده مجدد از سلول‌ها استفاده می‌کند — سلول‌ها در حین پیمایش ایجاد می‌شوند. ScrollView + VStack همه View‌ها را یکباره ایجاد می‌کند. برای فهرست‌های با ۵۰+ ردیف، List ترجیح داده می‌شود. برای مجموعه‌های ثابت کوچک (تا ۲۰ عنصر) تفاوت ناچیز است.

چگونه pull-to-refresh را به List اضافه کنیم؟

از اصلاح‌کننده .refreshable (iOS 15+) استفاده کنید. یک closure ناهمزمان با منطق به‌روزرسانی داده‌ها ارسال کنید. SwiftUI به طور خودکار نشانگر بارگذاری را نمایش می‌دهد و پس از اتمام عملیات ناهمزمان آن را پنهان می‌کند.

چگونه ردیف‌ها را در List گروه‌بندی کنیم؟

از Section View با header و پاورقی اختیاری استفاده کنید. ردیف‌های فهرست را درون Section قرار دهید. برای بخش‌های پویا از ForEach با groupedData استفاده کنید. سبک فهرست از طریق .listStyle(.insetGrouped) برای ظاهری شبیه iOS تنظیم می‌شود.

چگونه List با تعداد زیاد ردیف را سریع‌تر کنیم؟

برای داده‌ها از struct (value types) استفاده کنید، سلول‌های پیچیده را به View‌های جداگانه با EquatableView منتقل کنید، از به‌روزرسانی مکرر وضعیت در هر ردیف خودداری کنید. برای فهرست‌های با ۱۰۰۰+ ردیف، اگر به قابلیت‌های List نیاز ندارید، LazyVStack را در نظر بگیرید.

خلاصه

  • List — کانتینری برای فهرست قابل پیمایش با lazy-loading و استفاده مجدد از سلول‌ها
  • ForEach — روش اصلی نمایش پویای داده‌ها در List
  • Section — گروه‌بندی ردیف‌ها با عنوان و پاورقی
  • swipeActions — عملیات کشیدن برای iOS 15+
  • refreshable — pull-to-refresh برای iOS 15+
  • سبک‌ها — insetGrouped, plain, inset, sidebar از طریق .listStyle()
  • عملکرد — از Identifiable, EquatableView و value types استفاده کنید

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

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

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

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