How to Make a Expandable Button in SwiftUI

In this post we are going to learn how to make a SwiftUI button that expands out to show more button options. Below is an example of what our button will look like when we are finished.

Let’s get started by creating a new SwiftUI project.

In our project let’s add a new SwiftUI file and name it ExpandableButton. Inside of our ExpandableButton.swift file we will add the following code.

import SwiftUI

struct ExpandableButton: View {
    var body: some View {
        Button(action: {
                    print("Expandable button tapped!!!")
        }) {
            Image(systemName: "plus.circle.fill")
                .resizable()
                .frame(width: 75, height: 75)
                .foregroundColor(.green)

        }
        
    }
}

In the code above all we did was create a button and stylize it. Next we will need to wrap our button in a VStack so that when we add our menu buttons they will appear above our expandable button.

import SwiftUI

struct ExpandableButton: View {
    var body: some View {
        VStack {
            Button(action: {
                        print("Expandable button tapped!!!")
            }) {
                Image(systemName: "plus.circle.fill")
                    .resizable()
                    .frame(width: 75, height: 75)
                    .foregroundColor(.green)

            }
        }
        
    }
}

Now let’s create our menu buttons in a new SwiftUI file. We will name this file MenuButtons and we will add the following code to it.

import SwiftUI

struct MenuButtons: View {
    var buttonImage: String
    
    var body: some View {
        Button(action: {
            print("Menu Button tapped")
            
        }) {
            ZStack {
                Circle()
                    .foregroundColor(.green)
                    .frame(width: 50, height: 50)
                
                Image(systemName: buttonImage)
                    .imageScale(.large)
                    .foregroundColor(.white)
                
            }
        }
    }
}

In the code above we made our menu buttons similar to how we created our expandable button. The only difference is that our menu buttons are slightly smaller and have a green circular background. We also added a buttonImage variable so that we can change the image that appears on our menu button.

Now that we have our menu button created let’s go back and add it to our ExpandableButton.swift file. First we will need to create a @State variable so that we can control when we show our menu buttons. In this example we will name are state property isExpanded and set it to false.

@State var isExpanded = false

Next we will add a conditional statement above our expandable button that will check if our button is expanded. If isExpanded returns true we will show our the menu buttons.

            if isExpanded {
                MenuButtons(buttonImage: "camera.fill")
                MenuButtons(buttonImage: "record.circle.fill")
                MenuButtons(buttonImage: "photo")
            }

In the action of our expandable button we will toggle our isExpanded property so that we can control when to show and hide our menu buttons. We’ll also add an animation so that when the expandable button is pressed our button will have a smooth transition. Our code should now look like the example below.

import SwiftUI

struct ExpandableButton: View {
    
    @State var isExpanded = false
    
    var body: some View {
        VStack {
            if isExpanded {
                MenuButtons(buttonImage: "camera.fill")
                MenuButtons(buttonImage: "record.circle.fill")
                MenuButtons(buttonImage: "photo")
            }
            
            Button(action: {
                print("Expandable button tapped!!!")
                isExpanded.toggle()
                
            }) {
                Image(systemName: "plus.circle.fill")
                    .resizable()
                    .frame(width: 75, height: 75)
                    .foregroundColor(.green)
            }
            
            
        }
        .animation(.spring())
    }
}

Now if we go and run our preview canvas we should see our button. If we go and tap our button then we should see our menu buttons pop up with an animation.

Thanks for reading! I hope this helps you in your next SwiftUI project.

All the code from this post can be found on my Github.

πŸ“± Happy Coding! πŸ’»

How to Add Custom Modifiers and Views to Xcode’s Library

SwiftUI allows us to add our own custom views and modifiers to Xcode’s library. By doing this we are able to easily access our custom views and add them into our code in just a click. Let’s see how we can take advantage of this in our own SwiftUI project.

First thing we will need is to add a new SwiftUI file to our project to store our custom views and modifiers. We’ll name our file LibraryContent and replace the boilerplate code with the code in the example below.

import SwiftUI

struct LibraryContent: LibraryContentProvider {
    @LibraryContentBuilder
    var views: [LibraryItem] {
        LibraryItem(CloseButton(), category: .control)
    }
}

