ساخت تایمر با Swift و SwiftUI — از صفر تا صد

۶۳ بازدید
آخرین به‌روزرسانی: ۱۲ مهر ۱۴۰۲
زمان مطالعه: ۵ دقیقه
ساخت تایمر با Swift و SwiftUI — از صفر تا صد

در این مقاله قصد داریم اقدام به ساخت تایمر با Swift و SwiftUI بکنیم. بدین ترتیب در یک فرایند گام به گام از ابتدای طراحی یک اپلیکیشن تا اجرای نهایی تایمر کامل شده با روش برنامه‌نویسی سوئیفت و SwiftUI آشنا خواهید شد.

گام 1: آغاز پروژه جدید

یک پروژه جدید در Xcode باز کنید. قالب آن باید یک اپلیکیشن با «نمای منفرد» (Single View) ‌باشد. زبان اپلیکیشن را روی سوئیفت تنظیم کنید و «رابط کاربری» (User Interface) را نیز روی SwiftUI قرار دهید. مقدار «نام محصول» (Product Name) را هر چه دوست دارید بگذارید. ما اپلیکیشن خود را Count Up Timer می‌گذاریم.

ساخت تایمر با Swift و SwiftUI

گام 2: افزودن متغیرها

در این بخش برخی متغیرها اضافه می‌کنیم تا ساعت، دقیقه و ثانیه را که باید روی صفحه نمایش یابند در خود ذخیره سازند.

در فایل ContentView.swift خطوط 6 تا 8 قطعه کد زیر را اضافه کنید:

1import SwiftUI
2
3struct ContentView: View {
4  
5  // Add lines 6 -> 8
6  @State var hours: Int = 0
7  @State var minutes: Int = 0
8  @State var seconds: Int = 0
9  
10  var body: some View {
11    Text("Hello, World!")
12  }
13}
14
15struct ContentView_Previews: PreviewProvider {
16  static var previews: some View {
17    ContentView()
18  }
19}

این سه متغیر یعنی hours ،minutes و seconds با استفاده از پوشش مشخصه ‎@State اعلان شده‌اند تا در زمان تغییر یافتن مقدار، متن مربوطه به‌روزرسانی شود.

گام 3: طراحی رابط کاربری

اکنون باید عملاً به طراحی UI بپردازیم. ما قصد داریم یک تایمر در میانه صفحه داشته باشیم و سپس دکمه‌های آغاز/مکث تایمر و ریست کردن تایمر روی صفر را قرار بدهیم. نخستین کاری که باید انجام دهیم افزودن یک VStack در body است. به این منظور روی Text("Hello, World!") راست-کلیک کرده و گزینه Embed in VStack را انتخاب کنید. اینک کد شما باید مانند زیر شده باشد:

1var body: some View {
2  VStack {
3    Text("Hello, World!")
4  }
5}

نمایش مقادیر تایمر

در ادامه باید متغیرها را مورد استفاده قرار دهیم. می‌خواهیم !Hello, World را به \(hours):\(minutes):\(seconds) تغییر دهیم. اگر بوم را باز کرده و آن را resume کنید، می‌بینید که مقدار 0:0:0 روی دستگاه نمایش می‌یابد.

شاید تعجب کنید که چرا از ساختار ()\ در پیرامون نام متغیر استفاده کرده‌ایم. این ممیز و پرانتز به کامپایلر اعلام می‌کند که درون پرانتز، کدی قرار دارد. از این رو برنامه محتوای متغیر را به جای نام آن نمایش می‌‌دهد.

افزودن دکمه

اکنون زمان آن رسیده است که دکمه‌ها را اضافه کرده و آن‌ها را وادار به انجام دادن کاری بکنیم. ابتدا باید یک متغیر حالت جدید اضافه کنیم که مشخص سازد آیا تایمر آغاز شده یا مکث یافته است. درست پس از اعلان seconds مقدار زیر را اضافه می‌کنیم:

@State var timerIsPaused: Bool = true

سپس در ادامه ()Text باید یک گزاره if اضافه کنیم تا در زمان مکث یافتن تایمر یک نما دیده شود و در ادامه با راه‌اندازی مجدد پنهان شود. قطعه کد زیر این گزاره if را نمایش می‌دهد:

