What is a SceneDelegate in Swift?

In short the SceneDelegate.swift file is there to help with the new multi-window support that was announced with iOS 13.

The UISceneDelegate protocol is used to manage the life cycle for one instance of your app. Apple gave a good example of this when showing multiple instances of their notes app in split screen alongside other apps at the WWDC keynote.

Think of SceneDelegate as a offshoot of the AppDelegate. The AppDelegate will still handle things like configuring the initial scenes and register for services like push notifications but now the AppDelegate will be sharing its responsibility of the apps life cycle with the SceneDelegate.

Things like state transition methods or life cycle methods that use to be handled in the AppDelegate, like “will enter foreground”, “will become active”, and “when it enters the background” are now handled in the SceneDelegate.

For a more indepth look into the SceneDelegate and all the changes to the AppDelegate I recommend reading this great article by Reinder de Vries. Reinder takes a deep dive look into how to get started using the SceneDelegate and what has changed in iOS 13.

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! πŸŒƒ

How to Set an Image as a WatchOS Complication

The reason I’m writing this post is because I had submitted a WatchOS side project I was working on (Status of Github) to the app store. The problem was that I submitted the app with all complications activated but had no image or placeholders for the complications (How embarrassing πŸ€¦πŸ»β€β™‚οΈ). So let’s jump into the project and fix this issue by setting a image to our complications.

Let’s get started by going into the WatchOS project folder at the top of our file navigation.

We need to select the General tab at the top and then scroll down to the Complication Configuration section.

Next we will select which complications we want to support for our project.

Now we will need to add the image we want to use to the Assets folder in the WatchKit Extension part of our WatchOS app.

In the Assets folder you will see another folder named Complication.

In this folder we will add the image that we want to show for the complication types we chose to support in the Complication Configuration.

I would recommend checking out Apple’s Human Interface Guidelines to get the right dimensions for each complication so we have the right size image to display.

Now we will move on to the Complication Controller file where we will set the image from our assets folder to our complications.

    func getCurrentTimelineEntry(for complication: CLKComplication, withHandler handler: @escaping (CLKComplicationTimelineEntry?) -> Void) {
        // Call the handler with the current timeline entry

        if complication.family == .circularSmall {
            let template = CLKComplicationTemplateCircularSmallRingImage()
            guard let image = UIImage(named: "Complication/Circular") else { handler(nil); return}
            template.imageProvider = CLKImageProvider(onePieceImage: image)
            let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
            handler(timelineEntry)
            
        } else if complication.family == .utilitarianSmall {
            let template = CLKComplicationTemplateUtilitarianSmallRingImage()
            guard let image = UIImage(named: "Complication/Utilitarian") else { handler(nil); return}
            template.imageProvider = CLKImageProvider(onePieceImage: image)
            let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
            handler(timelineEntry)
            
        } else if complication.family == .modularSmall {
            let template = CLKComplicationTemplateModularSmallRingImage()
            guard let image = UIImage(named: "Complication/Modular") else { handler(nil); return}
            template.imageProvider = CLKImageProvider(onePieceImage: image)
            let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
            handler(timelineEntry)
            
        } else if complication.family == .graphicCircular {
            let template = CLKComplicationTemplateGraphicCircularImage()
            guard let image = UIImage(named: "Complication/GraphicCircular") else { handler(nil); return}
            template.imageProvider = CLKFullColorImageProvider(fullColorImage: image)
            let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
            handler(timelineEntry)
            
        } else if complication.family == .graphicCorner {
            let template = CLKComplicationTemplateGraphicCornerCircularImage()
            guard let image = UIImage(named: "GraphicCorner") else { handler(nil); return}
            template.imageProvider = CLKFullColorImageProvider(fullColorImage: image)
            let timelineEntry = CLKComplicationTimelineEntry(date: Date(), complicationTemplate: template)
            handler(timelineEntry)

        } else {
            handler(nil)
        }

    }

In the code above we created a image template for each of the complications. Then we set our image to the template. Lastly we set our temple to a complication timeline entry so that it can be displayed to the watch face.

Now let’s run our code in the simulator and go to the watch face home screen.

Here we can press and hold on the screen to customize the watch face and set our new complication.