In the example code we are creating a LibraryItem so we can add our custom view to the Xcode library. We chose to add our custom close button because we will most likely use this view throughout the app and we will want to have quick access to it from our Xcode library.

If we dive into the Documentation for LibraryItem we can see that we can add things like a title and category to our LibraryItem. This is to help us better organization our views and modifiers in our Xcode Library. In our example we are adding the close button to the .control category. Also you will notice we didn’t add a title to our LibraryItem but Xcode is smart enough to use the filename “CloseButton” as the title.

Now Xcode probably is showing some errors because it can’t find our CloseButton view. Let’s go ahead and create a new SwiftUI file and name it CloseButton.

In our CloseButton.swift file add the following code.

import SwiftUI

struct CloseButton: View {
    var body: some View {
        Image(systemName: "xmark")
                    .font(.system(size: 17, weight: .bold))
                    .foregroundColor(.white)
                    .padding(.all, 10)
                    .background(Color.black.opacity(0.6))
                    .clipShape(Circle())
    }
}

struct CloseButton_Previews: PreviewProvider {
    static var previews: some View {
        CloseButton()
    }
}

If we go and run the preview canvas in CloseButton.swift we should see a circular button with an X in the center.

Now if we go to our Xcode library we can see that our close button has been added. We can open up our Xcode library by going to the + button in the top right of Xcode or by using the keyboard shortcut Command + Shift + L.

Now that the Xcode library is open we can use its search bar at the top to search for our custom “Close button”. Like in the image below we should see our new custom view show up and allow us to drag and drop it or double click on it to add it to our current SwiftUI file.

We can also add custom modifiers to our library like we did our custom view.

To add a reusable modifier we will need to add a View extension to our LibraryContent.swift file. Inside of the extension we will need to create a function that returns a view with the modifiers we want added.

Let’s take a look at the example code below.

extension View {
    func customViewStyle() -> some View {
        return self
            .background(Color.red)
            .cornerRadius(22)
            .shadow(color: Color.red.opacity(0.3), radius: 20, x: 0, y: 10)

    }
}

Above we created our customViewStyle() function which is returning a view with 3 custom modifiers.

With just this code we can now go to any file in our project and apply our new custom modifier. Let’s see this in action by going to our ContentView.swift file. At the end of the Hello World text view we can add our new modifier.

import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .padding()
            .customViewStyle()
    }
}

This is great but the only problem is that our new modifier for our view doesn’t show up in our Xcode library.

Let’s go back to the LibraryContent.swift file and under our CloseButton() let’s add another @LibraryContentBuilder with the following code.

    @LibraryContentBuilder
    func modifiers(base: Image) -> [LibraryItem] {
        LibraryItem(
            base.customViewStyle(),
            title: "Custom View Style 1",
            category: .effect
        )
    }

As you can see in the example above this code is very similar to how we added our custom close button to our library. Now if we go to our library with the second tab selected and search for our modifier we will see our “Custom View Style 1” modifier has been added.

Lastly let’s make our custom modifier customizable. We are going to change the hard coded values into variables so that anyone that is using our modifier can style it to their liking. Let’s go back to our LibraryContent.swift file and add the following changes to our code.

    @LibraryContentBuilder
    func modifiers(base: Image) -> [LibraryItem] {
        LibraryItem(
            // Added default values for our customViewStyle function
            
            base.customViewStyle(color: Color.red, cornerRadius: 22),
            title: "Custom View Style 1",
            category: .effect
        )
    }
}

extension View {
    // Add variables to our function so we can customize it to our like for the specific view we are working on
    
    func customViewStyle(color: Color, cornerRadius: CGFloat) -> some View {
        return self
            .background(color)
            .cornerRadius(cornerRadius)
            .shadow(color: color.opacity(0.3), radius: 20, x: 0, y: 10)

    }
}

As you can see in the code above we added variables to our customViewStyle() function so we can change the color and the corner radius to whatever value we want. We also added our previously hard coded values as the default values for our modifier. Let’s go back to our ContentView.swift file and apply our updated modifier to the Hello World text view.

import SwiftUI

struct ContentView: View {
    var body: some View {
        Text("Hello, world!")
            .padding()
            .customViewStyle(color: .green, cornerRadius: 10)
    }
}

Hope this helps you on your next SwiftUI project!

Thanks for reading!

All the code in this post can be found on my Github.

