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! 👨🏻‍💻

How to make a Secure TextField in SwiftUI

A secure textfield allows us to display a editable text area that hides the text the user inputs. In this post I will show you how easy it is to implement a secure textfield in a SwiftUI project.

First we will need to open a SwiftUI project. Next we will need to copy the code below into our ContentView.swift file

import SwiftUI

struct ContentView: View {
    
    // 1.
    @State private var password: String = ""
    @State var buttonPass: String = ""
    
    var body: some View {
        VStack(alignment: .leading) {
            Text("Login")
                .font(.headline)
            
            // 2.
            SecureField("Enter Your Password", text: $password)
                .padding(.all)
                .background(Color(red: 239.0/255.0, green: 243.0/255.0, blue: 244.0/255.0, opacity: 1.0))
                .cornerRadius(10)

           // 3.
            HStack {
                Spacer()
                Button(action: {
                    self.buttonPass = self.password
                    
                }) {
                    Text("Login")
                        .foregroundColor(.white)
                }
                .frame(width: 150)
                .padding(.all)
                .background(Color.green)
                .cornerRadius(10)
                Spacer()
            }

            // 4.
            Text("\(buttonPass)")
        }.padding()
        
    }
    
}

So what’s going on in the code above is:

  1. We are creating @State property which will represent the entered text inside the textfield. Our other @State property is for passing our password to a label once the login button is pressed.
  2. Create a SecureField with our placeholder text.
  3. Making a button that when tapped will display our password.
  4. Our Text where we will display the password.

Now if we go to our preview canvas and run our code you will see our login secure textfield and our login button. Type a password in and tap the login button. You should see something like the example below.

In just a few lines of code we now have a secure textfield to handle passwords or any other secure text in SwiftUI.

Hope this quick look at secure textfields helps to secure your project!

👮🏻‍♂️🚨Happy coding! 🚨👮🏻‍♂️

What is a Enum in Swift

What is a Enum? Apple defines and enum as “a common type for a group of related values and enables you to work with those values in a type-safe way within your code”. What the heck does that mean? A enum is shorthand for enumeration and gives us a way to use fixed names for values rather than using strings or integers. Let’s take a look at an example to better explain how to use a enum.

enum Device {
    case phone
    case computer
    case tablet
}

In the above example we created a enum of devices. We can uses this enum to give our code a clean way to assign a value to a object. Let’s look at the example below to see how we can apply this enum to a person struct.

struct Person {
    var name: String
    var device: Device
}

Above you can see we assigned our device variable to our Device enum. Because of this we now can use the Device enum to specify which device we want to assign when creating our Person variable.

let person1 = Person(name: "Tom", device: .phone)
let person2 = Person(name: "Tim", device: .computer)
let person3 = Person(name: "Ted", device: .tablet)

Another scenario for using enum’s that you will see in most app projects is when using custom error messages. Below is an example of how I setup a error messages enum in a project I am working on.

import Foundation

enum TPError : String, Error {
    case invalidUsername = "This username created and invalid request. Please try again"
    case unableToComplete = "Unable to complete your request. Please check your internet connection"
    case invalidResponse = "Invalid response from the server. Please try again"
    case invalidData = "The data received from the sever was invalid. Please try again"
    case unableToFavorite = "There was an error favoriting this user please try again"
    case alreadyInFavorites = "You already favorited this person"
}

