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 πŸš«β›

What are Optionals in Swift

A optional in Swift is the handling of nil in a variable. We check to see if our value is nil by a process we call unwrapping. Similar to a box that came in the mail, we have no idea if the box has anything inside or if it has nil inside. The only way to find out is by unwrapping it. Let’s look at a example to see how we can handle unwrapping optionals.

import UIKit

var studentScores: [Int] = [81, 77, 65, 93, 55]
studentScores.sort()

// if let
if let topScore = studentScores.last {
    // If topScore has a value
    print("The top score in the class is \(topScore)")
} else {
    // If nil
    print("There are no student scores")
}



// guard let
func getTopScore() {
    // If topScore is nil break out of the function
    guard let topScore = studentScores.last else {
        return
    }
    print(topScore)
}



// nil coalescing
    // allows us to set a default value of the same type if nil
let topScore = studentScores.last ?? 100



// force unwrap
let highestScore = studentScores.last!

In the above example we are trying to see what the students top score was in the class. Let’s pretend that we don’t know if the studentScores array is nil. In the example we use the 4 main ways to handle unwrapping optionals in Swift.

The first way we handle an optional value is by using a if let statement. A if let statement allows us to check the variable and then handle the value in a if else statement.

The second way is using a guard let statement. A guard let statement can only be used inside of a function. This way of checking an optional is like a line in the sand because if the guard let statement finds that the variable is nil it will no longer run the code inside of the function.

The third method of unwrapping is called nil coalescing. This allows us to set a default value of the same type if the value is nil.

Our last way of unwrapping an optional is by force unwrapping. This is dangerous to do because if the value turns out to be nil your app will crash. You should only force unwrap if you know the value can never be nil.

Hope this helps you to better understand optionals in Swift.

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

What are Life Cycle Functions in SwiftUI?

If you have done any development with UIKit you have used a life cycle function. These UIKit life cycle functions would be viewDidLoad, viewWillAppear, viewWillDisappear, and viewDidDisappear. In SwiftUI we lose these life cycle functions because there are no more ViewControllers in SwiftUI, only views. SwiftUI replaces these functions with two methods called onAppear( ) and onDisappear( ).

onAppear( ): is a function that runs every time a view appears on screen. The onAppear( ) function is similar to the viewWillAppear function used in UIKit. A good example of how we can use the onAppear( ) function is for any network calls we would need for that view.

onDisappear( ): is a function that runs when a view disappears from our apps screen. This function is similar to the viewWillDisappear function in UIKit. A example for when to use the onDisappear( ) function is for clearing any data before dismissing that view.

By using the onAppear( ) and onDisappear( ) functions in SwiftUI we can achieve similar behavior and functionality to the UIKit lifecycle functions.

Thanks for reading and I hope this helps in your learning of SwiftUI!

πŸ‘¨πŸ»β€πŸ’» Happy Programming πŸ‘¨πŸ»β€πŸ’»

What are Life Cycle Methods in Swift

In Swift our view controllers have life cycle methods. Knowing your apps life cycle is really important for developers to understand how there app works. In this post we are going to run through all the life cycle methods we should know about when developing in iOS.

loadView: This method loads or creates a view and assigns it to the view property. This method is most commonly used if you are creating your view controllers programmatically.

viewDidLoad: This is called one time in a view controllers life cycle when the view controller is initially created. It gets called when the content view is created in memory. Some common use cases for this method would be to make network calls, set up user interface, or anything that needs to be called once when the view has been loaded.

viewWillAppear: This is called before the content view is added to the view hierarchy in your app. This means that this is called just before the view shows up on screen. This method will also be called every time the view is going to appear on screen. This is the main difference between viewDidLoad. You can override viewWillAppear to display custom views and animation like hiding fields or disable actions before the view is visible to the user.

viewDidAppear: This is called right after the view appears on screen. This method is good to use for taking care of things like saving data to core data or starting animations.

viewWillDisappear: This is called right before the view is removed from the screen. Things that are usually handled in this method are saving changes in the app. A example of this is having a form for the user to sign up to your app. Let’s imagine our user was half way done filling out the form and then the user leaves the app. In viewWillDisappear we can save the users inputs before leaving the app so progress isn’t lost.