πŸ‘¨πŸ»β€πŸ’» Happy coding! πŸ‘¨πŸ»β€πŸ’»

How to Make a Placeholder View in SwiftUI using the Redacted Modifier

As of iOS 14 we can now use the new .redacted(reason:) modifier in SwiftUI to make placeholders for our views. Let’s take a look at the example below to get a better understanding of how we can add placeholders to our SwiftUI project.

        Text("Hello world!")
            .padding()
            .redacted(reason: .placeholder)

By adding the redacted modifier our users will get a outline preview of our content. This is great to use when content is being loaded to our views.

We can also redact groups of SwiftUI views. Let’s write some code to see how we can implement this in a example. First let’s create a new SwiftUI file and name it ComplexView. Next let’s add the following code below.

import SwiftUI

struct ComplexView: View {
    var body: some View {
        VStack(alignment: .leading) {
            Spacer()
            Image("husky")
                .resizable()
                .frame(width: 200, height: 200)
                .clipShape(Circle())
            Text("Husky World!")
                .font(.title)
            .fontWeight(.bold)
                Spacer()
            Text("A husky is a sled dog used in the polar regions. One can differentiate huskies from other dog types by their fast pulling-style. They represent an ever-changing crossbreed of the fastest dogs (the Alaskan Malamute, by contrast, pulled heavier loads at a slower speed). Humans use huskies in sled-dog racing. Various companies have marketed tourist treks with dog sledges for adventure travelers in snow regions. Huskies are also kept as pets, and groups work to find new pet homes for retired racing and adventure-trekking dogs.")
            HStack() {
                Spacer()
                Button("More Huskies!") {
                    print("Huskies!!!!")
                }
                .padding()
                .font(.system(size: 32))
                Spacer()
            }
            Spacer()
        }
        .padding()
    }
}

We should now see a view about huskies in our preview canvas!

Now if we go to our ContentView.Swift file we can add our ComplexView() to our body. Here we will add the redacted modifier to the ComplexView to redact all of the views inside of the container.

import SwiftUI

struct ContentView: View {
    var body: some View {
        ComplexView()
            .redacted(reason: .placeholder)
    }
}

We can also redact specific views in our ComplexView.swift file. Let’s say we wanted to show a placeholder for everything in our complex view except for our “Husky World!” text. We can simply go back to our ComplexView.swift file and add the .unredacted() modifier to our “Husky World!” text view.

struct ComplexView: View {
    var body: some View {
        VStack(alignment: .leading) {
            Spacer()
            Image("husky")
                .resizable()
                .frame(width: 200, height: 200)
                .clipShape(Circle())
            Text("Husky World!")
                .font(.title)
                .fontWeight(.bold)
                // Added Unredacted
                .unredacted()
            Spacer()
            Text("A husky is a sled dog used in the polar regions. One can differentiate huskies from other dog types by their fast pulling-style. They represent an ever-changing crossbreed of the fastest dogs (the Alaskan Malamute, by contrast, pulled heavier loads at a slower speed). Humans use huskies in sled-dog racing. Various companies have marketed tourist treks with dog sledges for adventure travelers in snow regions. Huskies are also kept as pets, and groups work to find new pet homes for retired racing and adventure-trekking dogs.")
            HStack() {
                Spacer()
                Button("More Huskies!") {
                    print("Huskies!!!!")
                }
                .padding()
                .font(.system(size: 32))
                Spacer()
            }
            Spacer()
        }
        .padding()
    }
}

Now when we look at our preview for our Complex view we should see everything redacted except “Husky World!”.

It is good to note that buttons are not disabled when using the redacted modifier. This means users can still tap on buttons while the placeholder for the button is being shown. You will need to use a @State or @Enviorment variable to handle disabling any buttons in your view so that button actions won’t get triggered as your redacted view is being shown.

The example code for this post can be found on my GitHub.

Thanks for reading my post and I hope this helps in your next SwiftUI project.

Happy Coding!

Redact GIFs - Get the best GIF on GIPHY

How to Add Sign In with Apple to a SwiftUI Project

Sign in with Apple makes it safe and secure for users to login to websites and apps. We can implement Sign in with Apple easily with SwiftUI 2. For us to use Sign in with Apple in our app we are required to use iOS 14 or later and Xcode 12 or later.

