آشنایی با تازه های SwiftUI 2.0 | راهنمای کاربردی
کنفرانس WWDC 2020 اخیراً برگزار شد و در آن خبرهای جدید زیادی برای جامعه توسعهدهندگان اپل وجود داشت. یکی از مهمترین زمینهها که کاربران زیادی در انتظار خبرهای جدید از آن بودند، SwiftUI 2.0 است. در این مقاله با تازه های SwiftUI 2.0 آشنا خواهیم شد.
بهینهسازیهای جدید در SwiftUI همگی دارای ماهیتی افزایشی (سازگار با نسخه قدیمی) هستند. این بدان معنی است که هیچ خبری از منسوخ شدن قابلیتها یا تغییراتی که موجب ایجاد ناسازگاری با نسخه قدیمی SwiftUI 2.0 شوند، وجود نداشته است.
در این مقاله به بررسی اجمالی کنترلهای جدید SwiftUI میپردازیم که با iOS 14 معرفی شدهاند. برای اجرای این موارد به Xcode 12 بتا و در نتیجه macOS با نسخه کمینه 10.15.4 نیاز خواهید داشت.
نقطه آغاز اپلیکیشن جدید در SwiftUI
تا به اکنون برای تعیین نما (View)-ی آغازین SwiftUI باید از AppDelegates و SceneDelegates استفاده میکردیم.
از نسخه سوئیفت نسخه 5.3 به بعد یک نقطه ورودی مبتنی بر نوع برای برنامهها معرفی شده است که میتوان با استفاده از خصوصیت @main آن را تعیین کرد و نسخه جدید SwiftUI نیز به طور هوشمندانهای از این قابلیت بهره میگیرد.
SwiftUI اکنون struct زیر را ارائه میکند که به محض اجرای اپلیکیشن فراخوانی میشود:
1@main
2struct WhatsNewiOS14SwiftUIApp: App {
3 var body: some Scene {
4 WindowGroup {
5 ContentView()
6 }
7 }
8}
WindowGroup یک مشخصه «صحنه» (Scene) داخلی دارد، به طوری که میتوانیم سلسله نمای آغازین را تعریف کنیم. ما میتوانیم TabView ،NavigationViews یا App Clips را درون مشخصه محاسبهشده WindowGroup تنظیم کنیم.
LazyVStack و LazyHStack در SwiftUI
تا پیش از این نماهای SwiftUI بیدرنگ بارگذاری میشدند که منجر به مشکلات عملکردی و حافظه در زمان مقداردهی حجم بالایی از دادهها میشد. در نهایت از نمای مقصد NavigationLink برای بارگذاری محتوا پس از لود اولیه SwiftUI استفاده میشد. این بار اپل پشتههای افقی و عمودی را معرفی کرده است که محتوا را در زمان نیاز بارگذاری میکنند. به این ترتیب، شاهد یک بهینهسازی عملکردی در SwiftUI هستیم. «بارگذاری کُند» (Lazy loading) در لیستهای SwiftUI نیز معرفی شده است. در ادامه مثالی از LazyHStack در SwiftUI میبینید:
1struct ContentView: View {
2
3 var body: some View {
4
5 ScrollView(.horizontal) {
6
7 LazyHStack(spacing: 10) {
8 ForEach(0..<1000) { index in
9 Text("\(index)")
10 .frame(width: 100, height: 200)
11 .border(Color.gray.opacity(0.5), width: 0.5)
12 .background(Color.blue)
13 .cornerRadius(6)
14 }
15 }
16 .padding(.leading, 10)
17 }
18 }
19}
موقعیت اسکرول نما در SwiftUI
نسخه اول SwiftUI به جهت ظرفیتهای ScrollView مشکلات زیادی را متحمل شد. SwiftUI مربوط به iOS 14 عناصر بسیار ضروری ScrollViewReader و ScrollViewProxy را معرفی کرده که موقعیت آفست اسکرول نما را دریافت کرده و آنها را به صورت برنامهنویسیشده جابجا میکند. به این منظور باید نماها را درون یک ScrollViewReader قرار داده و از متد scrollTo به یکی از روشهای زیر استفاده کنیم:
1scrollView.scrollTo(viewId)
2//or
3scrollView.scrollTo(viewId, anchor: .center)
موقعیت اسکرول نما به صورت پیشفرض روی بخش فوقانی نما قرار دارد. امکان تغییر این موقعیت با استفاده از مشخصه anchor وجود دارد. برای نمونه در قطعه کد زیر، زمانی که مشخصه anchor روی مقدار center تنظیم شده باشد، موقعیت اسکرول بسپار بهتر از زمانی دیده میشود که روی leading تنظیم شده باشد.
ProgressView در SwiftUI
تا پیش از این باید از شکلهای SwiftUI برای تکرار ProgressView و UIViewRepresentable خطی جهت ایجاد ProgressView and UIViewRepresentable در SwiftUI استفاده میکردیم. اکنون در SwiftUI مربوط به iOS 14 از پشتیبانی نیتیو ProgressView برخوردار هستیم.
()ProgressView به صورت پیشفرض یک UIActivityIndicator غیر قطعی شبیه به یک نمایشگر پیشرفت ایجاد میکند، در حالی که کد زیر یک ProgressView خطی در SwiftUI میسازد:
1ProgressView("Text", value: 10, total: 100)
با استفاده از progressViewStyle میتوانیم ProgressView را بیش از این سفارشیسازی کنیم. progressViewStyle مقادیر CircularProgressViewStyle و DefaultProgressViewStyle را میگیرد و که امکان ساخت مادیفایرهای سفارشی را نیز فراهم میسازند:
از accentColor برای تعیین رنگ متن در ProgressView استفاده کردهایم، در حالی که foregroundColor به عنوان tint عمل میکند.
برچسبها، لینکها و انتخابگرهای رنگ در SwiftUI
برچسبها (Labels) یکی از مهمترین قابلیتهایی هستند که به نسخه جدید SwiftUI اضافه شدهاند. با استفاده از برچسبها میتوانیم آیکونها را نیز همراه متن به صورت زیر تعیین کنیم:
1Label("SwiftUI 2.0", systemImage: "checkmark.icloud")
درون مشخصه icons میتوان از نمادهای SF، فاصلهای تصویر یا شکلهای خاص SwiftUI استفاده کرد.
نکته: در زمان نگارش این مطلب، icon در راستای بخش فوقانی متن قرار میگیرد که این مسئله به زودی اصلاح خواهد شد.
Link در SwiftUI نیز یک کنترل UI جالب دیگر است که از پشتیبانی نیتیو برای ناوبری یک URL برخوردار است:
1Link("Click me",destination: URL(string: "your_url")!)
لینک به یک مرورگر وب یا در صورتی که لینک سراسری باشد به اپلیکیشن مرتبط هدایت میکند. قابلیت مهم دیگری که به مجموعه ابزارهای SwiftUI اضافه شده است، یک کنترل UI نیتیو به نام ColorPicker است. با استفاده از پوشش مشخصه state میتوانید رنگ انتخاب شده از سوی کاربر را به صورت زیر بهروزرسانی کنید:
1ColorPicker("Sample Picker", selection: $myColor)
TextEditor ،MapKit و Sign In With Apple
در نسخه جدید SwiftUI شاهد معرفی UITextViews هستیم.
1TextEditor(text: $stateProperty)
MapKit نیز که قبلاً باید درون UIViewRepresentable قرار میگرفت، اینک به صورت نیتیو پشتیبانی میشود. امکان ارسال یک MKCoordinateRegion، نمایش مکان کاربر و انجام کارهای مختلف MapKit به صورت مستقیم از خود اینترفیس نمای SwiftUI وجود دارد.
1Map(mapRect:interactionModes:showsUserLocation: userTrackingMode:
SignInWithAppleButton نیز یک قابلیت تازه دیگر است که موجب میشود با افزودن یک دکمه، امکان ورود با حساب کاربری اصل را به کاربر بدهیم. به این منظور کافی است یک دکمه را تنظیم کرده و یک وهله از struct ساخته و آرگومان label را به صورت یکی از حالتهای .signUp یا .signIn تعیین کنیم تا نوع احراز هویت مشخص شود. برای کسب اطلاعات بیشتر در این خصوص به مستندات رسمی (+) مراجعه کنید.
یک مادیفایر تازه onChange برای گوش دادن به تغییرهای حالت
onChange یک مادیفایر تازه نما است که اکنون در همه نماهای SwiftUI موجود است. این مادیفایر امکان گوش دادن به تغییرهای حالت و اجرای اکشنهایی بر این مبنا روی view را فراهم میسازد. برای نمونه میتوانیم تغییر حالت دکمه را اجرا کرده و TextEditor را طوری تریگر کنیم که پاک شود:
1import SwiftUI
2
3struct ContentView: View {
4
5 @State var currentText: String = "Hi How are you?"
6 @State var clearText: Bool = false
7
8 var body: some View {
9
10 VStack{
11
12 TextEditor(text: $currentText)
13 .onChange(of: clearText) { value in
14 if clearText{
15 currentText = ""
16 }
17 }
18
19 Button(action: {clearText = true}, label: {
20 Text("Clear Text Editor")
21 })
22 }
23 }
24}
نکته: مشخصه حالت clearText نخستین باری که بدنه SwiftUI وهلهسازی شود، موجب تحریک مادیفایر onChange به صورت خودکار میشود.
استایل جدید برای کنترل صفحه با TabView در SwiftUI
UIPageViewController اینک راه خود را به سمت SwiftUI گشوده است. در نسخه 14 iOS، SwiftUI یک سبک جدید برای درج کنترلهای صفحه در نماهای SwiftUI معرفی کرده است. کافی است ()PageTabViewStyle را در مادیفایر ()tabViewStyle. خود به صورت زیر تعیین کنید:
1import SwiftUI
2
3struct ContentView: View {
4
5 let colors: [Color] = [.red, .green, .yellow, .blue]
6
7 var body: some View {
8
9 TabView {
10 ForEach(0..<6) { index in
11 Text("Tab \(index)")
12 .font(.title)
13 .frame(maxWidth: .infinity, maxHeight: .infinity)
14 .background(colors[index % colors.count])
15 .cornerRadius(8)
16 }
17 }.tabViewStyle(PageTabViewStyle())
18 }
19}
تصویر خروجی کد فوق در Xcode 12 به صورت زیر است:
گریدهای SwiftUI
CollectionView و Compositional Layouts اینک از SwiftUI در iOS 1 حذف شدهاند. اما برخی کانتینرهای جدید برای لیآوتهای مبتنی بر گرید معرفی شده است که امکان تعیین نماهای فرزند را در LazyHGrid یا LazyVGrid میدهد.
هر عنصر یک گرید LazyHGrid یا LazyVGrid به صورت یک GridItem است. ما میتوانیم جهتگیری، فاصلهبندی و اندازه GridItem را تعیین کنیم. در قطعه کد زیر یک لیآوت گرید عمودی در SwiftUI ساختهایم که شامل سه ستون است:
1struct ContentView: View {
2
3
4 let colors: [Color] = [.red, .green, .yellow, .blue]
5
6 var columns: [GridItem] =
7 Array(repeating: .init(.flexible(), alignment: .center), count: 3)
8
9 var body: some View {
10 ScrollView {
11
12 LazyVGrid(columns: columns, spacing: 10) {
13 ForEach(0...100, id: \.self) { index in
14 Text("Tab \(index)")
15 .frame(width: 110, height: 200)
16 .background(colors[index % colors.count])
17 .cornerRadius(8)
18 }
19 }
20 }
21 }
22}
چنان که میبیند صرفاً با چند خط کد یک لیآوت گرید قابل سفارشیسازی در SwiftUI برای iOS 14 ساختهایم.
سخن پایانی
در این مقاله به معرفی تازههای SwiftUI 2.0 پرداختیم. البته موارد زیاد دیگری وجود دارند که قابل بررسی هستند. از آن جمله پشتیبانی SwiftUI از OutlineGroups و VideoPlayer است. مهمتر از همه نماسازهای SwiftUI اینک از گزارههای if let و switch پشتیبانی میکنند. در هر حال امیدواریم این مطلب مورد توجه شما قرار گرفته باشد.