ساخت تایمر شمارش معکوس با SwiftUI – از صفر تا صد


چنان که میدانید اپل اخیراً فریمورک جدیدی به نام SwiftUI ارائه کرده است که امکان ساخت اینترفیس اپلیکیشنها را به روشی جدید و 100 درصد منطبق با زبان سوئیفت فراهم میآورد. در این راهنما با بررسی یک مثال به صورت ساخت تایمر شمارش معکوس با SwiftUI با این فریمورک جدید بیشتر آشنان میشویم.
پیشنیازها
برای آغاز کار با SwiftUI باید به صفحه دانلود (+) اپل بروید و آخرین نسخه از Xcode 11 و macOS Catalina 10.15 را دانلود کنید. SwiftUI به همراه Xcode روی Mojave نیز کار میکند، اما پیشنمایش در این شرایط کار نخواهد کرد. ضمناً لازم به ذکر است که فریمورک SwiftUI تنها برای iOS 13 ،macOS 10.15 ،watchOS 6 و iPadOS 13 کاربردی است.
ایجاد پروژه SwiftUI
یک پروژه iOS جدید با Xcode 11 بسازید و مطمئن شوید که کادر SwiftUI را تیک زدهاید:
اینک که پروژه را ایجاد کردهاید، نگاهی به فایل ContentView.swift و پیادهسازی متغیر body بیندازید. این همان جایی است که view را در SwiftUI پیادهسازی خواهیم کرد. وضعیت آن اکنون باید به صورت زیر باشد:
1var body: some View {
2 Text("Hello World")
3}
ایجاد منطق تایمر
برای این که بتوانیم اینترفیس خود را هر ثانیه یک بار رفرش کنیم، باید از یک تایمر استفاده کنیم و تاریخی برای ساخت تایمر معکوس تعیین نماییم.
1@State var nowDate: Date = Date()
2let referenceDate: Date
3var timer: Timer {
4 Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {_ in
5 self.nowDate = Date()
6 }
7}
توجه کنید که State@ اینترفیس ما را هر بار که تاریخ بهروزرسانی میشود از نو میسازد و کاری که میخواهیم انجام دهیم را درون بلوک کدی که تایمر اجرا میکند نشان میدهد.
افزودن منطق شمارش معکوس درون برچسب
اکنون که تایمر ما هر ثانیه یک بار تحریک میشود، میتوانیم اینترفیس را بر مبنای تاریخ جاری بهروزرسانی کنیم. بدین منظور تابعی میسازیم که یک رشته شمارش معکوس بازگشت میدهد:
1func countDownString(from date: Date, until nowDate: Date) -> String {
2 let calendar = Calendar(identifier: .gregorian)
3 let components = calendar
4 .dateComponents([.day, .hour, .minute, .second]
5 ,from: nowDate,
6 to: date)
7 return String(format: "%02dd:%02dh:%02d:%02ds",
8 components.day ?? 00,
9 components.hour ?? 00,
10 components.minute ?? 00,
11 components.second ?? 00)
12}
در ادامه تابع را به جای متن hello world فراخوانی میکنیم:
1var body: some View {
2 Text(countDownString(from: referenceDate, until: date))
3}
اما این برچسب بهروزرسانی نمیشود، زیرا زمان کُند است و تا زمانی که تایمر فراخوانی نشود وجود نخواهد داشت و نمیتواند تحریک شود.
متحرک ساختن تایمر
یک روش برای مقداردهی اولیه تایمر، افزودن یک کلوژر onAppear به عنصر Text است تا وقتی متن ظاهر میشود تایمر را ایجاد کرده و حلقه را آغاز نماید:
1var body: some View {
2 Text(countDownString(from: referenceDate, until: nowDate))
3 .onAppear(perform: {
4 let _ = self.timer
5 })
6 }
شاید این بهترین روش برای انجام این کار نباشد، اما به هر حال کار میکند. زمانی که view ناپدید میشود برای جلوگیری از نشت حافظه باید تایمر را invalidate کنید. کد کامل به صورت زیر است:
1import SwiftUI
2
3struct CountDownView : View {
4
5 @State var nowDate: Date = Date()
6 let referenceDate: Date
7 var timer: Timer {
8 Timer.scheduledTimer(withTimeInterval: 1, repeats: true) {_ in
9 self.nowDate = Date()
10 }
11 }
12
13 var body: some View {
14 Text(countDownString(from: referenceDate))
15 .font(.largeTitle)
16 .onAppear(perform: {
17 _ = self.timer
18 })
19 }
20
21 func countDownString(from date: Date) -> String {
22 let calendar = Calendar(identifier: .gregorian)
23 let components = calendar
24 .dateComponents([.day, .hour, .minute, .second],
25 from: nowDate,
26 to: referenceDate)
27 return String(format: "%02dd:%02dh:%02dm:%02ds",
28 components.day ?? 00,
29 components.hour ?? 00,
30 components.minute ?? 00,
31 components.second ?? 00)
32 }
33
34}
بدین ترتیب موفق شدیم یک تایمر شمارش معکوس با استفاده از SwiftUI بسازیم.
اگر این مطلب برای شما مفید بوده است، آموزشهای زیر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای برنامهنویسی
- آموزش برنامه نویسی Swift (سوئیفت) برای برنامه نویسی iOS
- مجموعه آموزشهای دروس علوم و مهندسی کامپیوتر
- آموزش سوئیفت (Swift) — مجموعه مقالات مجله فرادرس
- آموزش سوئیفت (Swift): معماری MVC — بخش هجدهم
==