The first thing we need to do is go to our project file which is located at the top of our navigator on the left side of Xcode. Then we need to go to the Signing & Capabilities tab. In the left corner of this tab we need to click on the + Capability button and type in Sign in with Apple. Then press enter to add it to our project.

Now let’s navigate to our ContentView.swift file to get started.

We need to open our library to get a Sign in with Apple Button for our project. We can use the keyboard shortcut Command + Shift + L to bring up our library. In the search bar we can type in Sign in with Apple and drag and drop our Sign in with Apple button into either our code or onto our canvas.

Now you might have a error pop up that says Xcode can not find Sign in with Apple in our scope. All you have to do to get rid of this error is import AuthenticationServices at the top of our ContentView.swift file. Now let’s add the code in the example below to our project and we will walk through what we are implementing in our app.

import SwiftUI
import AuthenticationServices

struct ContentView: View {
    var body: some View {
        SignInWithAppleButton(
            // 1.
            onRequest: { request in
                request.requestedScopes = [.fullName, .email]
            },
            onCompletion: { result in
                switch result {
                // 2.
                case .success (let authenticationResults):
                print("Authorization successful! :\(authenticationResults)")

                // 3.
                case .failure(let error):
                    print("Authorization failed: " + error.localizedDescription)
                }
            }
            // 4.
        ).frame(width: 200, height: 50, alignment: .center)
    }
}

  1. Here we are specify what kind of information we would like to get from our user. In this example we are requesting the users full name and email address to be used in our app.
  2. If the request goes through successfully we can then gain access to the users information we requested. This would be the users full name and email address.
  3. If something goes wrong this is where we will be able to show a error message to our user and notify them that something has gone wrong with using Sign in with Apple.
  4. Lastly we are setting the frame of our button so our button won’t take up the whole screen.

Now when we run our app we should see a Sign in with Apple button.

When we tap on our button we should be prompted to authenticate using our full name and email.

We can switch the Sign in button to be a Continue with Apple button or a SignUp with Apple button by simply adding the following code at the top of our existing code.

import SwiftUI
import AuthenticationServices

struct ContentView: View {
    var body: some View {
        SignInWithAppleButton(
            // Add this below for Sign up with Apple button
            .signUp,
            
            onRequest: { request in
                request.requestedScopes = [.fullName, .email]
            },
            onCompletion: { result in
                switch result {
                case .success (let authenticationResults):
                print("Authorization successful! :\(authenticationResults)")
                case .failure(let error):
                    print("Authorization failed: " + error.localizedDescription)
                }
            }
        ).frame(width: 200, height: 50, alignment: .center)
    }
}
struct ContentView: View {
    var body: some View {
        SignInWithAppleButton(
            // Add this below for Continue with Apple button
            .continue,
            
            onRequest: { request in
                request.requestedScopes = [.fullName, .email]
            },
            onCompletion: { result in
                switch result {
                case .success (let authenticationResults):
                print("Authorization successful! :\(authenticationResults)")
                case .failure(let error):
                    print("Authorization failed: " + error.localizedDescription)
                }
            }
        ).frame(width: 200, height: 50, alignment: .center)
    }
}

That’s all there is to adding Sign in with Apple to our SwiftUI project. This blogs code can be found on my Github. If you want to see how we can implement Sign in with Apple in UIKit please check out my other blog post.

Thanks for reading and I hope this helps you on your next SwiftUI project!

κ©œπŸ’»πŸ‘¨πŸ»β€πŸ’» Happy Coding! πŸ‘¨πŸ»β€πŸ’»πŸ’»κ©œ

How to Make a Sidebar Menu in SwiftUI

Sidebars are really useful for navigating on bigger screen such as iPad’s and the Mac’s. We are going to take a look at how we can implement sidebars into a multiplatform SwiftUI app.

The first thing we need to do is open a new Xcode project and create a new SwiftUI file. In this example we are going to name our file SideBar. Inside the Sidebar file we are going to replace the boilerplate code with the code below.

struct Sidebar: View {
    var body: some View {
        NavigationView {
            List {
                Label("Books", systemImage: "book.closed")
                Label("Tutorials", systemImage: "list.bullet.rectangle")
                Label("Video Tutorials", systemImage: "tv")
                Label("Contacts", systemImage: "mail.stack")
                Label("Search", systemImage: "magnifyingglass")
            }
            .listStyle(SidebarListStyle())
            .navigationTitle("Code")
        }

    }
}

In the above example we have created a simple list view with a few labels for our sidebar. Then we set our list with the sidebar style by simply adding the .listStyle(SidebarListStyle()) modifier. We also added a navigation view so we can have a nice title label and add navigation to our sidebar labels in the future.

Now we are going to run this code on our iPad simulator and rotate our simulator 90Β°. We can now see how our sidebar looks on a bigger iPad screen.

Let’s fill in the blank space of our example to see how this would look in a real app. First we will remove the NavigationView from our Sidebar.swift file. Then we will go into our ContentView file and add the following code below.

struct ContentView: View {
    var body: some View {
        NavigationView {
            Sidebar()
            List(0 ..< 20) {_ in
                Text("Book")
            }
            .navigationTitle("Book List")
        }
        
        
    }
}

Now when we run our application we get a mock book list next to our sidebar.

If we wanted to make this sidebar available on a Mac version of our app all we would need to do is add a few lines of code to our project.

The first thing we will need to do is extract out the code in between the NavigationView curly braces. We can do this by holding down the command button and clicking on List. Next scroll down and select Extract subview. We will rename our subview SideBarContent. Now we need to add #if, #else, and #endif under our NavigationView. This will allow us to specify how we want our sidebar layout to look for the different operating systems.

struct Sidebar: View {
    var body: some View {
        NavigationView {
            #if os(iOS)
            SideBarContent()
                .navigationTitle("Code")
            #else
            SideBarContent()
                .frame(minWidth: 200, idealWidth: 250,maxWidth: 300)
            #endif
        }

    }
}

The code above is allowing us to adapt our sidebar code to the different OS‘s (Operating Systems) our app is going to run on. We need to separate our code because there are different requirements for running our code on the different operating systems. In the first part of our #if statement we are checking to see if our OS is iOS and if it is we are then setting our sidebar with a navigation title. We need to add our .navigationTitle() modifier here because it is not supported in MacOS. In the #else statement all we need to do is set the minimum frame of our Mac app’s window. Lastly we end our if statement with the #endif.

Now we can run our sidebar code on both the iOS and MacOS (We need to have MacOS Big Sur installed on your Mac to run this on the Mac simulator).

That’s all there is too adding a native sidebar to a multiplatform SwiftUI app. Feel free to check out the example code here on my Github.

πŸ’»πŸ‘¨πŸ»β€πŸ’» Happy Coding! πŸ’»πŸ‘¨πŸ»β€πŸ’»

How to Show a ProgressView in SwiftUI

At WWDC 2020 Apple introduced ProgressView‘s to SwiftUI. A ProgressView allows us to show either a circular progress view or a linear progress view for when tasks are loading in our app.

The first type of progress view we will look at is the Indeterminate Progress view. The indeterminate progress view creates a spinning loading view. The example below shows how we can easily add this into our code.

ProgressView()

We can also add text to the progress view by adding a string inside the parentheses.

ProgressView("Loading...")

The second type of progress view we will look at is the Linear Progress view. Linear progress views are great for when we have something loading and we want to show the progress to our user.

To make a linear progress view we need to specify two parameters, the current value and the total value of our progress view.

ProgressView("Downloading…", value: 25, total: 100)  
    .padding()

As you can see in the above example all we did was add a current value of 25 and a total value of 100. This shows our current progress as the blue line at 25% of our total value which is 100%.

We can see how a linear progress view works by adding a simple timer that changes the current value over time until it reaches our total value.

struct LinearProgressView: View {
    @State private var currentValue = 0.0
    let timer = Timer.publish(every: 0.09, on: .main, in: .common).autoconnect()
    
    var body: some View {
        ProgressView("Downloading…", value: currentValue, total: 100)
            .padding()
            .onReceive(timer) { _ in
                if currentValue < 100 {
                    currentValue += 1
                }
            }
    }
}

In the example above we added a @State property called currentValue. This will update the current progress of our linear progress view. Then we created and added our timer to the .onReceive modifier. This will update our currentValue variable every time our timer hits 0.09 seconds. We also check to make sure that the currentValue never exceeds the total value of the progress view because this can cause problems in your code and Xcode will yell at us.