viewDidDisappear: This is called after all view controllers views have been removed from the view hierarchy. We can use this to stop listening to device sensors or stop listening for any notifications.

viewWillLayoutSubviews: This is called when the content views bounds change but before it lays out its subviews. A example of this is when the bounds change when we rotate the device from portrait to landscape. This always us to layout any customization before the rotation happens.

viewDidLayoutSubviews: Similar to viewWillLayoutSubviews, this method is called when the content views bounds change but after it lays out its subviews.

These are the main life cycle method you should know when programming in swift. Knowing when and how to use these methods can help in solving error for when the app should do a particular task. Below is an image for you to try and visualize the flow of the life cycle methods when being used in an app.

I hope this helps to shed some light on how and when to use a particular life cycle method in swift.

πŸš΄β€β™‚οΈ Happy coding πŸš΄β€β™‚οΈ

Variadic Functions in Swift

What is a variadic function? A Variadic function takes in multiple arguments as a parameter. The swift compiler automatically organizes variadic function objects into an array. The arguments of a variadic function are shown by three periods (…) after the argument’s type. A good everyday example of this would be a print statement where you can print multiple objects.

The “Any…” in the autocomplete of our print statement shows a variadic function allowing us to print multiple objects.

Below is another example on how to use a variadic function inside of a function.

func average(_ numbers: Double...) -> Double {
    var total: Double = 0
    for number in numbers {
        total += number
    }
    return total / Double(numbers.count)
}
average(1, 2, 3, 4, 5)
// Output: 3

Above we have a function that finds the average of our numbers parameter. The numbers parameter is our variadic function, it will take in as many numbers as we want and then use them in an array to calculate the average.

I hope this clears up how a variadic function work!

Happy coding!

πŸ‘¨πŸ»β€πŸ’»πŸ’»πŸ“±πŸ‘¨πŸ»β€πŸ’»πŸ’»πŸ“±

What is ARC memory management in Swift

What is ARC? ARC stands for Automatic Reference Counting. Reference counting is a way of storing number references or pointer to a object. In short ARC helps to store references into memory and helps clean up memory when it is not being used.

Apples documentation says β€œMemory management β€œjust works” in Swift, and you do not need to think about memory management yourself. ARC automatically frees up the memory used by class instances when those instances are no longer needed.”

ARC uses references like strong, weak, or unowned as a way of knowing when to free memory for a given object. By default when we declare a class property its a strong reference type. In this post we will take a look at how to use strong and weak references in ARC.

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

class Person {
     var name: String
     var device: Device?
     init(name: String, device: Device?) {
        self.name = name
        self.device = device
     }
}

class Device {
     var owner: Person?
     var device: String
     init(owner: Person, device: String) {
        self.owner = owner
        self.device = device
     }
}

In the above example we created two classes, a Person class and a Device class. We created these classes to show an example of a strong reference cycle.

The Person class has a strong reference to the Device class through it’s device property, and device has a strong reference to Person through its owner property. The problem with this is that these objects hold strong references to one another. This means that ARC is unable to deallocate memory when one of the objects are removed because they reference one another. This creates a memory leak in our code.

To fix our strong reference cycle problem we will have to set our device variable to a weak variable type in our Person class. This allows the variable to be deallocated from memory when its not need.

class Person {
     var name: String
     weak var device: Device?
     init(name: String, device: Device?) {
        self.name = name
        self.device = device
     }
}

class Device {
     var owner: Person?
     var device: String
     init(owner: Person, device: String) {
        self.owner = owner
        self.device = device
     }
}

Above we now have the Device class with a strong reference to the Person class, but the Person class has a weak reference to the Device class.

When we use a weak reference type on a object it needs to be a optional because it has to have the ability to become nil. If the Device class variable becomes nil our Person class will deallocate or release the memory stored. This corrects our strong reference cycle and stops our memory leak.

A good rule of thumb:

A Strong references should be used when a parent object is referencing a child object.

A Weak references should be used to avoid retain cycles.

This is a brief look at how ARC memory management works. For a deeper dive into ARC I recommending checking out the Swift documentation on Automatic Reference Counting.

I hope this opened the curtain to what goes on behind the scenes of Swift memory management and helps to shed some light on how ARC works in Swift.

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