برنامه نویسی 166 بازدید

کنفرانس 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 2.0

SwiftUI اکنون struct زیر را ارائه می‌کند که به محض اجرای اپلیکیشن فراخوانی می‌‌شود:

@main
struct WhatsNewiOS14SwiftUIApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

WindowGroup یک مشخصه «صحنه» (Scene) داخلی دارد، به طوری که می‌توانیم سلسله نمای آغازین را تعریف کنیم. ما می‌توانیم TabView ،NavigationViews یا App Clips را درون مشخصه محاسبه‌شده WindowGroup تنظیم کنیم.

LazyVStack و LazyHStack در SwiftUI

تا پیش از این نماهای SwiftUI بی‌درنگ بارگذاری می‌شدند که منجر به مشکلات عملکردی و حافظه در زمان مقداردهی حجم بالایی از داده‌ها می‌شد. در نهایت از نمای مقصد NavigationLink برای بارگذاری محتوا پس از لود اولیه SwiftUI استفاده می‌شد. این بار اپل پشته‌های افقی و عمودی را معرفی کرده است که محتوا را در زمان نیاز بارگذاری می‌کنند. به این ترتیب، شاهد یک بهینه‌سازی عملکردی در SwiftUI هستیم. «بارگذاری کُند» (Lazy loading) در لیست‌های SwiftUI نیز معرفی شده است. در ادامه مثالی از LazyHStack در SwiftUI می‌بینید:

struct ContentView: View {

    var body: some View {
    
        ScrollView(.horizontal) {
            
            LazyHStack(spacing: 10) {
                ForEach(0..<1000) { index in
                    Text("\(index)")
                            .frame(width: 100, height: 200)
                            .border(Color.gray.opacity(0.5), width: 0.5)
                            .background(Color.blue)
                            .cornerRadius(6)
                }
            }
            .padding(.leading, 10)
        }
    }
}

تازه های SwiftUI 2.0

موقعیت اسکرول نما در SwiftUI

نسخه اول SwiftUI به جهت ظرفیت‌های ScrollView مشکلات زیادی را متحمل شد. SwiftUI مربوط به iOS 14 عناصر بسیار ضروری ScrollViewReader و ScrollViewProxy را معرفی کرده که موقعیت آفست اسکرول نما را دریافت کرده و آن‌ها را به صورت برنامه‌نویسی‌شده جابجا می‌کند. به این منظور باید نماها را درون یک ScrollViewReader قرار داده و از متد scrollTo به یکی از روش‌های زیر استفاده کنیم:

scrollView.scrollTo(viewId)
//or
scrollView.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 می‌سازد:

ProgressView("Text", value: 10, total: 100)

با استفاده از progressViewStyle می‌توانیم ProgressView را بیش از این سفارشی‌سازی کنیم. progressViewStyle مقادیر CircularProgressViewStyle و DefaultProgressViewStyle را می‌گیرد و که امکان ساخت مادیفایرهای سفارشی را نیز فراهم می‌سازند:

تازه های SwiftUI 2.0

از accentColor برای تعیین رنگ متن در ProgressView استفاده کرده‌ایم، در حالی که foregroundColor به عنوان tint عمل می‌کند.

برچسب‌ها، لینک‌ها و انتخاب‌گرهای رنگ در SwiftUI

برچسب‌ها (Labels) یکی از مهم‌ترین قابلیت‌هایی هستند که به نسخه جدید SwiftUI اضافه شده‌اند. با استفاده از برچسب‌ها می‌توانیم آیکون‌ها را نیز همراه متن به صورت زیر تعیین کنیم:

Label("SwiftUI 2.0", systemImage: "checkmark.icloud")

درون مشخصه icons می‌توان از نمادهای SF، فاصل‌های تصویر یا شکل‌های خاص SwiftUI استفاده کرد.

نکته: در زمان نگارش این مطلب، icon در راستای بخش فوقانی متن قرار می‌گیرد که این مسئله به زودی اصلاح خواهد شد.

Link در SwiftUI نیز یک کنترل UI جالب دیگر است که از پشتیبانی نیتیو برای ناوبری یک URL برخوردار است:

Link("Click me",destination: URL(string: "your_url")!)

لینک به یک مرورگر وب یا در صورتی که لینک سراسری باشد به اپلیکیشن مرتبط هدایت می‌کند. قابلیت مهم دیگری که به مجموعه ابزارهای SwiftUI اضافه شده است، یک کنترل UI نیتیو به نام ColorPicker است. با استفاده از پوشش مشخصه state می‌توانید رنگ انتخاب شده از سوی کاربر را به صورت زیر به‌روز‌رسانی کنید:

ColorPicker("Sample Picker", selection: $myColor)

TextEditor ،MapKit و Sign In With Apple

در نسخه جدید SwiftUI شاهد معرفی UITextViews هستیم.

TextEditor(text: $stateProperty)

MapKit نیز که قبلاً باید درون UIViewRepresentable قرار می‌گرفت، اینک به صورت نیتیو پشتیبانی می‌شود. امکان ارسال یک MKCoordinateRegion، نمایش مکان کاربر و انجام کارهای مختلف MapKit به صورت مستقیم از خود اینترفیس نمای SwiftUI وجود دارد.