Above is my TPError.swift file which stores all my error messages in a enum to display in my app. Next let us look at an example of how I use this emun to handle error messaging in a network call.

    func getFollowers(for username: String, page: Int, completed: @escaping (Result<[Follower], TPError>) -> Void) {
        let endpoint = baseURL + "\(username)/followers?per_page=100&page=\(page)"
        
        guard let url = URL(string: endpoint) else {
            completed(.failure(.invalidUsername))
            return
        } ...

First I set my failure completion to use my TPError. Next in the failure completion handler I assign the .invalidUsername message from the enum that will be displayed on failure. This makes the code much more readable for possible future changes and eliminates a long string from being in my network call.

Using enum’s is a great way to make sure you don’t make silly string or value errors.

Hope this helps to explain enums and how you can use them in your swift programs!

👨🏻‍💻 Happy coding 👨🏻‍💻

How to Implement Sign in with Apple in Swift

At the 2019 WWDC, Apple announced Sign in with Apple which allows users to sign into applications and websites securely. Sign in with Apple ensures privacy by not tracking your sensitive information and also provides a synchronous experience across all your Apple devices. The best part is that it is offered in browsers for platforms like Android and Windows devices through Sign in with Apple JS.

Today we are going to take a look at how we can add Sign in with Apple into our swift app. Let’s start by opening a new Swift project in Xcode.

First thing we have to do is enable Sign in with Apple. We do this by going to our target and going to the Signing & Capabilities. Then in the left corner hit the + button and type in Sign in with Apple.

Now we’re ready to add a Sign in with Apple button in our application. To implement this we need to import AuthenticationServices library and then make a ASAuthorizationAppleIDButton. Let look at the example below.

import UIKit
import AuthenticationServices

class ViewController: UIViewController {

    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureSignInWithAppleButton()
        
    }

    func configureSignInWithAppleButton() {
        
        // Create sign in button
        let signInButton = ASAuthorizationAppleIDButton()
        
        //Add to view
        self.view.addSubview(signInButton)
        
        // Function for the action of our button
        signInButton.addTarget(self, action: #selector(ViewController.signInButtonTapped), for: .touchDown)
        
        // Remove constraints so we can add them programmatically
        signInButton.translatesAutoresizingMaskIntoConstraints = false
        
        // Added button constraints
        NSLayoutConstraint.activate([
            signInButton.centerXAnchor.constraint(equalToSystemSpacingAfter: view.centerXAnchor, multiplier: 1),
            signInButton.centerYAnchor.constraint(equalToSystemSpacingBelow: view.centerYAnchor, multiplier: 1),
            signInButton.heightAnchor.constraint(equalToConstant: 40),
            signInButton.widthAnchor.constraint(equalToConstant: 200)
        ])
    }
}

In the code above we are importing AuthenticationServices and then setting up our Sign in with Apple button programmatically.

First we create our button variable with our signInButton. Next we add our button to the subview. Then we add a target action to our button and remove the auto resizing constraints. Lastly we add the constraints for our sign in button.

Next we need to handle what happens when our sign in button is tapped. Let us take a look at the following code.

    @objc private func signInButtonTapped() {
        let authorizationProvider = ASAuthorizationAppleIDProvider()
        let request = authorizationProvider.createRequest()
        request.requestedScopes = [.email]
        
        let authorizationController = ASAuthorizationController(authorizationRequests: [request])
        authorizationController.delegate = self
        authorizationController.presentationContextProvider = self
        authorizationController.performRequests()
    }


The signInButtonTapped() function will be called on when our button is tapped. What we are doing inside the function is creating our authorizationProvider and then creating a request to get the users information that we want to be able to use in our app. In this case we are only requesting for the users email but we can also ask for the users full name. Next we create a authorizationController to present to the user that will ask for permission to use their email information.

Now we need to handle the ASAuthorizationController delegate. This is where we will handle the users information once we are allowed access to the users email. To implement this we are going to add and extension at bottom of swift file outside of the viewcontroller.

extension ViewController: ASAuthorizationControllerDelegate {
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        guard let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential else {
            return
        }
        
        print("AppleID Credential Authorization: userId: \(appleIDCredential.user), email: \(String(describing: appleIDCredential.email))")
        
    }
    
func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        print("AppleID Credential failed with error: \(error.localizedDescription)")
    }
}

In the above extension we are checking with our guard let statement to see if we have any credentials. Usually we would do something with the users information but in this case we are just going to print our user email to the console. Lastly we create a function to handle the error in case something goes wrong. We will also print out an error to the console for this example but in a real project you would want to handle the error to the user with some kind of alert view.

Lastly we need to present our ASAuthorizationController by adding another extension to ViewController.

extension ViewController: ASAuthorizationControllerPresentationContextProviding {
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
        return self.view.window!
    }
}

This allows us to present the ASAuthorizationController over our app.

Our final code should look like the example below.

import UIKit
import AuthenticationServices

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureSignInWithAppleButton()
        
    }

    func configureSignInWithAppleButton() {
        
        // Create sign in button
        let signInButton = ASAuthorizationAppleIDButton()
        
        //Add to view
        self.view.addSubview(signInButton)
        
        // Function for the action of our button
        signInButton.addTarget(self, action: #selector(ViewController.signInButtonTapped), for: .touchDown)
        
        // Remove constraints so we can add them programmatically
        signInButton.translatesAutoresizingMaskIntoConstraints = false
        
        // Added button constraints
        NSLayoutConstraint.activate([
            signInButton.centerXAnchor.constraint(equalToSystemSpacingAfter: view.centerXAnchor, multiplier: 1),
            signInButton.centerYAnchor.constraint(equalToSystemSpacingBelow: view.centerYAnchor, multiplier: 1),
            signInButton.heightAnchor.constraint(equalToConstant: 40),
            signInButton.widthAnchor.constraint(equalToConstant: 200)
        ])
    }

    @objc private func signInButtonTapped() {
        let authorizationProvider = ASAuthorizationAppleIDProvider()
        let request = authorizationProvider.createRequest()
        request.requestedScopes = [.email]
        
        let authorizationController = ASAuthorizationController(authorizationRequests: [request])
        authorizationController.delegate = self
        authorizationController.presentationContextProvider = self
        authorizationController.performRequests()
    }
    
}