1var body: some View {
2  VStack {
3    Text("\(hours):\(minutes):\(seconds)")
4    if timerIsPaused {
5      Text("PAUSED")
6    } else {
7      Text("NOT Paused")
8    }
9  }
10}

اینک باید Text را به Buttons عوض کنیم و از SF Symbol برای شروع، مکث و ریست کردن تایمر بهره بگیریم. اگر timerIsPaused مقدار true داشته باشد در این صورت باید یک آیکون play برای شروع تایمر نمایش دهیم و یک آیکون رو به عقب نیز برای ریست نمایش نمی‌یابد. به این منظور باید از Image(systemName: String) به عنوان برچسب‌های دکمه استفاده کنیم. این دو دکمه همچنین باید در یک HStack در کنار هم قرار بگیرند. اکنون اگر timerIsPaused مقدار false داشته باشد، باید یک آیکون مکث برای توقف تایمر نشان دهیم. قطعه کد زیر دکمه‌ها را در یک گزاره if نمایش می‌دهد:

1if timerIsPaused {
2  HStack {
3    Button(action:{
4      print("RESTART")
5    }){
6      Image(systemName: "backward.end.alt")
7        .padding(.all)
8    }
9    .padding(.all)
10    Button(action:{
11      print("START")
12    }){
13      Image(systemName: "play.fill")
14        .padding(.all)
15    }
16    .padding(.all)
17  }
18} else {
19  Text("NOT Paused")
20}

گام 4: آغاز تایمر

اینک زمان آن رسیده است که تایمر آغاز شود. ما از Timer که یک کارکرد داخلی سوئیفت است، بهره می‌گیریم. باید یک تایمر تکراری بسازیم که در هر ثانیه یک ثانیه به مقدارش اضافه می‌شود. در ادامه یک متغیر برای حالت نخست اضافه می‌کنیم. بنابراین پس از timerIsPaused یک مقدار به صورت زیر اضافه می‌کنیم:

@State var timer: Timer? = nil

این دستور یک متغیر برای ذخیره‌سازی تایمر در آن اعلان می‌کند، اما در عمل یک تایمر را هنوز در خود جای نداده است، چون در زمان آغاز به کار تایمر آن را اضافه خواهیم کرد.

سپس باید تابعی بنویسیم که تایمر را آغاز می‌کند و مقدار timerIsPaused را به false عوض می‌کند. نام این تابع را ()startTimer می‌گذاریم. در این تابع یک خط به صورت timerIsPaused = false اضافه می‌کنیم. سپس یک تایمر اضافه می‌شود. به قطعه کد زیر توجه کنید:

1  func startTimer(){
2    timerIsPaused = false
3    // 1. Make a new timer
4    timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true){ tempTimer in
5      // 2. Check time to add to H:M:S                                                               
6      if self.seconds == 59 {
7        self.seconds = 0
8        if self.minutes == 59 {
9          self.minutes = 0
10          self.hours = self.hours + 1
11        } else {
12          self.minutes = self.minutes + 1
13        }
14      } else {
15        self.seconds = self.seconds + 1
16      }
17    }
18  }

در ادامه اتفاقاتی که در خطوط 3 تا 5 کد فوق می‌افتد را توضیح می‌دهیم.

ساخت یک تایمر جدید

این همان جایی است که تایمر عملاً ساخته می‌شود. ما از یک تایمر زمان‌بندی استفاده می‌کنیم که هر ثانیه یک بار چیزی را تحریک می‌کند.

  • withTimeInterval – برای تعیین فراوانی هر عمل که درون کلوژر اجرا می‌شود بر حسب ثانیه مورد استفاده قرار می‌گیرد. مقدار آن را روی یک تعیین کرده‌ایم تا seconds هر ثانیه یک واحد افزایش یابد.
  • Repeats – این مقدار باید روی true تنظیم شود تا کد درون کلوژر هر ثانیه یک بار اجرا شود. اگر مقدار آن false باشد، عملیات درون کلوژر تنها یک بار اجرا خواهد شد.

بررسی زمان برای افزودن