Map(mapRect:interactionModes:showsUserLocation: userTrackingMode:

SignInWithAppleButton نیز یک قابلیت تازه دیگر است که موجب می‌شود با افزودن یک دکمه، امکان ورود با حساب کاربری اصل را به کاربر بدهیم. به این منظور کافی است یک دکمه را تنظیم کرده و یک وهله از struct ساخته و آرگومان label را به صورت یکی از حالت‌های ‎.signUp یا ‎.signIn تعیین کنیم تا نوع احراز هویت مشخص شود. برای کسب اطلاعات بیشتر در این خصوص به مستندات رسمی (+) مراجعه کنید.

یک مادیفایر تازه onChange برای گوش دادن به تغییرهای حالت

onChange یک مادیفایر تازه نما است که اکنون در همه نماهای SwiftUI موجود است. این مادیفایر امکان گوش دادن به تغییرهای حالت و اجرای اکشن‌هایی بر این مبنا روی view را فراهم می‌سازد. برای نمونه می‌توانیم تغییر حالت دکمه را اجرا کرده و TextEditor را طوری تریگر کنیم که پاک شود:

import SwiftUI

struct ContentView: View {

    @State var currentText: String = "Hi How are you?"
    @State var clearText: Bool = false

    var body: some View {

        VStack{

            TextEditor(text: $currentText)
                .onChange(of: clearText) { value in
                    if clearText{
                        currentText = ""
                    }
                }
            
            Button(action: {clearText = true}, label: {
                Text("Clear Text Editor")
            })
        }
    }
}

نکته: مشخصه حالت clearText نخستین باری که بدنه SwiftUI وهله‌سازی شود، موجب تحریک مادیفایر onChange به صورت خودکار می‌شود.

استایل جدید برای کنترل صفحه با TabView در SwiftUI

UIPageViewController اینک راه خود را به سمت SwiftUI گشوده است. در نسخه 14 iOS، SwiftUI یک سبک جدید برای درج کنترل‌های صفحه در نماهای SwiftUI معرفی کرده است. کافی است ()PageTabViewStyle را در مادیفایر ()tabViewStyle. خود به صورت زیر تعیین کنید:

import SwiftUI

struct ContentView: View {

    let colors: [Color] = [.red, .green, .yellow, .blue]

    var body: some View {

            TabView {
                ForEach(0..<6) { index in
                        Text("Tab \(index)")
                        .font(.title)
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                        .background(colors[index % colors.count])
                        .cornerRadius(8)
                    }
            }.tabViewStyle(PageTabViewStyle())
    }
}

تصویر خروجی کد فوق در Xcode 12 به صورت زیر است:

گریدهای SwiftUI

CollectionView و Compositional Layouts اینک از SwiftUI در iOS 1 حذف شده‌اند. اما برخی کانتینرهای جدید برای لی‌آوت‌های مبتنی بر گرید معرفی شده است که امکان تعیین نماهای فرزند را در LazyHGrid یا LazyVGrid می‌دهد.

هر عنصر یک گرید LazyHGrid یا LazyVGrid به صورت یک GridItem است. ما می‌توانیم جهت‌گیری، فاصله‌بندی و اندازه GridItem را تعیین کنیم. در قطعه کد زیر یک لی‌آوت گرید عمودی در SwiftUI ساخته‌ایم که شامل سه ستون است:

struct ContentView: View {
    
    
    let colors: [Color] = [.red, .green, .yellow, .blue]
    
    var columns: [GridItem] =
        Array(repeating: .init(.flexible(), alignment: .center), count: 3)
    
    var body: some View {
        ScrollView {

            LazyVGrid(columns: columns, spacing: 10) {
                ForEach(0...100, id: \.self) { index in
                    Text("Tab \(index)")
                        .frame(width: 110, height: 200)
                        .background(colors[index % colors.count])
                    .cornerRadius(8)
                }
            }
        }
    }
}

چنان که می‌بیند صرفاً با چند خط کد یک لی‌آوت گرید قابل سفارشی‌سازی در SwiftUI برای iOS 14 ساخته‌ایم.

سخن پایانی

در این مقاله به معرفی تازه‌های SwiftUI 2.0 پرداختیم. البته موارد زیاد دیگری وجود دارند که قابل بررسی هستند. از آن جمله پشتیبانی SwiftUI از OutlineGroups و VideoPlayer است. مهم‌تر از همه نماسازهای SwiftUI اینک از گزاره‌های if let و switch پشتیبانی می‌کنند. در هر حال امیدواریم این مطلب مورد توجه شما قرار گرفته باشد.

اگر بازخوردی درباره این مطلب دارید یا پرسشی دارید که بدون پاسخ مانده است، آن را از طریق بخش نظرات مطرح کنید.

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

«میثم لطفی» دانش‌آموخته ریاضیات و شیفته فناوری به خصوص در حوزه رایانه است. وی در حال حاضر علاوه بر پیگیری علاقه‌مندی‌هایش در رشته‌های برنامه‌نویسی، کپی‌رایتینگ و محتوای چندرسانه‌ای، در زمینه نگارش مقالاتی با محوریت نرم‌افزار نیز با مجله فرادرس همکاری دارد.

بر اساس رای 1 نفر

آیا این مطلب برای شما مفید بود؟

نظر شما چیست؟

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