Lastly we can customize your linear progress view by changing the accent color of the progress bar with the .accentColor modifier and by changing the text color by using the .foregroundColor modifier.

struct LinearProgressView: View {
    @State private var currentValue = 0.0
    let timer = Timer.publish(every: 0.09, on: .main, in: .common).autoconnect()
    
    var body: some View {
        ProgressView("Downloading…", value: currentValue, total: 100)
            .padding()
            .onReceive(timer) { _ in
                if currentValue < 100 {
                    currentValue += 1
                }
            }
            .accentColor(.purple)
            .foregroundColor(.red)
    }
}

If you would like to play around with these progress view examples please check out the code for this blog on my Github.

Hope this helps shed some light on how to use progress views in SwiftUI!

πŸ’» ꩜ Happy Programming! κ©œπŸ’»

How to Show a Menu When a Button is Pressed in SwiftUI

As of iOS 14 and SwiftUI 2 we can now add a pop out menu to any button in our app. We can implement this by using the new Menu keyword. Menus in some way are going to replace the current action sheets used in iOS apps. The problem with action sheets is they only show up at the bottom of our screen. This doesn’t look great on larger screens like the iPad and Mac. Menus allow the flexibility in where we would want to show pop out menus in our app instead of only showing them at the bottom of our screens.

Let’s take a look at the example below of how we can implement this in our application.

struct ContentView: View {
    var body: some View {
        
        Menu("Create") {
            Button("Cancel", action: {})
            Button("Search", action: {})
            Button("Add", action: {})
        }
    }
}

As you can see in the example above we use the Menu keyword and name our menu “Create“. Next inside the menu curly braces we can add as many buttons as we want. The order of how we place the buttons in the menu does matter. The first button we create will always be at the bottom and whatever button we create next will be on top of the pervious the button. Take a look at the example below.

As you can see in the above example once our create button is tapped we can see our menu of buttons appear in the specific order we placed them in our code.

We can also have menus inside of menus.

struct ContentView: View {
    var body: some View {
        
        Menu("Create") {
            Button("Cancel", action: {})
            Menu("More") {
                    Button("Rename", action: {})
                    Button("Developer Mode", action: {})
                }
            Button("Search", action: {})
            Button("Add", action: {})
        }
    }
}

Now if we tap on the Create button and then tap our More button we now get presented with our new menu inside of our main menu.

Lastly we can have customized text and icons in our menu by adding a label to our menu.

struct ContentView: View {
    var body: some View {
        
        Menu {
            Button("Cancel", action: {})
            Button("Search", action: {})
            Button("Add", action: {})
        } label: {
            Label("Create", systemImage: "plus.circle")
        }
    }
}

As you can see in the above example now we can add a custom title and icon to our menu button.

There is a great WWDC video that can help explain menus if you are still confused.

I hope this helps you better understand how to use the menus in iOS 14 and SwiftUI 2.

πŸ’»πŸ‘¨πŸ»β€πŸ’» Happy coding! πŸ’»πŸ‘¨πŸ»β€πŸ’»

How to Make Keyboard Shortcuts in SwiftUI

As of WWDC 2020, SwiftUI has made it insanely easy to add keyboard shortcuts to any SwiftUI app. Let’s look at how we can add keyboard shortcuts to our project by looking at the code example below.

struct ContentView: View {
    var body: some View {
        
        Button(action: {
            print("Button Tapped!!")
        }) {
            Text("Button")
        }.keyboardShortcut("T")
        
    }
}

As you can see in the example above all we needed to do was add the .keyboardShortcut() modifier to our button and assign it a key. Now by holding the command button on our external keyboard and pressing “T”, our action for our button will be triggered.

We can customize our shortcut by modifying which buttons need to be pressed.

.keyboardShortcut("T", modifiers: .control)

In the example above if we want to trigger our new modified shortcut we need to press the control button and the “T” button.

We can also use different combinations of modifier keys in an array.

.keyboardShortcut("T", modifiers: [.command, .control])

Like in the example before we need to hold the control and “T” key but now we also need to hold the command key to get our shortcut to work.

We can also use other keyboard keys like directional keys, spacebar, and many more.

.keyboardShortcut("T", modifiers: [.command, .shift, .space])