در کد زیر بررسی می‌کنیم چه زمانی باید مقادیر متغیرهای seconds ،minutes و hours افزایش یابند. ما از متد کلوژر برای آغاز یک تایمر جدید استفاده کرده‌ایم تا تابع را در یک فراخواننده Objective-C قرار ندهیم. زمانی که تابع نوشته شد، باید مطمئن شویم که آن را در یک دکمه فراخوانی می‌کنیم. کد دکمه شروع به صورت زیر است:

1Button(action:{
2  self.startTimer()
3}){
4  Image(systemName: "play.fill")
5    .padding(.all)
6}
7  .padding(.all)

گام 5: توقف تایمر

اینک زمان کدنویسی یک کارکرد دیگر تایمر یعنی متوقف ساختن آن رسیده است. این تابع را ()stopTimer می‌نامیم. در این تایمر باید مقدار timerIsPaused را به صورت false تعیین کنیم و تایمری که هم اینک کار می‌کند را از بین ببریم. برای از بین بردن تایمر باید تابع ()invalidate را روی تایمر فراخوانی کنیم که امکان آغاز مجدد تایمر را نمی‌دهد. کد تابع به صورت زیر است:

1  func stopTimer(){
2    timerIsPaused = true
3    timer?.invalidate()
4    timer = nil
5  }

اینک باید مطمئن شویم که وقتی دکمه Stop زده می‌شود، تابع فراخوانی خواهد شد. بدین ترتیب فایل ContentView.swift تا اینجا به صورت زیر درآمده است:

1//
2//  ContentView.swift
3//  count-up-timer
4//
5//  Created by Maegan Wilson on 4/28/20.
6//  Copyright © 2020 Maegan Wilson. All rights reserved.
7//
8import SwiftUI
9
10struct ContentView: View {
11  
12  @State var hours: Int = 0
13  @State var minutes: Int = 0
14  @State var seconds: Int = 0
15  @State var timerIsPaused: Bool = true
16  
17  @State var timer: Timer? = nil
18  
19  var body: some View {
20    VStack {
21      Text("\(hours):\(minutes):\(seconds)")
22      if timerIsPaused {
23        HStack {
24          Button(action:{
25            print("RESTART")
26          }){
27            Image(systemName: "backward.end.alt")
28              .padding(.all)
29          }
30          .padding(.all)
31          Button(action:{
32            self.startTimer()
33            print("START")
34          }){
35            Image(systemName: "play.fill")
36              .padding(.all)
37          }
38          .padding(.all)
39        }
40      } else {
41        Button(action:{
42          print("STOP")
43          self.stopTimer()
44        }){
45          Image(systemName: "stop.fill")
46            .padding(.all)
47        }
48        .padding(.all)
49      }
50    }
51  }
52  
53  func startTimer(){
54    timerIsPaused = false
55    timer = Timer.scheduledTimer(withTimeInterval: 1, repeats: true){ tempTimer in
56      if self.seconds == 59 {
57        self.seconds = 0
58        if self.minutes == 59 {
59          self.minutes = 0
60          self.hours = self.hours + 1
61        } else {
62          self.minutes = self.minutes + 1
63        }
64      } else {
65        self.seconds = self.seconds + 1
66      }
67    }
68  }
69  
70  func stopTimer(){
71    timerIsPaused = true
72    timer?.invalidate()
73    timer = nil
74  }
75}
76
77struct ContentView_Previews: PreviewProvider {
78  static var previews: some View {
79    ContentView()
80  }
81}

گام 6: ریست کردن ساعت

این ساده‌ترین تابع پروژه ما است. کافی است مقادیر متغیرهای hour ،minutes و seconds را روی صفر تنظیم کنیم.

1func restartTimer(){
2  hours = 0
3  minutes = 0
4  seconds = 0
5}

اکنون زمانی که دکمه reset زده شود، با استفاده از ()self.restartTimer آن را فراخوانی می‌کنیم. بدین ترتیب کار طراحی تایمر ما به پایان می‌رسد.

ساخت تایمر با Swift و SwiftUI

کد کامل این پروژه را می‌توانید در این ریپوی گیت‌لب (+) مشاهده کنید.

اگر این مطلب برای شما مفید بوده است، آموزش‌های زیر نیز به شما پیشنهاد می‌شوند:

==

بر اساس رای ۰ نفر
آیا این مطلب برای شما مفید بود؟
اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.
منابع:
better-programming
نظر شما چیست؟

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *