/SwiftUI2024

⌨️ Unlocking the Potential of AnyLayout, ViewThatFits, Grid / GridRow, ControlGroup / Menu, @Observable Macro, iOS 17.

Primary LanguageSwift

⌨️ Unlocking the Potential of AnyLayout, ViewThatFits, Grid / GridRow, ControlGroup / Menu, @Observable Macro, iOS 17.

  • Dive deep into the world of advanced layout techniques with this comprehensive tutorial on Grid and GridRow implementation. Learn how to harness the power of SwiftUI to craft stunning user interfaces optimized for iOS 17 and macOS platforms.

  • Explore the intricacies of grid structures, mastering the art of arranging rows, columns, and spacing to perfection.

AnyLayout

import SwiftUI

struct AnyLayoutSwiftUI: View {
    @Environment(\.horizontalSizeClass) private var horizontalSizeClass
    @Environment(\.verticalSizeClass) private var verticalSizeClass
    
    var body: some View {
        VStack(spacing: 10) {
            Text("Horizontal: \(horizontalSizeClass.debugDescription)")
            Text("Vertical: \(verticalSizeClass.debugDescription)")
            
            let layout: AnyLayout = horizontalSizeClass == .compact ? AnyLayout(VStackLayout()) : AnyLayout(HStackLayout())
            
            layout {
                Text("First")
                Text("Second")
                Text("Third")
            }
#Preview {
    AnyLayoutSwiftUI()
}

ViewThatFits

import SwiftUI

struct ViewThatFitsSwiftUI: View {
    var body: some View {
        ZStack {
            Color.black.ignoresSafeArea()
            
            ViewThatFits(in: .horizontal) {
                Text("Hello there! How are you today? What are you doing?")
                Text("Hello there! How are you today?")
                Text("Hello there!")
            }
        }
        .foregroundStyle(.white)
        .frame(height: 300)
        .cornerRadius(10)
        .padding(25)
        .font(.headline)
    }
}

#Preview {
    ViewThatFitsSwiftUI()
}

Grid 1

light dark
import SwiftUI

struct GridSwiftUI: View {
    var body: some View {
        Grid {
            GridRow {
                cell(int: 1)
                cell(int: 2)
                cell(int: 3)
                cell(int: 4)
            }
            
            Divider()
                .gridCellUnsizedAxes(.horizontal)
            
            GridRow {
                cell(int: 5)
                cell(int: 6)
                cell(int: 7)
                cell(int: 8)
            }
        }
        .cornerRadius(10)
    }
    
    private func cell(int: Int) -> some View {
        Text("\(int)")
            .font(.system(size: 20, weight: .bold, design: .rounded))
            .padding()
            .background(Color.green.opacity(0.5))
    }
}

#Preview {
    GridSwiftUI()
}

Grid 2

light1 dark1
import SwiftUI

struct GridSwiftUI: View {
    var body: some View {
        
        Grid(alignment: .center, horizontalSpacing: 5, verticalSpacing: 5) {
            ForEach(0..<4) { rowIndex in
                GridRow {
                    ForEach(0..<4) { columnIndex in
                        let cellNumber = (rowIndex * 4) + (columnIndex * 1)
                        cell(int: cellNumber)
                    }
                }
            }
            .cornerRadius(20)
        }
    }
    
    private func cell(int: Int) -> some View {
        Text("\(int)")
            .font(.system(size: 20, weight: .bold, design: .rounded))
            .padding(30)
            .background(Color.gray.gradient)
    }
}

#Preview {
    GridSwiftUI()
}

ControlGroup / Menu

ControlGroup.mov
import SwiftUI

struct ControlGroupSwiftUI: View {
    var body: some View {
        Menu("Open Menu") {
            ControlGroup("Food"){
                Button("Vegies") {
                    
                }
                Button("Sweet") {
                    
                }
                Menu("Fruits") {
                    Button("Apple") {
                        
                    }
                    Button("Banana") {
                        
                    }
                }
            }
            Button("Hey!") {
                
            }
            Menu("Mood") {
                Button("Hey!") {
                    
                }
                Menu("How are you?") {
                    Button("Good") {
                        
                    }
                    Button("Bad") {
                        
                    }
                }
            }
        }
        .buttonStyle(.bordered)
        .font(.system(size: 18, weight: .semibold, design: .rounded))
        .foregroundStyle(Color(.label))
    }
}

#Preview {
    ControlGroupSwiftUI()
}

@Observable Macro

Before

import SwiftUI

class ObservableViewModel: ObservableObject {
    @Published var title: String = "Apple"
}

struct ObservableSwiftUI: View {
    @StateObject private var viewModel = ObservableViewModel()
    
    var body: some View {
        VStack(spacing: 20) {
            Button(viewModel.title) {
                viewModel.title = "Meta"
            }
            
            ChildView(viewModel: viewModel)
            
            ThirdView()
        }
        .environmentObject(viewModel)
    }
}

struct ChildView: View {
    @ObservedObject var viewModel: ObservableViewModel
    
    var body: some View {
        Button(viewModel.title) {
            viewModel.title = "Amazon"
        }
    }
}

struct ThirdView: View {
    @EnvironmentObject var viewModel: ObservableViewModel
    
    var body: some View {
        Button(viewModel.title) {
            viewModel.title = "Armaco"
        }
    }
}

#Preview {
    ObservableSwiftUI()
}

After

import SwiftUI

@Observable class ObservableViewModel {
    var title: String = "Apple"
}

struct ObservableSwiftUI: View {
    @State private var viewModel = ObservableViewModel()
    
    var body: some View {
        VStack(spacing: 20) {
            Button(viewModel.title) {
                viewModel.title = "Meta"
            }
            
            ChildView(viewModel: viewModel)
            
            ThirdView()
        }
        .environment(viewModel)
    }
}

struct ChildView: View {
    @Bindable var viewModel: ObservableViewModel
    
    var body: some View {
        Button(viewModel.title) {
            viewModel.title = "Amazon"
        }
    }
}

struct ThirdView: View {
    @Environment(ObservableViewModel.self) var viewModel
    
    var body: some View {
        Button(viewModel.title) {
            viewModel.title = "Armaco"
        }
    }
}

#Preview {
    ObservableSwiftUI()
}