Now that our complication is on our watch face, we can simply tap on our complication and we will be take directly into our app!

I hope this helps you from making the same mistake I made!

If you want to learn more about complications in WatchOS I highly recommend checking out this WWDC15 video called Creating Complications with ClockKit.

⌚️ Happy Coding! ⌚️

Disclosure Groups in SwiftUI

At WWDC 2020 disclosure groups were announced for SwiftUI. Disclosure groups are very similar to how drop down menus work on the Mac. Apple’s documentation defines it as “A view that shows or hides another content view, based on the state of a disclosure control”.

Before we get started on building a disclosure group you will need to have Xcode 12 installed and be running your project for iOS 14 or newer.

In this post we will be using disclosure groups to help us build parts of a settings menu in a app.

Let’s open a new SwiftUI project in Xcode and get started.

The first thing we will need for our disclosure group is a @State variable so we can keep track of if our disclosure view is expanded or not.

@State private var isSettingsExpanded: Bool = false

Next we need to add our disclosure group to our body view.

@State private var isSettingsExpanded: Bool = false
    
var body: some View {
        DisclosureGroup("Settings", isExpanded: $isSettingsExpanded) {
            Text("Terms of service")
        }
        .padding()
    }

If we go and run this code you should see a disclosure group labeled “Settings” and if we tap on the arrow we should see a drop down that has our “Terms of Service” text view.

What’s really cool is that we can nest Disclosure groups as well.

@State private var isSettingsExpanded: Bool = false
@State private var isTermsOfServiceExpanded: Bool = false

var body: some View {
    DisclosureGroup("Settings", isExpanded: $isSettingsExpanded) {
        DisclosureGroup("Terms of Service", isExpanded: $isTermsOfServiceExpanded) {
            Text("NO ONE READS THESE THINGS!")
        }
    }
    .padding()
}

Above we added another state property and a disclosure group like we did before. Now we have our “Terms of Service” disclosure view nested to our parent “Settings” disclosure view.

We also are not limited to just using text, we can also use any kind of view in our disclosure group. For example maybe we want to turn on and off dark mode in our app. We can simply add a toggle to our disclosure group.

@State private var isDarkModeOn = true
@State private var isSettingsExpanded: Bool = true

var body: some View {
    DisclosureGroup("Settings", isExpanded: $isSettingsExpanded) {
        Toggle("Dark Mode", isOn: $isDarkModeOn)
    }
    .padding()
}

With just a few lines of code we can have all kinds of information being displayed or hidden from the user.

I hope this brief look into disclosure groups helps you to build amazing SwiftUI apps!

Happy Coding!

How to Style an Image in SwiftUI

In this post we are going to take a look at how to customize images in SwiftUI.

First thing we need to do is open a new SwiftUI Xcode project and add an image to our assets folder. I downloaded a random image of a husky as my image asset but feel free to use any image you would like.

Next we will set our image in our ContentView.swift file like the example below.

struct ContentView: View {
    var body: some View {
        Image("husky")
    }
}

Now that we have our image set let us customize it so that it fits our screen better. We can start by resizing our image using the .resizeable() modifier.

struct ContentView: View {
    var body: some View {
        Image("husky")
            .resizable()
    }
}

Now the image fits the screen but we definitely want the image to look a little less crammed on screen. We can fix this by adding the .scaledToFit() modifier. This allows the image to fit the screen without making the image look crammed.

struct ContentView: View {
    var body: some View {
        Image("husky")
            .resizable()
            .scaledToFit()
    }
}

We can also resize the frame of our image by add the .frame() modifier.

struct ContentView: View {
    var body: some View {
        Image("husky")
            .resizable()
            .scaledToFit()
            .frame(width: 300.0, height: 300.0)
    }
}

We can also clip our image into a shape. In this example we are going to clip out image into a circular shape like how many apps show profile pictures. SwiftUI makes this real easy by adding the .clipShape(Circle()) modifier.

struct ContentView: View {
    var body: some View {
        Image("husky")
            .resizable()
            .scaledToFit()
            .clipShape(Circle())
    }
}

These are some of the ways we can manipulate images in SwiftUI.

