توسعه اپلیکیشن لیست وظایف با SwiftUI و Core Data – از صفر تا صد


در این مقاله قصد داریم یک اپلیکیشن لیست وظایف با SwiftUI و Core Data توسعه دهیم که شرایط زیر را داشته باشد:
- بتوانیم یک وظیفه اضافه کنیم.
- یک وظیفه را تکمیل کنیم.
- یک وظیفه را حذف کنیم.
- در صورت بسته شدن اپلیکیشن، دادهها حفظ شوند.
اپلیکیشن نهایی ما به صورت زیر خواهد بود:
برای مشاهده کد کامل اپلیکیشن میتوانید به این ریپوی گیتهاب (+) مراجعه کنید. اما اگر میخواهید آن را به صورت گام به گام همراه با ما بسازید، در ادامه این نوشته با ما همراه شوید.
1. ایجاد یک اپلیکیشن تک صفحهای iOS
ابتدا یک پروژه جدید Xcode برای یک اپلیکیشن تکصفحهای iOS ایجاد کنید. تیک گزینه استفاده از SwiftUI و همچنین Core Data را بزنید.
2. موجودیت و خصوصیتهای Core Data
نخستین کاری که باید انجام دهیم افزودن یک موجودیت به مدل Core Data است. به این منظور فایل ProjectName.xcdatamodeld را باز کنید. توجه کنید که ProjectName همان نام پروژه شما است که در گام قبلی تعیین کردهاید. سپس روی Add Entity در انتهای پنجره کلیک کنید. نام موجودیت جدید را Task بگذارید. در تصویر زیر جایی که نام در inspector تغییر مییابد را میبینید:
2.1 افزودن خصوصیت به موجودیت Task
در این مرحله باید برای موجودیت Task، خصوصیتهایی تعیین کنیم تا اطلاعات زیر را ذخیره کند:
- id – به صورت یک شناسه یکتا برای هر وظیفه استفاده میشود.
- name – نامی است که کاربر به وظیفه میدهد.
- isComplete – تکمیل شدن یا نشدن وظیفه را تعیین میکند.
- dateAdded – تاریخ اضافه شدن وظیفه را نشان میدهد.
برای افزودن خصوصیتها به Task از کلید + در بخش Attributes استفاده کنید و یک نام و نوع برای خصوصیت تعیین کنید. در تصویر زیر روش انجام کار را میبینید:
این جدول هر خصوصیت و نوع متناظر با خصوصیت را تعیین میکند:
- id: UUID
- name: string
- isComplete: Bool
- dateAdded: date
فایل ProjectName.xcdatamodeld اینک باید به صورت تصویر زیر در آمده باشد:
2.2 افزودن یک فایل جدید سوئیفت
در این بخش یک فایل جدید سوئیفت اضافه میکنیم که موجب میشود Task قابل شناسایی باشد و فراخوانی فهرست وظایف آسانتر باشد. یک فایل جدید سوئیفت اضافه کرده و نام آن را Task+Extensions بگذارید. در این فایل کد زیر را اضافه کنید:
با افزودن کد فوق، کلاس Task اکنون با کلاس Identifiable سازگار است.
2.3 افزودن Core Data به ContentView.swift
در ادامه باید متغیری اضافه کنیم که به managedObjectContext در فایل ContentView.swift دسترسی داشته باشد. به این منظور فایل ContentView.swift را باز کنید و خط زیر را پیش از متغیر body اضافه کنید:
به این ترتیب ContentView اینک باید به صورت زیر در آمده باشد:
در کد فوق context را به صورت یک متغیر محیطی اعلان میکنیم یعنی مقدار آن قرار است از محیط view بیاید. در این مورد مقدار آن از SceneDelegate.swift در خطوط 23 تا 27 ناشی میشود که context اعلان شده و سپس ()ContentView داده میشود.
3. کار روی UI
در این بخش روی رابط کاربری اپلیکیشن خود در ContentView.swift کار میکنیم.
3.1 افزودن یک TextField
کار خود را با اضافه کردن یک TextField به اپلیکیشن آغاز میکنیم. به این منظور در فایل ContentView.swift مقدار Text(HelloWorld) را به خط زیر تغییر دهید:
TextField باید دو مشخصه یکی StringProtocol و دیگری <Binding<String داشته باشد. برای StringProtocol یک مشخصه به نام "Task Name" اضافه میکنیم. زمانی که TextField خالی باشد، نام وظیفه به رنگ خاکستری روشن ظاهر میشود. سپس به یک <Binding<String نیاز داریم. این مشخصه به اندازه قبلی ساده نیست. ما باید یک متغیر برای آن اعلان کنیم. پیش از اعلان متغیر body خط زیر را اضافه کنید:
سپس مشخصه دوم TextField را به صورت $taskName تعیین کنید. اینک فایل ContentView.swift باید مانند زیر باشد:
از آنجا که ما از SwiftUI استفاده میکنیم، اگر از canvas استفاده کنید، میتوانید بدون الزام به اجرای اپلیکیشن در شبیهساز، UI اپلیکیشن را ببینید. در کد فوق ابتدا یک مشخصه state با استفاده از پوشش مشخصه State@ تعریف کردیم. بنابراین taskName یک مقدار binding است. یک مشخصه state باید مقدار را در taskName ذخیره کند و به ویو امکان میدهد که موارد تغییر مقادیر را مشاهده کرده و بهروزرسانی کند.
3.2 افزودن وظیفه به Core Data
ابتدا باید یک دکمه اضافه کنیم تا وقتی که کاربر، وظیفه را وارد کرد، بتواند با فشردن آن، وظیفه را در لیست خود اضافه کند. به این منظور باید TextField را در یک HStack قرار دهیم و سپس یک ()Button اضافه کنیم. زمانی که دکمه را اضافه میکنیم، اکشن آن باید ()self.addTask باشد و برچسب دکمه نیز به صورت Text("Add Task") است. کد ما در body به صورت زیر است:
اکنون Xcode خطایی به صورت زیر نمایش میدهد:
معنای آن این است که باید تابع ()addTask را اضافه کنیم. پس از متغیر body کد زیر را اضافه کنید:
در کد فوق در ()addTask یک شیء جدید Task اضافه کرده و سپس خصوصیتهای متناظر را به مقادیر newTask میدهیم. در ادامه از ()save استفاده میکنیم تا آن را به Core Data اضافه کنیم. اینک UI ما به صورت زیر در آمده است:
3.3 ایجاد لیست وظایف
اینک زمان آن رسیده است که لیست وظایف را ایجاد کنیم. ابتدا باید یک درخواست واکشی برای دریافت وظایف اضافه شده ارسال کنیم. کد زیر را به ContentView اضافه میکنیم:
در کد فوق کارهای زیر را انجام میدهیم:
- Entity تعیین میکند که کدام موجودیت Core Data را بازیابی میکنیم.
- sortDescriptors شیوه مرتبسازی موجودیتها را توصیف میکند.
- predicate به عنوان یک فیلتر عمل میکند.
از این رو در کد فوق همه وظایفی که تکمیل نشدهاند را درخواست میکنیم. این موارد بر اساس تاریخ از جدید به قدیم مرتبسازی میشوند. سپس باید یک لیست ایجاد کنیم که وظایف را نمایش دهد. بدین منظور HStack را درون یک VStack جای میدهیم. کد آن به صورت زیر است:
اکنون میتوانیم یک لیست اضافه کنیم. پس از HStack کد زیر را اضافه کنید:
بدین ترتیب یک لیست زیر TextField اضافه شده و UI به صورت زیر درمیآید:
در ادامه باید Hi را به تعداد وظایفی که داریم تکرار کنیم. به این منظور Text("Hi") را درون ForEach به صورت زیر قرار دهید:
لزومی به تعیین id برای notCompletedTasks در ForEach وجود ندارد، زیرا Task به لطف کاری که در گام 2.3 راهنما انجام دادیم با Identifiable سازگار است. اینک اگر اپلیکیشن را اجرا کنید و یک نام وظیفه وارد کنید، با زدن روی دکمه Add Task ردیف دیگری از Hi ایجاد میشود. در ادامه یک struct جدید برای نمای TaskRow ایجاد میکنیم که وظیفه موجود در ContentView.swift را میگیرد. کد زیر را بالاتر از ()ContentView اضافه کنید:
درون Text از عملگر ادغام تهی ?? استفاده کردیم تا یک مقدار پیشفرض به آن بدهیم. دلیل این که این کار را انجام دادیم آن است که مقدار خصوصیت Task به صورت Optional است و ممکن است مقداری نداشته باشد. اکنون درون ForEach مقدار Text را با TaskRow(task) عوض میکنیم. بدین ترتیب فایل ContentView.swift اکنون باید به صورت زیر باشد:
ظاهر اپلیکیشن نیز در این مرحله مانند زیر است:
4. علامتگذاری یک وظیفه به صورت تکمیل شده
اکنون باید وظیفهها را به صورت تکمیلشده علامتگذاری کنیم. به این ترتیب آن وظیفهها دیگر در لیست ظاهر نمیشوند. ابتدا TaskRow را درون یک Button قرار دهید و اکشن دکمه را نیز self.updateTask(task) قرار دهید تا به صورت زیر دربیاید:
سپس باید یک تابع به نام updateTask ایجاد میکنیم که بتونیم عملاً وظیفه را بهروزرسانی کرده و آن را به صورت تکمیلشده علامتگذاری کنیم. پس از addTask خط زیر را اضافه کنید:
استفاده از _ نشان میدهد که میتوانیم برچسب آرگومان را در زمان فراخوانی تابع نادیده بگیریم. در ادامه تابع را به صورت زیر مینویسیم:
در کد فوق ابتدا یک ثابت برای مقدار جدید isComplete برای وظیفه تعیین کردیم. سپس id وظیفه را روی یک مقدار ثابت قرار دادیم تا به صورت پیشبینی مورد استفاده دهیم. در ادامه باید یک درخواست واکشی ایجاد کنیم که یک وظیفه خاص که قرار ست بهروزرسانی شود را میگیرد. در ادامه بهروزرسانی را اجرا میکنیم.
اکنون اگر اپلیکیشن را اجرا کنید، میتوانید یک وظیفه جدید اضافه کرده و سپس روی آن ضربه بزنید تا به صورت تکمیلشده علامتگذاری شود. از آنجا که در لیست تنها از وظایف تکمیلنشده استفاده میکنیم، وظایف تکمیلشده دیگر در لیست ظاهر نخواهند شد. تصویر زیر اپلیکیشن نهایی را نمایش میدهد:
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی
- مجموعه آموزشهای دروس علوم و مهندسی کامپیوتر
- ساخت اپلیکیشن چت برای iOS با SwiftUI — از صفر تا صد
- ساخت نمودارهای میلهای در SwiftUI — از صفر تا صد
- ساخت اپلیکیشن با Firebase و SwiftUI — از صفر تا صد
==