extension ViewController: ASAuthorizationControllerDelegate {
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithAuthorization authorization: ASAuthorization) {
        guard let appleIDCredential = authorization.credential as? ASAuthorizationAppleIDCredential else {
            return
        }
        
        print("AppleID Credential Authorization: userId: \(appleIDCredential.user), email: \(String(describing: appleIDCredential.email))")
        
    }
    
    func authorizationController(controller: ASAuthorizationController, didCompleteWithError error: Error) {
        print("AppleID Credential failed with error: \(error.localizedDescription)")
    }
}

extension ViewController: ASAuthorizationControllerPresentationContextProviding {
    func presentationAnchor(for controller: ASAuthorizationController) -> ASPresentationAnchor {
        return self.view.window!
    }
}

Remember that we can only test for Sign in with Apple on a physical device and not in the Xcode simulator.

That’s all there is to adding Sign in with Apple to your swift project.

I hope this post helps make it easy for your user to login to your app!

📱💻👨🏻‍💻Happy coding! 👨🏻‍💻💻📱

How to Round the Corners of a View in SwiftUI

In this quick post we are going to look at how we can make views in SwiftUI have rounded corners. You can round the corners of any SwiftUI view by using the cornerRadius() modifier. Simply add a value to the cornerRadius to control how rounded you want the view to be. Let us look at a simple example below.

struct ContentView: View {
    
    @State private var hovering = false
    
    var body: some View {
        Button(action: {}) {
            Text("Button")
        }
        .buttonStyle(PlainButtonStyle())
        .padding()
        .background(Color.green)
        .cornerRadius(10)
    }
}

By adding a cornerRadius of 10 to our button we now get nice rounded corners on our button. This can be used on any view that you want to manipulate the corners to have rounded edges.

Hope this helps in styling your views in SwiftUI!

Adding Pointer Hover Effects on iPadOS using SwiftUI

Apple’s latest update now includes support for you to connect a mouse or a trackpad to your iPad in iPadOS 13.4! This is really cool but how can we implement this in our own SwiftUI app for iPad. The good news is Apple makes this simple by giving us two modifiers .hoverEffect and .onHover to add to our SwiftUI views. Let us start by opening up Xcode and in a SwiftUI project add the following code.

struct ContentView: View {
    var body: some View {
        Button(action: {}) {
            Text("Button")
        }
        .hoverEffect()
    }
}

Here we created a button and added the hoverEffect modifier. By adding hoverEffect modifier we get the iPadOS hover effect that clings to the nearest view like buttons or labels. This modifier has three types of effects that we can set to the pointer. By default the hoverEffect modifier uses the first type called automatic. The other two types are highlight and lift.

.hoverEffect(.lift)
.hoverEffect(.highlight)

Lift is a effect that slides the pointer behind the view object and goes aways as the view scales up.

Highlight is a effect that changes the pointer into a platter behind the view and shows a light source showing the cursors position.

Next we are going to look at the onHover modifier. This modifier allows us to make custom effects when the pointer hovers over a view. The onHover modifier uses a closure that is called whenever the cursor of the trackpad or mouse goes over the view. This is where we can set some state to track the cursor and implement our custom animation. Take a look at the example code below.

    @State private var hovering = false
    
    var body: some View {
        Button(action: {}) {
            Text("Button")
        }
        .buttonStyle(PlainButtonStyle())
        .scaleEffect(hovering ? 1.5 : 1.0)
        .animation(.spring())
        .padding()
        .background(Color.green)
        .cornerRadius(10)
        .onHover { isHovered in
            self.hovering = isHovered
            
        }
    }

The above code created a hovering state property to keep track of if the cursor is over our button. If the cursor is hovering over our button we set the state to true in our .onHover closure. This will trigger our scaleEffect of the spring animation. This makes our text animate by enlarging it when our button has the cursor over our it.

Pretty neat!

If you have an iPad app and are using SwiftUI, definitely support the use of the trackpad and mouse in your app!

Hope this was helpful and happy coding!!

👨🏻‍💻🖱👨🏻‍💻🖱👨🏻‍💻🖱

What is a Ternary Operator in Swift

A ternary operator takes a condition and then returns either true or false depending on the value of the condition. The basic syntax can be seen in the example below.

CONDITION ? TRUE VALUE : FALSE VALUE

This can be used as an alternative or a shorthand to If statements.

Let check out an example below.

var ourSpeed = 55

var speedLimit = 50

var currentSpeed = ourSpeed > speedLimit ? "Over Speed Limit" : "Below Speed Limit"

//                |     CONDITION      | ? |      TRUE      | : |      FALSE      |