Also be mindful that system keyboard shortcuts like cut, copy, and paste take priority over app shortcuts. Keep this in mind when assigning your keyboard shortcuts.

I hope this helps you to expand keyboard shortcuts to your SwiftUI app!

⌨️ 🩳 πŸ’‡β€β™‚οΈ Happy Coding ⌨️ 🩳 πŸ’‡β€β™‚οΈ

How to use LazyVGrid and LazyHGrid in SwiftUI

As of iOS 14, SwiftUI now gives developers two new UI components called LazyVGrid and LazyHGrid. LazyVGrid is used for creating vertical grids and LazyHGrid is used for horizontal grids. The keyword Lazy means that the grids view does not create items for the grid until they are needed to appear on screen. This allows our app to have much faster loading times when using grids!

In this post we are going to look at how to make a LazyVGrid. All the examples in this post can be applied to LazyHGrid.

There are three things we need to make a LazyVGrid.

  1. We need a list of data to display
  2. We need a GridItem. This defines how we want the layout to look
  3. We need to choose if we want our grid to be vertical or horizontal
    private var gridLayout = [
        GridItem(.flexible()),
        GridItem(.flexible())
    ]

Above we are creating the gridLayout variable which is an array of GridItem‘s. We will use this variable to set the layout we want for our grid. Later we will talk about the .flexible() but for now don’t worry.

In this example we want two columns in our grid. The more GridItem‘s we add to the array will mean more columns of our data to be displayed on the screen. We can add as many columns as our display can handle but for this example we are going to use two columns.

Next we need to add a ScrollView and our LazyVGrid.

    private var gridLayout = [
        GridItem(.flexible()),
        GridItem(.flexible())
    ]
    
    var body: some View {
        
        ScrollView {
            LazyVGrid(columns: gridLayout, spacing: 20) {
                ForEach((1...100), id: \.self) {
                    Text("\($0)")
                        .font(.title)
                        .foregroundColor(Color.white)
                        .frame(minWidth: 0, maxWidth: .infinity, minHeight: 50)
                        .background(Color.red)
                }
            }
            .padding(.all, 10)
        }
    }

In the above code we are applying our gridLayout variable to our LazyVGrid with a spacing of 20. Then we are adding a ForEach statement that will display numbers in a text view from 1 to 100 and we added a little styling to the text view.

Now if we run the code above we should get two columns of numbers in a vertical grid like in the image below.

In the above example we used the flexible lazy grid style. This flexible style allows us to specify how big we want each item to be and also lets us control of how many columns we want to display. There are two other types of grid styles called fixed and adaptive.

The fixed grid type will make any of our column’s fixed to a particular width size. To show this in an example we are going to run the same code as above but switch our first GridItem style.

    private var gridLayout = [
        GridItem(.fixed(100)),
        GridItem(.flexible())
    ]

You can now see that our first GridItem in our grid will always have a fixed width of 100, while the flexible style on the second GridItem will take up the rest of the row space.

Next we have the adaptive grid layout which will take a minimum width and display as many rows as it can on the screens layout.

    private var gridLayout = [
        GridItem(.adaptive(minimum: 100)),
    ]

All of these same methods for customizing LazyVGrid can be used when creating LazyHGrid. A reminder you can only use this style of lazy grids in apps supporting iOS 14 and above.

Hope this helps you to be more lazy with your grids!

πŸ˜΄πŸ›Œ Happy Coding πŸ˜΄πŸ›Œ

How to Detect Dark Mode in SwiftUI

SwiftUI makes it really simply to detect when dark mode is enabled. We simply have to add a @Enviroment variable and use .colorScheme property to scan the settings on our device and see if dark mode is enabled.

Let’s take a look at the example below.

struct ContentView: View {
    @Environment(\.colorScheme) var colorScheme

    var body: some View {
        ZStack {
            Color(colorScheme == .light ? .blue : .red)
            Text("Hello, World!")
        }
    }
}

In the code above we are creating the @Environment variable to see if our device is in dark mode. Then inside of our body view we are setting the background color to red if its in dark mode or blue if its not in dark mode by using our colorScheme variable inside of a ternary operator.

A great use case for this is if you want to support different custom UI’s for when the users device is in dark mode.

πŸŒƒ Happy Coding! πŸŒƒ