As a recap we learned how to use .resizeable() modifier which allows us to resize the aspect ratio of the image. We also used .aspectRatio() or the .scaledToFit() modifier to fill the content of our image so it will look proper on screen. Lastly we learned how to resize the frame of an image and saw how we can clip images into shapes like we did with the circle image.

I hope this helps to show how powerful and easy it is to customize images in SwiftUI.

πŸ“·πŸŒ‰ Happy Coding!! πŸŒ‰πŸ“·

How to Customize Text in SwiftUI

In this post we are going to take a quick look at how to style text in SwiftUI.

If we want to change the font of our text we can simply add the .font modifier.

Above you can see Swift has preset options of font types like title, body, large title and many more. We also have the option of using our own custom fonts like the example below.

.font(.custom("Helvetica", size: 15))

Let’s say we want to change the thickness or thinness of our text. We can do this by using the .fontWeight() modifier.

We can also change the color of the font by simply using .foregroundColor() modifier. This allows us to select the color of our text lettering.

You can also change the background color of the text view by using .backgroundColor() modifier.

Text("Warning")
    .background(Color.red)
    .foregroundColor(.white)

Lastly we can also change how far the spacing is between multiple lines by using .lineSpacing and .lineLimit.

The .lineSpacing modifier allows us to make the lines shorter or longer between line breaks and the .lineLimit modifier allows us to limit the lines in a text view.

.lineLimit(3)
.lineSpacing(10)

These are the basics on how to manipulate text so we can customize them to our liking.

I hope this helps you to better understand how to customize text in SwiftUI.

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

What is @escaping and @nonescaping in a Swift closure?

A Closure is a block of code that can pass around data. Closure’s are similar to functions but have special attributes. One feature of what makes closure’s special is that the block of code inside the closure can live passed the function they are called in. It does this by retaining a copy of the closures code in memory until it finishes executing. More about that in a bit, let’s look at an example of a simple closure below.

let greetingClosure = { (name:String) -> String in  
    return "Hello \(name)!"  

}  

let message = greetingClosure("Swift Tom")  

print(message)

// Output: Hello Swift Tom!

In the example above we have a closure variable that takes in a parameter and returns a string. When the example above is called its value is assigned to our closure variable and then printed out.

Now that we have seen a basic closure let’s look at when to use @escaping and @nonescaping in a closure.

A common example of a @escaping closure would be a completion handler. Completion handlers run asynchronous tasks like a network call. Let’s look a example of a network call below.

func performRequest(parameters: [String: String], completionHandler: @escaping (Result<Data, Error>) -> Void) {
   
 var request = URLRequest(url: url)
    request.httpMethod = "GET"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpBody = try! JSONEncoder().encode(parameters)

    let task = URLSession.shared.dataTask(with: request) { data, _, error in
        guard let data = data else {
            completionHandler(.failure(error!))
            return
        }
        completionHandler(.success(data))
    }
    task.resume()
}

The @escaping allows for the closure to be retained in memory until the completion handler either returns success on the network call or a failure. The @escaping outlives the function it was created in to retrive the data we are requesting.

A @nonescaping closure is the opposite of @escaping and doesn’t live past the function it was called in. Below is an example of a @nonescaping closure.

func calculateSumOf(array:[Int],  handler: ((Int)->Void)) {  
        var sum: Int = 0  
        for value in array {  
            sum += value  
        }  
            handler(sum)  
    }  

func getSum() {  
        self.calculateSumOf(array: [22, 18, 9, 50]) { [weak self] sum in  
        
        print(sum)  
        // finishing the execution  
        }  
    } 

getSum()
//Output: 99

In the above example we can see that the function getSum( ) will calculate the sum of the values passed into the array. Once the function finishes running the closure will not be retained memory.

All closures by default are @nonescaping closure’s. The first example I used in this post is also a @nonescaping closure.

The reason for all closures being @nonescaping by default is performance and code optimization for the compiler. If the compiler knows that the closure is @nonescaping it can manage the memory allocation in the closure much faster because it doesn’t have to retain memory until it is returned like in a @escaping closure.

If you want to learn more about closures and how to use them checkout the excellent Swift documentation on closures.

Hope this helps to explain escaping and non-escaping closure.

␛ Happy Coding πŸš«β›