print(currentSpeed)

// OUTPUT: Over Speed Limit

You can read the ternary example above as “if ourSpeed is greater than the speedLimit set currentSpeed to “Over Speed Limit” otherwise set currentSpeed to “Below Speed Limit”. Because our speedLimit was 50, the currentSpeed variable will be set to the true value of “Over Speed Limit”.

Ternary conditionals can be a little confusing to understand at first but they can be a great way to set variables based on a condition in one line of code. This is great for writing nice clean code.

Hope this helps clear up what is/how to use ternary conditionals.

Happy coding!

👨🏻‍💻💻👨🏻‍💻

Testing with Network Link Conditions in Xcode

Testing how your app works in different networking conditions is really important before you release an app. As of Xcode 11, testing different network conditions built right to make our lives easier.

First thing we need to do is connect our device with Xcode. Then we need to load the app we want to test on to our device. After that we need to go to the top of the screen and click on Window drop down and then go to Devices and Simulator.

Next in Devices and Simulator you should see your connected device. While the app is connected and running you can now scroll down to the bottom and see device conditions.

In device conditions click on the profile drop down. You will see a list of networking conditions that you can use to change the networking speed.

Once you selected your networking condition you then want then press the start button. Your app will now be running at that networking speed that you have selected.

When your done testing remember to stop the device condition or else you will have poor networking on your device.

You can do this same network testing on the device itself. If you go to your iPhone/iPads settings app. Go to Developer > Network Link Conditioner > Enable.

Once enabled, you now can add a profile to test on device just like we did in Xcode.

That’s all there is too it.

Happy Testing 👨🏻‍💻

How to Use Switch Statements in Swift

A switch statement is used to check a variable against a list of possible cases for that variable to then execute. It looks for the first case that matches your variable you want to check and then runs that cases block of code. When that case is finished running its code it will break out from the switch statement.

Let’s look at a example.

let numberToCheck = 20

switch numberToCheck {
case 0:
    print("0 is the number")

case 10:
    print("10 is the number")

case 20:
    print("20 is the number")

case 30:
    print("30 is the number")

default:
    print("Number is not 0, 10, 20, 30")
}
//OUTPUT: 20 is the number

Above is a simple example where we are checking to see the value of a number. If that number is a particular number value that matches our case we want it to print out the number of the case value. If the numberToCheck doesn’t match any of the numbers in our switch case we need a default value for the numberToCheck value.

We can also have switch statements with a range.

let numberToCheck = 40

switch numberToCheck {
case 0...10:
    print("The number is between 0 and 10")

case 10...20:
    print("The number is between 10 and 20")

case 20...30:
    print("The number is between 20 and 30")

case 30...40:
    print("The number is between 30 and 40")

default:
    print("The number is below 0 and above 40")
}

//OUTPUT: The number is between 30 and 40

Above we are using our numberToCheck variable to see what print statement it should make in specific range of numbers. For example if our numberToCheck is 7 the print out would be “The number is between 0 and 10”.

That’s all there is too it.

Switch statements are great for checking a variable against multiple options and then being able to execute a block of code based on your variables value.

I hope this helps clean up your code from having a lot of crazy “if” statements.

👨🏻‍💻 Happy Coding 👨🏻‍💻

Alert Views in SwiftUI

In this post we are going to take a look at how to show an alert in SwiftUI!

Implementing an alert is very simple and all we need is just a few lines of code.

Open up Xcode and create an new SwiftUI project.

In the ContentView.swift file let’s creating a simple @State bool to keep track of when to show and hide our alert.

@State private var showingAlert = false

Next we will make a button and in the action part of the button we will switch the state of our showingAlert variable to true. Then we’ll name the button label “Alert”. Lastly we add the .alert modifier to the end of our button. In the modifier we set the state showing the alert. We also set the title, message, and dismiss button of the alert.

    var body: some View {
        Button(action: {
            self.showingAlert = true
        }) {
            Text("Alert")
        }
        .alert(isPresented: $showingAlert) {
            Alert(title: Text("Alert"), message: Text("Something Went Wrong"), dismissButton: .default(Text("OK")))
        }
    }

Now if we go and run this in our simulator you will see an alert button in the middle of the screen. When tapped our alert will popup with our title, message, and our dismiss button!

With minimal code we made and alert which can be used for all kinds of things in our apps.

How this helps you in learning SwiftUI!

👨🏻‍💻💻👨🏻‍💻💻👨🏻‍💻💻👨🏻‍💻💻👨🏻‍💻💻👨🏻‍💻💻👨🏻‍💻💻👨🏻‍💻💻👨🏻‍💻💻👨🏻‍💻💻👨🏻‍💻💻👨🏻‍💻💻👨🏻‍💻💻