iOS – Are 20 Quick Valuable Concepts Best way to Learn Swift?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (Are 20 Quick Valuable Concepts Best way to Learn Swift? ).

In this article, We will discuss 20 quick valuable concepts which is the best way to learn swift and helps to build iOS applications. We’ll need Swift Foundation Concepts as we start building apps. It means that we introduce each topic in a way. This provides enough background to understand the foundation concepts.

A famous quote about learning is :

The beautiful thing about learning is that nobody can take it away from you.

So Let’s begin.


1. Hello World

It is common to start any tutorial for a new language with the Hello World example so we’ll start out by showing how easy this is to do in Swift:

print("Hello World!")      // Prints "Hello World!" to the output window in Xcode

To make this a little more personal, let’s look at one of the handy features of Swift (called string interpolation) where we can insert values into strings using the \(...) syntax. Below, we’ve inserted name into the middle of our string:

let name: String = "World"
print("Hello \(name)!")     // Prints "Hello World!"


2. When to use let vs var

We’ll notice in the example above we’ve used let to create the new variable for the name “Bob”. In Swift, we’ll choose from the following 2 options when creating a new variable:

  • let => Use let when we are defining a constant (a value that will not change)
let numberOfContinents: Int = 7   // Seven continents will not change so we've used "let"
  • var => Use var when we are defining a variable (a value that might change)
var continentsVisited: Int = 2   // Continents visited increases over time so we've used "var"

In general, it is considered a best practice to use constants (let) whenever possible.


3. Numbers

The two most common types of numbers we’ll use in Swift are integers (Int) and doubles (Double):

Integers are whole numbers with no fractional component:

let minValue: Int = -42
let maxValue: Int = 55 

Doubles can have a fractional component:

let pi: Double = 3.14159
let billAmount: Double = 10.25


4. Strings

Strings represent a series of characters:

let hello: String = "Hello"
let world: String = "World"

We can use string interpolation to construct new strings:

let helloWorld: String = "\(hello) \(world)"    // "Hello World"

Or we can use the + operator to combine strings:

let helloWorld: String = hello + " " + world    // "Hello World"


5. Booleans

Boolean is a very simple type in Swift as it can only ever be true or false:

let swiftIsCool: Bool = true
let iMissObjectiveC: Bool = false 


6. Arrays

Arrays store a list of values that must be of the same type. Below we’ve kept track of the previous bill amounts (which is a list of doubles):

// Notice how we've used "var" here since we want to append new items to the array
var previousBillAmounts: [Double] = [10.25, 21.32, 15.54]

To add a new bill to the array:

previousBillAmounts.append(52.45)    // Result: [10.25, 21.32, 15.54, 52.45]

To check on how many bills there are in the array:

let count = previousBillAmounts.count            // Result: 4

Or to check the first bill amount in the array:

let firstBillAmount = previousBillAmounts[0]    // Result: 10.25


7. Dictionaries

Much like we might use a real-world dictionary to look up the definition for a word, you can use the dictionary data structure in Swift to create associations between keys (the word in the real-world dictionary) and values (the definition in the real-world dictionary).

For example, let’s say we want to keep track of the ages of people that are using our app. This will best done using the following dictionary:

var people: [String: Int] = [
                              "Bob": 32,
                              "Cindy": 25
                            ]

Here, the key is the name of the person and the value is the person’s age.

Later on if we want to find out Bob’s age, we can look it up by doing:

let bobsAge = people["Bob"]

If we get a new user we can easily add them to our dictionary using the following syntax:

people["Dan"] = 56


8. Specifying Types

In most of the examples in this article, we are explicit with the types of our constants and variables. Explicit typing looks something like:

let name: String = "Bob"   // Explicitly designating "name" to be of type "String"

However, Swift is smart enough to infer the type for us in a lot of cases. The short example of previous example is:

let name = "Bob"   // Swift infers "name" is of type "String" since "Bob" is a String

In cases where Swift can infer the type, it’s not necessary to be explicit with the types for our constants and variables. We just do it in this guide so that the examples are easier to follow.


9. Any and AnyObject

Swift has two special “catch all types” that come in handy when a more specific type cannot determine.

  • AnyObject can represent an instance of any class type.
  • Any can represent an instance of any type at all.

In general, it’s a best practice to be as specific with our types as possible and avoid the use of AnyObject and Any, but they become particularly helpful when interacting with Objective-C code that is less strict on typing.


10. Optionals

Optionals is a very important concept in Swift and it means to improve the safety of Swift code. By simply placing a question mark (?) after any type, it declares that variable to be optional. An optional type allows that variable to exist in one of the following two states:

  1. There is a value and it equals x
  2. There isn’t a value at all

Let’s look at an example to make this more clear. Consider the following 2 examples where we are trying to convert a String to an Int:

// Example 1 (Conversion succeeds)
let input: String = "123"
let optionalConvertedInput: Int? = Int(input)  // optionalConvertedInput = 123

// Example 2 (Conversion fails - input is not a number)
let input: String = "123abc"
let optionalConvertedInput: Int? = Int(input)  // optionalConvertedInput = nil

Swift requires optionalConvertedInput to be of type Int? (or “optional Int”) so that it is explicit that convertedInput might not contain a value (in the case when the conversion fails). If we were to declare convertedInput as simply Int, we’d get a compile error.

There’s a handy syntax in Swift that we’ll use quite often when working with optionals. If we wanted to use the value of optionalConvertedInput later on in our code, we’d have to first check to make sure it’s not nil. We can do so using the following code:

if let convertedInput = optionalConvertedInput {
   // Code that gets executed when optionalConvertedInput is NOT nil
} else {
   // OptionalConvertedInput IS nil, do something else
}

In other languages like Java, NullPointerException is a common source of crashes. This exception fires when a null reference accesses. Swift’s Optionals go a long way to reduce this type of programming error.


Optionals in string interpolation

When using optionals in string interpolation, the value with either be Optional(...) or nil without being explicitly unwrapped. When the inner value needs, the optional must unwrap.

let maybeString: String? = "value"

print("\(maybeString)")  // prints -> Optional("value")
print("\(maybeString!)")  // prints -> "value"


11. Functions

Functions in Swift are very similar to other languages. The simplest function in Swift can write as:

// This prints "Hello!" to the output window
func printHello() {
    print("Hello!")
}

// Calls this function
printHello()

We can extend this function to be a little more personable by taking in a name and returning the greeting instead of printing it out:

// Takes in a "personName" parameter of type String and returns the greeting as a String
func sayHello(personName: String) -> String {
    // Implicitly returns when there is a single statement
    "Hello \(personName)!"
}

// Calls this function
let greeting: String = sayHello("Bob")

Things get a little more interesting when we start to have multiple parameters as Swift has the concept of external and local parameter names. An external parameter name is used to label arguments passed to a function call. A local parameter name is a name used in the implementation of the function.

// "to" + "and" are the external parameter names
// "person" + "anotherPerson" are the local parameter names
func sayHello(to person: String, and anotherPerson: String) -> String {
    "Hello \(person) and \(anotherPerson)!"
}

// Calls this function using the "external" parameter names
let greeting: String = sayHello(to: "Bill", and: "Ted")


12. Control Flow


Conditional Statements

If statements are very similar to other languages and can express as:

let temperatureInFahrenheit: Int = 90

if temperatureInFahrenheit <= 32 {
    print("It's very cold. Consider wearing a scarf.")
} else if temperatureInFahrenheit >= 86 {
    print("It's really warm. Don't forget to wear sunscreen.")
} else {
    print("It's not that cold. Wear a t-shirt.")
}


Loops

The two most common types of loops we’ll need in Swift are for loops and for-in loops.

For loops work well when we want to do something until a particular condition is met (in the case below until index >= 3):

// Simple for loop that prints "Hello" 3 times
for var index = 0; index < 3; index++ {
    print("Hello")
}

C-style for loops deprecated and will remove in future versions of Swift. For-in loops are preferred instead. The above example could be re-written as:

for _ in 0..<3 {
          print("Hello")
      }

For-in loops come in really handy when we want to do something to each item in a collection (such as an array):

let names = ["Anna", "Alex", "Brian", "Jack"]

// Loops over each name in "names" and prints out a greeting for each person
for name in names {
    print("Hello, \(name)!")
}

Sometimes, we want to loop over each item in an array and also keep track of the index of the item. Array’s enumerated() method can help you achieve this:

let names = ["Anna", "Alex", "Brian", "Jack"]

for (index, value) in names.enumerated() {
    print("Item \(index + 1): \(value)")
}


13. Classes

Classes are the building blocks of our app’s code. We define properties and methods to add functionality to our classes by using the same syntax as for variables and functions.

Below we can find a Person class that is meant to show an example of the types of things we’ll want to do when building our classes.

class Person {
	
    // Custom initializer - takes in firstName and lastName
    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName

        // Increment type property each time a new person is created
        Person.numberOfPeople++
    }
	
    // *** Properties ***
	
    // Stored Property - Stored as part of the current instance of the class
    var firstName: String
    var lastName: String

    // Computed Property - computes "fullName" from "firstName" and "lastName"
    var fullName: String {
    	get {
            "\(firstName) \(lastName)"
    	}
    }

    // Type Property - Single instance for all instances of the class,
    // similar to a static property in Java
    static var numberOfPeople = 0   
    
    // *** Methods ***
    
    // Instance Method
    func greet() {
    	// Notice the use of "self" - self refers to the current instance and 
        // is similar to "this" in Java
    	print ("Hello \(self.firstName)")
    }
    
    // Type Method
    class func printNumberOfPeople() {
    	print("Number of people = \(Person.numberOfPeople)")
    }
}

// ... Using the Person Class ...

// Create a new instance of the Person class
let bob = Person(firstName: "Bob", lastName: "Smith")

// Call instance method
bob.greet()   // Prints "Hello Bob"

// Accessing properies
print("Bob's first name is: \(bob.firstName)")  // Prints "Bob's first name is: Bob"
print("Bob's full name is: \(bob.fullName)")    // Prints "Bob's full name is: Bob Smith"

// Call type method
// Prints "Number of people = 1" (since we've only created one Person)
Person.printNumberOfPeople()


14. Protocols

Protocols are similar to interfaces in other languages. Think about a protocol as a contract. The contract includes a set of methods that must be implemented. Any classes that choose to implement a protocol sign this contract and implement all the methods that are in the protocol.

Let’s say we have the following protocol (MyFriendlyGreeterProtocol) that defines 2 methods sayHello() and sayBye():

protocol MyFriendlyGreeterProtocol {
    func sayHello()
    func sayBye()
}

Any classes that implement this protocol (you implement a protocol by adding its name after the class defintion as shown below), must implement both of these methods:

class MyEnglishPerson: MyFriendlyGreeterProtocol {
    func sayHello() {
        print("Hello!")
    }

    func sayBye() {
        print("Bye!")
    }
	
    // ... other methods for this class ...

}

class MySpanishPerson: MyFriendlyGreeterProtocol {
    func sayHello() {
        print("Hola!")
    }

    func sayBye() {
        print("Adios!")
    }
	
    // ... other methods for this class ...
}

There is a lot more you can do with protocols as they form one of the key design patterns in iOS. The code above merely shows how to get started with the syntax for protocols.


15. Swift Closures

Closures are self-contained blocks of code that can be passed around and used in our code. These are similar to blocks in Objective-C and lambdas in other programming languages.

Swift Closures can capture and store references to any constants and variables from the context in which they are defined. This is known as “closing” over those constants and variables. Swift handles all of the memory management of capturing for you.

Closure Example:

Example: A function called makeIncrementer which contains a nested function

Here’s an example of a function called makeIncrementer, which contains a nested function called incrementer. The nested incrementer() function captures two values, runningTotal and amount, from its surrounding context. After capturing these values, incrementer is returned by makeIncrementer as a closure that increments runningTotal by amount each time it is called.

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

The return type of makeIncrementer is () -> Int. This means that it returns a function, rather than a simple value. The function it returns has no parameters, and returns an Int value each time it is called.

The makeIncrementer(forIncrement:) function defines an integer variable called runningTotal, to store the current running total of the incrementer that will be returned. This variable is initialized with a value of 0.

The makeIncrementer(forIncrement:) function has a single Int parameter with an external name of forIncrement, and a local name of amount. The argument value passed to this parameter specifies how much runningTotal should be incremented by each time the returned incrementer function is called.

makeIncrementer defines a nested function called incrementer, which performs the actual incrementing. This function simply adds amount to runningTotal, and returns the result.

When considered in isolation, the nested incrementer() function might seem unusual:

func incrementer() -> Int {
    runningTotal += amount
    return runningTotal
}

The incrementer() function doesn’t have any parameters, and yet it refers to runningTotal and amount from within its function body. It does this by capturing a reference to runningTotal and amount from the surrounding function and using them within its own function body. Capturing by reference ensures that runningTotal and amount do not disappear when the call to makeIncrementer ends, and also ensures that runningTotal is available the next time the incrementer function is called.

Example: a function called makeIncrementer in action

Here’s an example of makeIncrementer in action:

// This example sets a constant called incrementByTen to refer to an //incrementer function that
// adds 10 to its runningTotal variable each time it is called.

let incrementByTen = makeIncrementer(forIncrement: 10)

incrementByTen()  // returns a value of 10
incrementByTen()  // returns a value of 20
incrementByTen()  // returns a value of 30


16. Type Casting (as, as?, as!)

Type casting changes the type of a particular instance to another compatible type. There are 3 ways to accomplish this with Swift:

  1. Guaranteed conversion with as : This is the safest cast. It will never fail since the compiler can guarantee the cast will work. Use this when you are upcasting from a child class to its parent or doing something like 1 as Float.
// Guaranteed conversion as the compiler can verify this will succeed
let myFloat = 1 as Float

// Guaranteed conversion as upcasting from a type to its parent type is safe 
// UIView is a parent of UITableView
let myView = myTableView as UIView

2. Conditional conversion with as? : This is a cautious cast. If the cast fails, it will return nil. This is needed when downcasting from a parent type to a child type.

// If myView is actually a tableView, the downcast will succeed, otherwise it will fail safely
if let myTableView = myView as? UITableView {
    print("The downcast succeeded!")
} else {
    print("The downcast failed!")   	   
}

3. Forced conversion with as! : This is a dangerous cast that you should avoid using. If the cast fails, this will crash our app. Use this cast carefully.

// DANGEROUS: If myView is actually a tableView, the downcast will succeed
// Otherwise it will crash the app
let myTableView = myView as! UITableView


17. Understanding the Exclamation Mark (!)

There are various places you might come across an exclamation mark in Swift code. The following examples are meant to capture the major types of use cases for the exclamation mark operator that can cause confusion when first learning Swift.

When getting the actual value out of an optional (called unwrapping an optional):

let possibleString: String? = "An optional string."

// DANGEROUS: possibleString must NOT be nil or this will crash
let forcedString: String = possibleString! 

// SAFE: Will only enter the if clause if possibleString is NOT nil
if let actualString = possibleString {
    // do something with actualString
}

// SAFE: Generally preferred alternate syntax to "if let" that can exit early
guard let actualString = possibleString else {
    // exit early or throw exception
}
// do something with actualString

When type casting (called forced conversion):

// DANGEROUS: If myView is actually a tableView, the downcast will succeed
// Otherwise it will crash the app
let myTableView = myView as! UITableView

When defining variables that are initially nil but get set soon afterwards and are guaranteed not to be nil after that (called implicitly unwrapped optionals):

let assumedString: String! = "An implicitly unwrapped optional string."

// no need for an exclamation mark since assumedString is an implicitly unwrapped optional
let implicitString: String = assumedString


18. Property Observers

A very useful inclusion of the Swift language is Property Observers. While the language might sound complex, it’s actually a literal explanation of what it does. It allows you to observe properties and respond to impending or finished property changes. It’s part of Apple’s goal to make Swift a cleaner language because a developer merely has to keep any logic related to updating properties in one convenient place.

Let’s look at an example.

Assume we have a Fitness tracking application and whenever a user enters their weight, we calculate and display their BMI to them.

Without property observers, and keeping in good practice (since BMI is calculated and not set in initialization), we might have a class like this –

Swift

class Profile {
    let height: Double
    var weight: Double
    private var BMI: Double
    
    init(weight: Double, height: Double) {
        self.height = height
        self.weight = weight
        self.BMI = weight / (height*height)
    }
    
    func getBMI() -> Double {
        self.BMI
    }
    
    func updateBMI() {
        self.BMI = weight / (height*height)
    }
}  

In a view where we ask the user to enter their new weight, we would call profile.updateBMI() after the new weight is set. Isn’t this a little tedious? It’s almost a trap for developers. We have to actively remember that we should update our BMI every time we update our weight.

Thankfully, with property observers, we don’t have to actively watch every property change as a developer. Our class becomes –

class Profile {
    let height: Double
    var weight: Double {
        didSet {
            updateBMI()
        }
    }
    private var BMI: Double
    
    init(weight: Double, height: Double) {
        self.height = height
        self.weight = weight
        self.BMI = weight / (height*height)
    }
    
    func getBMI() -> Double {
        self.BMI
    }
    
    func updateBMI() {
        self.BMI = weight / (height*height)
    }
}  

It might not look like much, but now whenever we update BMI, we don’t have to worry about calling updateBMI() and to be honest, we can clean this up even more by making BMI private(set), changing Profile to a struct and adding a mutating func.

struct Profile {
    let height: Double
    var weight: Double {
        didSet {
            updateBMI()
        }
    }
    private(set) var BMI: Double
    
    mutating private func updateBMI() {
        BMI = weight / (height * height)
    }
}  

What is mutating we ask? Well, normally Struct’s are read only. This is because in order for them to be fast, they need to take up space on Stack instead of Heap. A simple way to explain this is to imagine that Stack is writing with a Pen and Heap is writing with a Pencil. Some of you might think “well what’s the big deal? they both write.” But think about all the extra work that comes with a Pencil – We need an eraser, we have to clean the eraser off the paper and can end up using more material if we edit a lot. A pen, on the other hand, we just write (we’re assuming you’re not using an erasable pen or white-out) and it’s set.

Mutating gives us the ability to say, “Hey, this Struct will be read-only, but if I make it a variable, I might want to update its properties, so please give me the ability to edit that Struct”.

There’s a little more to this under the hood, but Structs tend to be pretty thread-safe, so we can assume every Struct exists by itself and it’s pretty safe to edit like this.


Other Property Observers

There are other property observers for every stage of a state change – willSet, set/get are included. willSet has the added ability of being able to compare newValue to the original value (called the property name).

A few hints about where didSet can be quite powerful is when dealing with network data and data sources. When a user has the ability to get objects from a server with a regular network call, a search and tapping a keyword, it can be useful if the var dataSource: [Models] has didSet to reload the data of the view. That way we won’t have to do it manually.


19. Working with JSON

A lot of the time when working with REST API’s (like Instagram, Twitter, etc), the data that comes back will be JSON. JSON is a human readable data format (very similar to XML).

Below is an example of JSON that simulates the type of JSON. We might get back when using an endpoint that returns movies and their ratings:

  • An open curly brace means the start of a dictionary
  • An open bracket means the start of an array
{
    "status": "OK",
    "movies": [
        {
            "title": "Whiplash",
            "rating": 8.5
        }, 
        {
            "title": "Feast",
            "rating": 5.2
        }, 
        {
            "title": "Kung Fury",
            "rating": 7.1
        }
    ]
}


Below is an example of how we extract the movies and ratings from that response:

// data returned from the network response will typically be of type
// NSData (which is a buffer of bytes)
let responseData: NSData = // ... some value retrieved from the network response ...

// Wrap our code in a do catch as our code might throw an exception which we need to handle
do {
    // Start by converting the NSData to a dictionary - a dictionary for the entire response
    if let responseDictionary = try NSJSONSerialization.JSONObjectWithData(responseData,
        options:NSJSONReadingOptions(rawValue:0)) as? [String:AnyObject] {

            // Dip inside the response to find the "movies" key and get the array of movies
            if let movies = responseDictionary["movies"] as? [AnyObject] {

                // Get each movie dictionary from the array of movies
                for movie in movies {
                
                    // Use the movie "title" key and "rating" key to get their values
                    if let title = movie["title"] as? String {
                        if let rating = movie["rating"] as? Double {
                            print("Title:\(title), rating:\(rating)")
                        }
                    }
                }
            }
    }
} catch {
    print("Error parsing JSON")
}


20. Playgrounds

Xcode includes a very useful tool for learning Swift called “Playgrounds”. It’s very easy to create a new playground through Xcode.

Once inside a playground, we can write Swift code and see it run immediately (without needing to build and run a project each time). This allows you to try out different syntaxes and test out our code before including it in our app.

We highly recommend checking out Playgrounds while we are learning Swift.

That’s all about in this article.

Related Other Articles / Posts


Conclusion

In this article, We discussed 20 quick valuable concepts which are the best way to learn swift and help to build iOS applications.

Thanks for reading! I hope you enjoyed and learned about the 20 quick valuable Swift Foundation Concepts. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

iOS – An Overview Of Swift Closures In iOS

Hello Readers, CoolMonkTechie heartily welcomes you in this article (An Overview Of Swift Closures In iOS) .

In this article, we will learn about Swift Closures in iOS. Swift Closures are other types of Swift functions which can be defined without using keyword func and a function name. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages. This article covers Swift Closures related concepts (like Closure Expressions, Trailing Closures, Capturing Values, Closure as Reference Types and Auto-closures) in iOS with an authentic example.

A famous quote about learning is :

” Develop a passion for learning. If you do, you will never cease to grow. ”

So Let’s begin.

Swift Closures Overview

Closures are self-contained blocks of functionality that can be passed around and used in our code. It is similar to blocks in C and Objective-C and to lambdas in other programming languages.”

Swift Closures can capture and store references to any constants and variables from the context in which they are defined. We know this as closing over those constants and variables. Swift handles all the memory management of capturing for us.

Global and nested functions are special cases of closures. Closures take one of three forms:

  • Global functions are closures that have a name and don’t capture any values.
  • Nested functions are closures that have a name and can capture values from their enclosing function.
  • Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.

Swift’s closure expressions have a clean and clear style, with optimizations that encourage brief, clutter-free syntax in common scenarios. These optimizations include:

  • Inferring parameter and return value types from context
  • Implicit returns from single-expression closures
  • Shorthand argument names
  • Trailing closure syntax

Swift Closure Expressions

Closure expressions are a way to write inline closures in a brief, focused syntax. Closure expressions provide several syntax optimizations for writing closures in a shortened form without loss of clarity or intent. The closure expression examples below illustrate these optimizations by refining a single example of the sorted(by:) method over several iterations, each of which expresses the same functionality in a more succinct way.

The Sorted Method

Swift’s standard library provides a method called sorted(by:), which sorts an array of values of a known type, based on the output of a sorting closure that we provide. Once it completes the sorting process, the sorted(by:) method returns a new array of the same type and size as the old one, with its elements in the correct sorted order. The original array is not modified by the sorted(by:) method.

The closure expression examples below use the sorted(by:) method to sort an array of String values in reverse alphabetical order. Here’s the initial array to be sorted:

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

The sorted(by:) method accepts a closure that takes two arguments of the same type as the array’s contents, and returns a Bool value to say whether the first value should appear before or after the second value once the values are sorted. The sorting closure needs to return true if the first value should appear before the second value, and false otherwise.

This example is sorting an array of String values, and so the sorting closure needs to be a function of type (String, String) -> Bool.

One way to provide the sorting closure is to write a normal function of the correct type, and to pass it in as an argument to the sorted(by:) method:

func backward(_ s1: String, _ s2: String) -> Bool {
    return s1 > s2
}
var reversedNames = names.sorted(by: backward)
// reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

In this example, if the first string (s1) is greater than the second string (s2), the backward (_:_:) function will return true, it is showing that s1 should appear before s2 in the sorted array. For characters in strings, “greater than” means “appears later in the alphabet than”. This means that the letter (B) is greater than the letter (A), and the string (Tom) is greater than the string (Tim). This gives a reverse alphabetical sort, with (Barry) being placed before (Alex), and so on.

However, this is a rather long-winded way to write what is essentially a single-expression function (a > b). In this example, it would be preferable to write the sorting closure inline, using closure expression syntax.

Closure Expression Syntax

Closure expression syntax has the following general form:

{ (parameters) -> return type in
    statements
}

The parameters in closure expression syntax can be in-out parameters, but they can’t have a default value. Variadic parameters can be used if we name the variadic parameter. Tuples can also be used as parameter types and return types.

The example below shows a closure expression version of the backward(_:_:) function from above:

reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})

We are aware that the declaration of parameters and return type for this inline closure is identical to the declaration from the backward(_:_:) function. In both cases, it is written as (s1: String, s2: String) -> Bool. However, for the inline closure expression, the parameters and return type are written inside the curly braces, not outside of them.

The start of the closure’s body is introduced by the in keyword. This keyword indicates that the definition of the closure’s parameters and return type has finished, and the body of the closure is about to begin.

Inferring Type From Context

Because the sorting closure is passed as an argument to a method, Swift can infer the types of its parameters and the type of the value it returns. The sorted(by:) method is being called on an array of strings, so its argument must be a function of type (String, String) -> Bool. This means that the (String, String) and Bool types don’t need to be written as part of the closure expression’s definition. Because all of the types can be inferred, the return arrow (->) and the parentheses around the names of the parameters can also be omitted:

reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )

It is always possible to infer the parameter types and return type when passing a closure to a function or method as an inline closure expression. As a result, we never need to write an inline closure in its fullest form when the closure is used as a function or method argument.

In the case of the sorted(by:) method, the purpose of the closure is clear from the fact that sorting is taking place, and it is safe for a reader to assume that the closure is likely to be working with String values, because it is assisting with the sorting of an array of strings.

Implicit Returns from Single-Expression Closures

Single-expression closures can implicitly return the result of their single expression by omitting the return keyword from their declaration, as in this version of the previous example:

reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )

Here, the function type of the sorted(by:) method’s argument makes it clear that a Bool value must be returned by the closure. Because the closure’s body contains a single expression (s1 > s2) that returns a Bool value, there’s no ambiguity, and the return keyword can be omitted.

Shorthand Argument Names

Swift automatically provides shorthand argument names to inline closures, which can be used to refer to the values of the closure’s arguments by the names $0$1$2, and so on.

If we use these shorthand argument names within our closure expression, we can omit the closure’s argument list from its definition, and the number and type of the shorthand argument names will be inferred from the expected function type. The in keyword can also be omitted, because the closure expression is made up entirely of its body:

reversedNames = names.sorted(by: { $0 > $1 } )

Here, $0 and $1 refer to the closure’s first and second String arguments.

Operator Methods

This is an even shorter way to write the closure expression above. Swift’s String type defines its string-specific implementation of the greater-than operator (>) as a method that has two parameters of type String, and returns a value of type Bool. This exactly matches the method type needed by the sorted(by:) method. Therefore, we can simply pass in the greater-than operator, and Swift will infer that we want to use its string-specific implementation:

reversedNames = names.sorted(by: >)

Trailing Swift Closures

If we need to pass a closure expression to a function as the function’s final argument and the closure expression is long, it can be useful to write it as a trailing closure instead. We write a trailing closure after the function call’s parentheses, even though the trailing closure is still an argument to the function.When we use the trailing closure syntax, we don’t write the argument label for the first closure as part of the function call.

A function call can include multiple trailing closures; however, the first few examples below use a single trailing closure.

func someFunctionThatTakesAClosure(closure: () -> Void) {
    // function body goes here
}

// Here's how you call this function without using a trailing closure:

someFunctionThatTakesAClosure(closure: {
    // closure's body goes here
})

// Here's how you call this function with a trailing closure instead:

someFunctionThatTakesAClosure() {
    // trailing closure's body goes here
}

The string-sorting closure from the Closure Expression Syntax section above can be written outside of the sorted(by:) method’s parentheses as a trailing closure:

reversedNames = names.sorted() { $0 > $1 }

If a closure expression is provided as the function’s or method’s only argument and we provide that expression as a trailing closure, we don’t need to write a pair of parentheses () after the function or method’s name when we call the function:

reversedNames = names.sorted { $0 > $1 }

Trailing closures are most useful when the closure is sufficiently long that it is not possible to write it inline on a single line.

Example

If a function takes multiple closures, we omit the argument label for the first trailing closure and we label the remaining trailing closures. For example, the function below loads a picture for a photo gallery:

func loadPicture(from server: Server, completion: (Picture) -> Void, onFailure: () -> Void) {
    if let picture = download("photo.jpg", from: server) {
        completion(picture)
    } else {
        onFailure()
    }
}

When we call this function to load a picture, we provide two closures. The first closure is a completion handler that displays a picture after a successful download. The second closure is an error handler that displays an error to the user.

loadPicture(from: someServer) { picture in
    someView.currentPicture = picture
} onFailure: {
    print("Couldn't download the next picture.")
}

In this example, the loadPicture(from:completion:onFailure:) function dispatches its network task into the background, and calls one of the two completion handlers when the network task finishes. Writing the function this way lets us cleanly separate the code that’s responsible for handling a network failure from the code that updates the user interface after a successful download, instead of using just one closure that handles both circumstances.

Capturing Values In Swift Closures

A closure can capture constants and variables from the surrounding context in which it is defined. The closure can then refer to and modify the values of those constants and variables from within its body, even if the original scope that defined the constants and variables no longer exists.

In Swift, the simplest form of a closure that can capture values is a nested function, written within the body of another function. A nested function can capture any of its outer function’s arguments and can also capture any constants and variables defined within the outer function.

Example

Here’s an example of a function called makeIncrementer, which contains a nested function called incrementer. The nested incrementer() function captures two values, runningTotal and amount, from its surrounding context. After capturing these values, incrementer is returned by makeIncrementer as a closure that increments runningTotal by amount each time it is called.

Code Syntax 1: makeIncrementer() function

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

The return type of makeIncrementer is () -> Int. This means that it returns a function, rather than a simple value. The function it returns has no parameters, and returns an Int value each time it is called.

The makeIncrementer(forIncrement:) function defines an integer variable called runningTotal, to store the current running total of the incrementer that will be returned. This variable is initialized with a value of 0.

The makeIncrementer(forIncrement:) function has a single Int parameter with an argument label of forIncrement, and a parameter name of amount. The argument value passed to this parameter specifies how much runningTotal should be incremented by each time the returned incrementer function is called. The makeIncrementer function defines a nested function called incrementer, which performs the actual incrementing. This function simply adds amount to runningTotal, and returns the result.

Code Syntax 2: incrementer() function

When considered in isolation, the nested incrementer() function might seem unusual:

func incrementer() -> Int {
    runningTotal += amount
    return runningTotal
}

The incrementer() function doesn’t have any parameters, and yet it refers to runningTotal and amount from within its function body. It does this by capturing a reference to runningTotal and amount from the surrounding function and using them within its own function body. Capturing by reference ensures that runningTotal and amount don’t disappear when the call to makeIncrementer ends, and also ensures that runningTotal is available the next time the incrementer function is called.

Code Syntax 3: makeIncrementer() function usage

Here’s an example of makeIncrementer usage is :

let incrementByTen = makeIncrementer(forIncrement: 10)

This example sets a constant called incrementByTen to refer to an incrementer function that adds 10 to its runningTotal variable each time it is called. Calling the function multiple times shows this behavior in action:

incrementByTen()
// returns a value of 10
incrementByTen()
// returns a value of 20
incrementByTen()
// returns a value of 30

If we create a second incrementer, it will have its own stored reference to a new, separate runningTotal variable:

let incrementBySeven = makeIncrementer(forIncrement: 7)
incrementBySeven()
// returns a value of 7

Calling the original incrementer (incrementByTen) again continues to increment its own runningTotal variable, and does not affect the variable captured by incrementBySeven:

incrementByTen()
// returns a value of 40

We are aware that Swift may instead capture and store a copy of a value as an optimization, if that value is not mutated by a closure, and if the value is not mutated after the closure is created.

Swift also handles all memory management involved in disposing of variables when they are no longer needed.

If we assign a closure to a property of a class instance, and the closure captures that instance by referring to the instance or its members, we will create a strong reference cycle between the closure and the instance. Swift uses capture lists to break these strong reference cycles.

Swift Closures As Reference Types

In the example above, incrementBySeven and incrementByTen are constants, but the closures these constants refer to are still able to increment the runningTotal variables that they have captured. This is because functions and closures are reference types.

Whenever we assign a function or a closure to a constant or a variable, we are actually setting that constant or variable to be reference to the function or closure.

Example

In the example above, it is the choice of closure that incrementByTen refers to that is constant, and not the contents of the closure itself.

This also means that if we assign a closure to two different constants or variables, both of those constants or variables refer to the same closure.

let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
// returns a value of 50

incrementByTen()
// returns a value of 60

The example above shows that calling alsoIncrementByTen is the same as calling incrementByTen. Because both of them refer to the same closure, they both increment and return the same running total.

Escaping Swift Closures

A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When we declare a function that takes a closure as one of its parameters, we can write @escaping before the parameter’s type to indicate that the closure is allowed to escape.

One way that a closure can escape is by being stored in a variable that’s defined outside the function.

Example

As an example, many functions that start an asynchronous operation take a closure argument as a completion handler. The function returns after it starts the operation, but the closure isn’t called until the operation is completed—the closure needs to escape, to be called later.

Code Syntax 1 : someFunctionWithEscapingClosure() function

var completionHandlers = [() -> Void]()
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}

The someFunctionWithEscapingClosure(_:) function takes a closure as its argument and adds it to an array that’s declared outside the function. If we didn’t mark the parameter of this function with @escaping, we would get a compile-time error.

An escaping closure that refers to self needs special consideration if self refers to an instance of a class. Capturing self in an escaping closure makes it easy to accidentally create a strong reference cycle.

Normally, a closure captures variables implicitly by using them in the body of the closure, but in this case we need to be explicit. If we want to capture self, write self explicitly when we use it, or include self in the closure’s capture list. Writing self explicitly lets we express our intent, and reminds us to confirm that there isn’t a reference cycle.

Code Syntax 2 : doSomething() function

For example, in the code below, the closure passed to someFunctionWithEscapingClosure(_:) refers to self explicitly. In contrast, the closure passed to someFunctionWithNonescapingClosure(_:) is a non-escaping closure, which means it can refer to self implicitly.

func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}

class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { self.x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints "200"

completionHandlers.first?()
print(instance.x)
// Prints "100"

Here’s a version of doSomething() that captures self by including it in the closure’s capture list, and then refers to self implicitly:

class SomeOtherClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { [self] in x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}

If self is an instance of a structure or an enumeration, we can always refer to self implicitly. However, an escaping closure can’t capture a mutable reference to self when self is an instance of a structure or an enumeration. Structures and enumerations don’t allow shared mutability.

struct SomeStruct {
    var x = 10
    mutating func doSomething() {
        someFunctionWithNonescapingClosure { x = 200 }  // Ok
        someFunctionWithEscapingClosure { x = 100 }     // Error
    }
}

The call to the someFunctionWithEscapingClosure function in the example above is an error because it’s inside a mutating method, so self is mutable. That violates the rule that escaping closures can’t capture a mutable reference to self for structures.

Auto-closures

An auto-closure is a closure that is automatically created to wrap an expression that’s being passed as an argument to a function. It doesn’t take any arguments, and when it’s called, it returns the value of the expression that’s wrapped inside of it. This syntactic convenience lets us omit braces around a function’s parameter by writing a normal expression instead of an explicit closure. It’s common to call functions that take auto-closures, but it’s not common to implement that kind of function.

For example, the assert(condition:message:file:line:) function takes an auto-closure for its condition and message parameters; its condition parameter is evaluated only in debug builds and its message parameter is evaluated only if condition is false.

An auto-closure lets us delay evaluation, because the code inside isn’t run until we call the closure. Delaying evaluation is useful for code that has side effects or is computationally expensive, because it lets us control when that code is evaluated.

Code Syntax 1 : Closure delays evaluation

The code below shows how a closure delays evaluation.

var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Prints "5"

let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// Prints "5"

print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// Prints "4"

Even though the first element of the customersInLine array is removed by the code inside the closure, the array element isn’t removed until the closure is actually called. If the closure is not called, the expression inside the closure is not evaluated. It means the array element is not removed. We are aware that the type of customerProvider is not String but () -> String — a function with no parameters that returns a string.

Code Syntax 2 : Closure as an argument to a function

We can get the same behavior of delayed evaluation when we pass a closure as an argument to a function.

// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) } )
// Prints "Now serving Alex!"

The serve(customer:) function in the listing above takes an explicit closure that returns a customer’s name. The version of serve(customer:) below performs the same operation but, instead of taking an explicit closure, it takes an auto-closure by marking its parameter’s type with the @autoclosure attribute. Now we can call the function as if it took a String argument instead of a closure. The argument is automatically converted to a closure, because the customerProvider parameter’s type is marked with the @autoclosure attribute.

// customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// Prints "Now serving Ewa!"

If we want an auto-closure that is allowed to escape, use both the @autoclosure and @escaping attributes.

// customersInLine is ["Barry", "Daniella"]
var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
    customerProviders.append(customerProvider)
}
collectCustomerProviders(customersInLine.remove(at: 0))
collectCustomerProviders(customersInLine.remove(at: 0))

print("Collected \(customerProviders.count) closures.")
// Prints "Collected 2 closures."
for customerProvider in customerProviders {
    print("Now serving \(customerProvider())!")
}
// Prints "Now serving Barry!"
// Prints "Now serving Daniella!"

In the code above, instead of calling the closure passed to it as its customerProvider argument, the collectCustomerProviders(_:) function appends the closure to the customerProviders array. The array is declared outside the scope of the function, which means the closures in the array can be executed after the function returns. As a result, the value of the customerProvider argument must be allowed to escape the function’s scope.

That’s all about in this article.

Related Other Articles / Posts

Conclusion

In this article, we understood Swift Closures in iOS. This article reviewed Swift Closures related concepts (like Closure Expressions, Trailing Closures, Capturing Values, Closure as Reference Types and Auto-closures) in iOS with an authentic example.

Thanks for reading! I hope you enjoyed and learned about Swift Closures Concepts in iOS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING!!???

iOS – An Overview Of Memory Safety In Swift

Hello Readers, CoolMonkTechie heartily welcomes you in this article (An Overview Of Memory Safety In Swift) .

In this article, we will learn about an overview of Memory Safety in Swift. Swift handles most memory safety automatically, to avoid conflicts. However, certain functions may cause conflicts and will either cause compile time or runtime errors. This article reviews the access conflict to memory (like In-Out Parameters, self in Methods and Properties) in swift.

A famous quote about learning is :

” One learns from books and example only that certain things can be done. Actual learning requires that you do those things.”

So Let’s begin.

Memory Safety Overview

Swift monitors risky behaviour that may occur in the code. For example, Swift ensures that variables are introduced before they’re utilized, likewise, memory isn’t accessed once its deallocated, and array indices are checked for out-of-bounds errors.

Swift also makes sure that multiple accesses to the same area of memory don’t conflict, by requiring code that modifies a location in memory to have exclusive access to that memory. Because Swift manages memory automatically, most of the time we don’t have to think about accessing memory at all. However, it’s important to understand where potential conflicts can occur, so we can avoid writing code that has conflicting access to memory. If our code does contain conflicts, we’ll get a compile-time or runtime error.

Understanding Conflicting Access to Memory

Memory access happens in our code when we do things like set the value of a variable or pass an argument to a function. For example, the following code contains both a read access and a write access:

// A write access to the memory where one is stored.
var one = 1

// A read access from the memory where one is stored.
print("We're number \(one)!")

A conflicting access to memory can occur when different parts of our code are trying to access the same location in memory at the same time. Multiple accesses to a location in memory at the same time can produce unpredictable or inconsistent behavior. In Swift, there are ways to modify a value that span several lines of code, making it possible to attempt to access a value in the middle of its own modification.

We can see a similar problem by thinking about how we update a budget that’s written on a piece of paper. Updating the budget is a two-step process: First, we add the items’ names and prices, and then we change the total amount to reflect the items currently on the list. Before and after the update, we can read any information from the budget and get a correct answer, as shown in the figure below.

Source : Swift.org – Memory Shopping

While we’re adding items to the budget, it’s in a temporary, invalid state because the total amount hasn’t been updated to reflect the newly added items. Reading the total amount during the process of adding an item gives us incorrect information.

This example also demonstrates a challenge we may encounter when fixing conflicting access to memory: There are sometimes multiple ways to fix the conflict that produce different answers, and it’s not always obvious which answer is correct. In this example, depending on whether we wanted the original total amount or the updated total amount, either $5 or $320 could be the correct answer. Before we can fix the conflicting access, we have to determine what it was intended to do.

” If we’ve written concurrent or multithreaded code, conflicting access to memory might be a familiar problem. However, the conflicting access discussed here can happen on a single thread and doesn’t involve concurrent or multithreaded code. ”

” If we have conflicting access to memory from within a single thread, Swift guarantees that we’ll get an error at either compile time or runtime. For multithreaded code, use Thread Sanitizer to help detect conflicting access across threads. “

Characteristics of Memory Access

There are three characteristics of memory access to consider in the context of conflicting access: whether the access is a read or a write, the duration of the access, and the location in memory being accessed. Specifically, a conflict occurs if we have two accesses that meet all of the following conditions:

  • At least one is a write access or a nonatomic access.
  • They access the same location in memory.
  • Their durations overlap.

The difference between a read and write access is usually obvious: a write access changes the location in memory, but a read access doesn’t. The location in memory refers to what is being accessed—for example, a variable, constant, or property. The duration of a memory access is either instantaneous or long-term.

An operation is atomic if it uses only C atomic operations; otherwise it’s nonatomic. An access is instantaneous if it’s not possible for other code to run after that access starts but before it ends. By their nature, two instantaneous accesses can’t happen at the same time. Most memory access is instantaneous. For example, all the read and write accesses in the code listing below are instantaneous:

func oneMore(than number: Int) -> Int {
    return number + 1
}

var myNumber = 1
myNumber = oneMore(than: myNumber)
print(myNumber)
// Prints "2"

However, there are several ways to access memory, called long-term accesses, that span the execution of other code. The difference between instantaneous access and long-term access is that it’s possible for other code to run after a long-term access starts but before it ends, which is called overlap. A long-term access can overlap with other long-term accesses and instantaneous accesses.

Overlapping accesses appear primarily in code that uses in-out parameters in functions and methods or mutating methods of a structure.

Conflicting Access to In-Out Parameters

In this section, we will discuss the specific kinds of Swift code that use long-term accesses. A function has long-term write access to all of its in-out parameters. The write access for an in-out parameter starts after all of the non-in-out parameters have been evaluated and lasts for the entire duration of that function call. If there are multiple in-out parameters, the write accesses start in the same order as the parameters appear.

One consequence of this long-term write access is that we can’t access the original variable that was passed as in-out, even if scoping rules and access control would otherwise permit it—any access to the original creates a conflict. For example:

var stepSize = 1

func increment(_ number: inout Int) {
    number += stepSize
}

increment(&stepSize)
// Error: conflicting accesses to stepSize

In the code above, stepSize is a global variable, and it is normally accessible from within increment(_:). However, the read access to stepSize overlaps with the write access to number.

Source : Swift.org – Memory Increment

As shown in the figure above, both number and stepSize refer to the same location in memory. The read and write accesses refer to the same memory and they overlap, producing a conflict.

One way to solve this conflict is to make an explicit copy of stepSize:

// Make an explicit copy.
var copyOfStepSize = stepSize
increment(&copyOfStepSize)

// Update the original.
stepSize = copyOfStepSize
// stepSize is now 2

When we make a copy of stepSize before calling increment(_:), it’s clear that the value of copyOfStepSize is incremented by the current step size. The read access ends before the write access starts, so there isn’t a conflict.

Another consequence of long-term write access to in-out parameters is that passing a single variable as the argument for multiple in-out parameters of the same function produces a conflict. For example:

func balance(_ x: inout Int, _ y: inout Int) {
    let sum = x + y
    x = sum / 2
    y = sum - x
}
var playerOneScore = 42
var playerTwoScore = 30
balance(&playerOneScore, &playerTwoScore)  // OK
balance(&playerOneScore, &playerOneScore)
// Error: conflicting accesses to playerOneScore

In the above code, the balance(_:_:) function modifies its two parameters to divide the total value evenly between them. Calling it with playerOneScore and playerTwoScore as arguments doesn’t produce a conflict—there are two write accesses that overlap in time, but they access different locations in memory. In contrast, passing playerOneScore as the value for both parameters produces a conflict because it tries to perform two write accesses to the same location in memory at the same time.

Because operators are functions, they can also have long-term accesses to their in-out parameters. For example, if balance(_:_:) was an operator function named <^>, writing playerOneScore <^> playerOneScore would result in the same conflict as balance(&playerOneScore, &playerOneScore).

Conflicting Access to self in Methods

A mutating method on a structure has write access to self for the duration of the method call. For example, consider a game where each player has a health amount, which decreases when taking damage, and an energy amount, which decreases when using special abilities.

struct Player {
    var name: String
    var health: Int
    var energy: Int

    static let maxHealth = 10
    mutating func restoreHealth() {
        health = Player.maxHealth
    }
}

In the restoreHealth() method above, a write access to self starts at the beginning of the method and lasts until the method returns. In this case, there’s no other code inside restoreHealth() that could have an overlapping access to the properties of a Player instance. The shareHealth(with:) method below takes another Player instance as an in-out parameter, creating the possibility of overlapping accesses.

extension Player {
    mutating func shareHealth(with teammate: inout Player) {
        balance(&teammate.health, &health)
    }
}

var oscar = Player(name: "Oscar", health: 10, energy: 10)
var maria = Player(name: "Maria", health: 5, energy: 10)
oscar.shareHealth(with: &maria)  // OK

In the example above, calling the shareHealth(with:) method for Oscar’s player to share health with Maria’s player doesn’t cause a conflict. There’s a write access to oscar during the method call because oscar is the value of self in a mutating method, and there’s a write access to maria for the same duration because maria was passed as an in-out parameter. As shown in the figure below, they access different locations in memory. Even though the two write accesses overlap in time, they don’t conflict.

Source : Swift.org – Memory Share Health

However, if we pass oscar as the argument to shareHealth(with:), there’s a conflict:

oscar.shareHealth(with: &oscar)
// Error: conflicting accesses to oscar

The mutating method needs write access to self for the duration of the method, and the in-out parameter needs write access to teammate for the same duration. Within the method, both self and teammate refer to the same location in memory—as shown in the figure below. The two write accesses refer to the same memory and they overlap, producing a conflict.

Source : Swift.org – Memory Share Health Oscar

Conflicting Access to Properties

Types like structures, tuples, and enumerations are made up of individual constituent values, such as the properties of a structure or the elements of a tuple. Because these are value types, mutating any piece of the value mutates the whole value, meaning read or write access to one of the properties requires read or write access to the whole value. For example, overlapping write accesses to the elements of a tuple produces a conflict:

var playerInformation = (health: 10, energy: 20)
balance(&playerInformation.health, &playerInformation.energy)
// Error: conflicting access to properties of playerInformation

In the example above, calling balance(_:_:) on the elements of a tuple produces a conflict because there are overlapping write accesses to playerInformation. Both playerInformation.health and playerInformation.energy are passed as in-out parameters, which means balance(_:_:) needs write access to them for the duration of the function call. In both cases, a write access to the tuple element requires a write access to the entire tuple. This means there are two write accesses to playerInformation with durations that overlap, causing a conflict.

The code below shows that the same error appears for overlapping write accesses to the properties of a structure that’s stored in a global variable.

var holly = Player(name: "Holly", health: 10, energy: 10)
balance(&holly.health, &holly.energy)  // Error

In practice, most access to the properties of a structure can overlap safely. For example, if the variable holly in the example above is changed to a local variable instead of a global variable, the compiler can prove that overlapping access to stored properties of the structure is safe:

func someFunction() {
    var oscar = Player(name: "Oscar", health: 10, energy: 10)
    balance(&oscar.health, &oscar.energy)  // OK
}

In the example above, Oscar’s health and energy are passed as the two in-out parameters to balance(_:_:). The compiler can prove that memory safety is preserved because the two stored properties don’t interact in any way.

The restriction against overlapping access to properties of a structure isn’t always necessary to preserve memory safety. Memory safety is the desired guarantee, but exclusive access is a stricter requirement than memory safety—which means some code preserves memory safety, even though it violates exclusive access to memory. Swift allows this memory-safe code if the compiler can prove that the nonexclusive access to memory is still safe. Specifically, it can prove that overlapping access to properties of a structure is safe if the following conditions apply:

  • We’re accessing only stored properties of an instance, not computed properties or class properties.
  • The structure is the value of a local variable, not a global variable.
  • The structure is either not captured by any closures, or it’s captured only by non-escaping closures.

If the compiler can’t prove the access is safe, it doesn’t allow the access.

That’s all about in this article.

Conclusion

In this article, we understood an overview of Memory Safety in Swift. This article reviewed the access conflict to memory (like In-Out Parameters, self in Methods and Properties) in swift.

Thanks for reading! I hope you enjoyed and learned about Memory Safety Concepts in Swift. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING!!???

iOS – Why Are Architecture Patterns Important In iOS Application ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (Why are Architecture Patterns important in iOS application) .

In this article, we will learn about Architecture Patterns importance in iOS application. Every iOS developer is familiar with issues related to product testing, code refactoring and support via ViewController. We also know the latter as a Massive View Controller. In search for solutions, we’ve delved into a profound investigation of programming patterns for iOS. At some point we realize even this is not enough and time comes for iOS architecture patterns. So we analyzed top-5 patterns, putting them to test in real-life projects. It is important to understand that architectural patterns are not the solution for all problems. They only describe approaches to design mobile applications. Details of realization depend and vary. So we can ask some questions from ourself like these :

  • Who supposed to own networking request: a Model or a Controller?
  • How do I pass a Model into a View Model of a new View?
  • Who creates a new VIPER module: Router or Presenter?

In this article, we cover the following iOS architecture patterns which is used in iOS Application development :

  • Classic MVC
  • Apple’s MVC
  • MVP
  • MVVM
  • VIPER

A famous quote about learning is :

” That is what learning is. You suddenly understand something you’ve understood all your life, but in a new way.”

So Let’s begin.


Why care about choosing the architecture?

Because if we don’t, one day, debugging a huge class with dozens of different things, we’ll find ourself being unable to find and fix any bugs in our class. Naturally, it is hard to keep this class in mind as complete entity, thus, we’ll always be missing some important details. If we are already in this situation with our application, it is likely that:

  • This class is the UIViewController subclass.
  • Our data stored directly in the UIViewController
  • Our UIViews do almost nothing
  • The Model is a dumb data structure
  • Our Unit Tests cover nothing

And this can happen, even despite the fact that we are following Apple’s guidelines and implementing Apple’s MVC pattern, so don’t feel bad. There is something wrong with the Apple’s MVC, but we’ll get back to it later.

Let’s define features of a good architecture:

  1. Balanced distribution of responsibilities among entities with strict roles. The easiest way to defeat complexity is to divide responsibility among multiple entities following the single responsibility principle.
  2. Testability usually comes from the first feature (and don’t worry: it is easy with appropriate architecture).
  3. Ease of use and a low maintenance cost. The least code we have to use, the fewer bugs we have to worry about.


Why is Distribution required?

Distribution keeps a fair load on our brain while we are trying to figure out how things work. If we think the more we develop, the better our brain will adapt to understanding complexity, then we are right. But this ability doesn’t scale linearly and reaches the cap quickly. So the easiest way to defeat complexity is to divide responsibilities among multiple entities following the Single Responsibility Principle.


Why is Testability required?

This is usually not a question for those who already felt gratitude to unit tests, which failed after adding new features or because of refactoring some intricacies of the class. This means the tests saved those developers from finding issues in runtime, which might happen when an app is on a user’s device and the fix takes a week to reach the user.


Why Ease of use?

This does not require an answer, but it is worth mentioning that the best code is the code that has never been written. Therefore, the less code we have, the fewer bugs we have. This means that desire to write less code should never be explained solely by laziness of a developer, and we should not favour a smarter solution closing our eyes to its maintenance cost.


Essential Aspects of Application Architecture

There are five essential aspects of Application Architecture as below :

  • Separation of concern
  • State sharing
  • State propagation
  • View controller communication
  • Parallelism


Aim of Application Architecture

The purpose of Application Architecture is :

  • Fix the massive-view-controller issue
  • Increase testability
  • Improve maintainability
  • Scale with team size


iOS Architecture Patterns

Nowadays we have many options when it comes to architecture design patterns:

  • Classic MVC
  • Apple’s MVC
  • MVP
  • MVVM
  • VIPER

First three of them assume putting the entities of the app into one of 3 categories:

  • Models — responsible for the domain data or a data access layer which manipulates the data, think of ‘Person’ or ‘PersonDataProvider’ classes.
  • Views — responsible for the presentation layer (GUI), for iOS environment think of everything starting with ‘UI’ prefix.
  • Controller/Presenter/ViewModel — the glue or the mediator between the Model and the View responsible for altering the Model by reacting to the user’s actions performed on the View and updating the View with changes from the Model.

Having entities divided allows us to:

  • Understand them better (as we already know)
  • Reuse them (mostly applicable to the View and the Model)
  • Test them independently

So Let’s start with one by one patterns


1. Classic MVC

Here, the View is stateless. It is simply rendered by the Controller once the Model is changed. Think of the web page completely reloaded once. We press on the link to navigate somewhere else. Although it is possible to implement the traditional MVC in iOS application, it doesn’t make much sense because of the architectural problem — it tightly couples all three entities, each entity knows about the other two. This dramatically reduces reusability of each of them — that is not what you want to have in your application. For this reason, we skip even trying to write a canonical MVC example.

Traditional MVC doesn’t seem to be applicable to modern iOS development.


2. Apple’s MVC


Expection

The Controller is a mediator between the View and the Model so that they don’t know about each other. The least reusable is the Controller and this is usually fine for us, since we must have a place for all that tricky business logic that doesn’t fit into the Model.

In theory, it looks very straightforward, but we feel that something is wrong, right? We even heard people abbreviating MVC as the Massive View Controller. View controller offloading became an important topic for the iOS developers. Why does this happen if Apple just took the traditional MVC and improved it a bit?


Reality

Cocoa MVC encourages us to write Massive View Controllers, because they are so involved in View’s life cycle that it’s hard to say they are separate. Although we still have ability to offload some business logic and data transformation to the Model, we have a little choice for offloading work to the View, at most of the times all the responsibility of the View is to send actions to the Controller. The view controller ends up being a delegate and a data source of everything, and is usually responsible for dispatching and cancelling the network requests and… we name it.

How many times have we seen code like this:

var userCell = tableView.dequeueReusableCellWithIdentifier("identifier") as UserCell
userCell.configureWithUser(user)

The cell which is the View configured directly with the Model, so MVC guidelines are violated, but this happens all the time, and usually people don’t feel it is wrong. If we strictly follow the MVC, then we supposed to configure the cell from the controller, and don’t pass the Model into the View, and this will increase the size of our Controller even more.

Cocoa MVC is reasonably unabbreviated as the Massive View Controller.

The problem might not be clear until it comes to the Unit Testing (hopefully, it does in our project). Since our view controller is tightly coupled with the view, it becomes difficult to test because we have to be very creative in mocking views and their life cycle, while writing the view controller’s code in such a way, that our business logic is separated as much as possible from the view layout code.

Let’s have a look on the simple playground example:

/**
 * MVC iOS Design Pattern
 *
 */

import UIKit
import PlaygroundSupport

struct Person { // Model
    let firstName: String
    let lastName: String
}

class GreetingViewController : UIViewController {   // View + Controller
    var person: Person!
    var showGreetingButton: UIButton!
    var greetingLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)
        
        self.setupUIElements()
        self.layout()
    }
    
    func setupUIElements() {
        self.title = "Test"
        
        self._setupButton()
        self._setupLabel()
    }
    
    private func _setupButton() {
        self.showGreetingButton = UIButton()
        self.showGreetingButton.setTitle("Click me", for: .normal)
        self.showGreetingButton.setTitle("You badass", for: .highlighted)
        self.showGreetingButton.setTitleColor(UIColor.white, for: .normal)
        self.showGreetingButton.setTitleColor(UIColor.red, for: .highlighted)
        self.showGreetingButton.translatesAutoresizingMaskIntoConstraints = false
        self.showGreetingButton.addTarget(self, action: #selector(didTapButton(sender:)), for: .touchUpInside)
        self.view.addSubview(self.showGreetingButton)
    }
    
    private func _setupLabel() {
        self.greetingLabel = UILabel()
        self.greetingLabel.textColor = UIColor.white
        self.greetingLabel.textAlignment = .center
        self.greetingLabel.translatesAutoresizingMaskIntoConstraints = false
        self.view.addSubview(self.greetingLabel)
    }
    
    func layout() {
        self._layoutButton()
        self._layoutLabel()
        
        self.view.layoutIfNeeded()
    }
    
    private func _layoutButton() {
        // layout button at the center of the screen
        let cs1 = NSLayoutConstraint(item: self.showGreetingButton, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1.0, constant: 1.0)
        let cs2 = NSLayoutConstraint(item: self.showGreetingButton, attribute: .centerY, relatedBy: .equal, toItem: self.view, attribute: .centerY, multiplier: 1.0, constant: 1.0)
        
        self.view.addConstraints([cs1, cs2])
    }
    
    private func _layoutLabel() {
        // layout label at the center, bottom of the screen
        let cs1 = NSLayoutConstraint(item: self.greetingLabel, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1.0, constant: 1.0)
        let cs2 = NSLayoutConstraint(item: self.greetingLabel, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1.0, constant: -10)
        let cs3 = NSLayoutConstraint(item: self.greetingLabel, attribute: .width, relatedBy: .equal, toItem: self.view, attribute: .width, multiplier: 0.70, constant: 0)
        
        self.view.addConstraints([cs1, cs2, cs3])
    }
    
    @objc func didTapButton(sender: UIButton) {
        self.greetingLabel.text = "Hello " + self.person.firstName + " " + self.person.lastName
    }
}

let model = Person(firstName: "Wasin", lastName: "Thonkaew")
let vc = GreetingViewController()
vc.person = model

PlaygroundPage.current.liveView = vc.view

MVC assembling can be performed in the presenting view controller.

This doesn’t seem very testable, right? We can move generation of greeting into the new GreetingModel class and test it separately, but we can’t test any presentation logic (although there is not much of such logic in the example above) inside the GreetingViewController without calling the UIView related methods directly (viewDidLoad, didTapButton) which might cause loading all views, and this is bad for the unit testing.

In fact, loading and testing UIViews on one simulator doesn’t guarantee that it would work fine on the other devices (e.g. iPad), so we’d recommend removing “Host Application” from our Unit Test target configuration and run our tests without our application running on simulator.

The interactions between the View and the Controller aren’t really testable with Unit Tests.

With all that said, it might seems that Cocoa MVC is a pretty bad pattern to choose. But let’s assess it in terms of features defined in the beginning of the article:

  • Distribution —the View and the Model in fact separated, but it tightly couples the View and the Controller.
  • Testability — because of the bad distribution, we’ll probably only test our Model.
  • Ease of use — the least amount of code among other patterns. In addition, everyone is familiar with it, thus, it’s easily maintained even by the unexperienced developers.

Cocoa MVC is the pattern of our choice if we are not ready to invest more time in our architecture, and we feel that something with higher maintenance cost is an overkill for our tiny pet project.

Cocoa MVC is the best architectural pattern in terms of the speed of the development.


3. MVP

MVP (Model View Presenter) is a further development of the MVC pattern. The Controller is replaced by the Presenter. Presenter, unlike Controller in the classic MVC:

  • holds the state of the View.
  • changes the state of the View.
  • handles events of the View.
  • transforms a Domain Model into a ViewModel.

Otherwise, Presenter is like the Controller from the classic MVC:

  • owns the Model.
  • changes the state of the Model (through calling appropriate methods) in response to external stimuli.
  • may contain Application Logic.


MVP – Cocoa MVC’s promises delivered (Passive View Variant)

This diagram doesn’t it look exactly like the Apple’s MVC? Yes, it does, and its name is MVP (Passive View variant). Here, the MVP’s mediator (Presenter) has nothing to do with the life cycle of the view controller, and the View can be mocked easily, so there is no layout code in the Presenter at all, but it updates the View with data and state. 

In terms of the MVP, the UIViewController subclasses are in fact the Views and not the Presenters. This distinction provides superb testability, which comes at a cost of the development speed, because we have to make manual data and event binding, as we can see from the example:

/**
 * MVP iOS Design Pattern
 *
 */

import UIKit
import PlaygroundSupport

struct Person { // Model
    let firstName: String
    let lastName: String
}

protocol GreetingView: class {
    func setGreeting(greeting: String)
}

protocol GreetingViewPresenter {
    init(view: GreetingView, person: Person)
    func showGreeting()
}

class GreetingPresenter : GreetingViewPresenter {
    weak var view: GreetingView?
    let person: Person
    
    required init(view: GreetingView, person: Person) {
        self.view = view
        self.person = person
    }
    
    func showGreeting() {
        let greeting = "Hello " + self.person.firstName + " " + self.person.lastName
        self.view?.setGreeting(greeting: greeting)
    }
}

class GreetingViewController : UIViewController, GreetingView {
    var presenter: GreetingViewPresenter!
    var showGreetingButton: UIButton!
    var greetingLabel: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)
        
        self.setupUIElements()
        self.layout()
    }
    
    func setGreeting(greeting: String) {
        self.greetingLabel.text = greeting
    }
    
    func setupUIElements() {
        self.title = "Test"
        
        self._setupButton()
        self._setupLabel()
    }
    
    private func _setupButton() {
        self.showGreetingButton = UIButton()
        self.showGreetingButton.setTitle("Click me", for: .normal)
        self.showGreetingButton.setTitle("You badass", for: .highlighted)
        self.showGreetingButton.setTitleColor(UIColor.white, for: .normal)
        self.showGreetingButton.setTitleColor(UIColor.red, for: .highlighted)
        self.showGreetingButton.translatesAutoresizingMaskIntoConstraints = false
        self.showGreetingButton.addTarget(self, action: #selector(didTapButton(sender:)), for: .touchUpInside)
        self.view.addSubview(self.showGreetingButton)
    }
    
    private func _setupLabel() {
        self.greetingLabel = UILabel()
        self.greetingLabel.textColor = UIColor.white
        self.greetingLabel.textAlignment = .center
        self.greetingLabel.translatesAutoresizingMaskIntoConstraints = false
        
        self.view.addSubview(self.greetingLabel)
    }
    
    func layout() {
        self._layoutButton()
        self._layoutLabel()
        
        self.view.layoutIfNeeded()
    }
    
    private func _layoutButton() {
        // layout button at the center of the screen
        let cs1 = NSLayoutConstraint(item: self.showGreetingButton, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1.0, constant: 1.0)
        let cs2 = NSLayoutConstraint(item: self.showGreetingButton, attribute: .centerY, relatedBy: .equal, toItem: self.view, attribute: .centerY, multiplier: 1.0, constant: 1.0)
        
        self.view.addConstraints([cs1, cs2])
    }
    
    private func _layoutLabel() {
        // layout label at the center, bottom of the screen
        let cs1 = NSLayoutConstraint(item: self.greetingLabel, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1.0, constant: 1.0)
        let cs2 = NSLayoutConstraint(item: self.greetingLabel, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1.0, constant: -10)
        let cs3 = NSLayoutConstraint(item: self.greetingLabel, attribute: .width, relatedBy: .equal, toItem: self.view, attribute: .width, multiplier: 0.70, constant: 0)
        
        self.view.addConstraints([cs1, cs2, cs3])
    }
    
    @objc func didTapButton(sender: UIButton) {
        self.presenter.showGreeting()
    }
}

// Assembling of MVP
// Note: Very important that these following lines will be within View when actually creating normal XCode project and follow design here.
let model = Person(firstName: "Wasin", lastName: "Thonkaew")
let view = GreetingViewController()
let presenter = GreetingPresenter(view: view, person: model)
view.presenter = presenter

PlaygroundPage.current.liveView = view.view

The MVP is the first pattern that reveals the assembly problem, which happens because of having three separate layers. Since we don’t want the View to know about the Model, it is not right to perform assembly in presenting view controller (which is the View), thus we have to do it somewhere else. For example, we can make the app-wide Router service, which will perform assembly and the View-to-View presentation. This issue arises and has to be addressed not only in the MVP but also in all the following patterns.

Let’s look on the features of the MVP:

  • Distribution — we have the most of the responsibilities divided between the Presenter and the Model, with the pretty dumb View (in the example above the Model is dumb as well).
  • Testability — is excellent, we can test most of the business logic because of the dumb View.
  • Easy of use — in our unrealistically simple example, the amount of code is doubled compared to the MVC, but, idea of the MVP is very clear.

MVP in iOS means superb testability and a lot of code.


MVP – With Bindings and Hooters (Supervising Presenter Variant)

There is the other flavour of the MVP — the Supervising Controller MVP. This variant includes direct binding of the View and the Model while the Presenter (The Supervising Controller) still handles actions from the View and is capable of changing the View.

But as we have already learned before, vague responsibility separation is bad, and tight coupling of the View and the Model. That is like how things work in Cocoa desktop development.

Same as with the traditional MVC, we don’t see a point in writing an example for the flawed architecture.


4. MVVM

Despite all the advantages of MVP, with the IDE development and frameworks, it didn’t fit in the automated application development, because it required “manual” work. The next pattern should solve these problems. MVVM (Model View ViewModel) was developed by engineers from Microsoft Ken Cooper and Ted Peters and announced by John Gossman in his blog in 2005.

The purpose of the pattern is separation between the user interface from development and business logic development, and facilitating the application testing using the main features of WPF and Silverlight platforms. Although the pattern of specialization was conceived for Microsoft technology, it can be used in Cocoa / CocoaTouch framework.

In theory, the Model-View-ViewModel looks very good. The View and the Model are already familiar to us, but also the Mediator, represented as the View Model.

It is pretty similar to the MVP:

  • The MVVM treats the view controller as the View
  • There is no tight coupling between the View and the Model

In addition, it does binding like the Supervising version of the MVP; however, this time not between the View and the Model, but between the View and the View Model.

So what is the View Model in the iOS reality? It is basically UIKit independent representation of our View and its state. The View Model invokes changes in the Model and updates itself with the updated Model, and since we have a binding between the View and the View Model, the first is updated accordingly.


Bindings

Bindings come out of a box for the OS X development, but we don’t have them in the iOS toolbox. Of course we have the KVO and notifications, but they aren’t as convenient as bindings.

So, provided we don’t want to write them ourselves, we have two options:

  • One of the KVO based binding libraries like the RZDataBinding or the SwiftBond
  • The full scale functional reactive programming beasts like ReactiveCocoaRxSwift or PromiseKit.

In fact, nowadays, if we hear “MVVM” — we think ReactiveCocoa, and vice versa. Although it is possible to build the MVVM with the simple bindings, ReactiveCocoa (or siblings) will allow us to get most of the MVVM.

There is one bitter truth about reactive frameworks: the great power comes with the great responsibility. It’s really easy to mess up things when we go reactive. In other words, if we do something wrong, we might spend a lot of time debugging the app, so just take a look at this call stack.

In our simple example, the FRF framework or even the KVO is an overkill, instead we’ll explicitly ask the View Model to update using showGreeting method and use the simple property for greetingDidChange callback function.

/*** MVVM iOS Design Pattern**/ import UIKitimport PlaygroundSupportstruct Person { let firstName: String let lastName: String} protocol GreetingViewModelProtocol: class {var greeting: String? { get }var greetingDidChange: ((GreetingViewModelProtocol) -> ())? { get set }init(person: Person)func showGreeting()}class GreetingViewModel : GreetingViewModelProtocol {let person: Personvar greeting: String? {didSet {self.greetingDidChange?(self)}}var greetingDidChange: ((GreetingViewModelProtocol) -> ())?required init(person: Person) {self.person = person}func showGreeting() {self.greeting = "Hello " + self.person.firstName + " " + self.person.lastName}}class GreetingViewController : UIViewController {var viewModel: GreetingViewModelProtocol? {didSet {self.viewModel?.greetingDidChange = { [unowned self] viewModel inself.greetingLabel.text = viewModel.greeting}}}var showGreetingButton: UIButton!var greetingLabel: UILabel!override func viewDidLoad() {super.viewDidLoad()self.view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)self.setupUIElements()self.layout()}func setupUIElements() {self.title = "Test"self._setupButton()self._setupLabel()}private func _setupButton() {self.showGreetingButton = UIButton()self.showGreetingButton.setTitle("Click me", for: .normal)self.showGreetingButton.setTitle("You badass", for: .highlighted)self.showGreetingButton.setTitleColor(UIColor.white, for: .normal)self.showGreetingButton.setTitleColor(UIColor.red, for: .highlighted)self.showGreetingButton.translatesAutoresizingMaskIntoConstraints = falseself.showGreetingButton.addTarget(self, action: #selector(didTapButton(sender:)), for: .touchUpInside)self.view.addSubview(self.showGreetingButton)}private func _setupLabel() {self.greetingLabel = UILabel()self.greetingLabel.textColor = UIColor.whiteself.greetingLabel.textAlignment = .centerself.greetingLabel.translatesAutoresizingMaskIntoConstraints = falseself.view.addSubview(self.greetingLabel)}func layout() {self._layoutButton()self._layoutLabel()self.view.layoutIfNeeded()}private func _layoutButton() { let cs1 = NSLayoutConstraint(item: self.showGreetingButton, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1.0, constant: 1.0)let cs2 = NSLayoutConstraint(item: self.showGreetingButton, attribute: .centerY, relatedBy: .equal, toItem: self.view, attribute: .centerY, multiplier: 1.0, constant: 1.0)self.view.addConstraints([cs1, cs2])}private func _layoutLabel() { let cs1 = NSLayoutConstraint(item: self.greetingLabel, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1.0, constant: 1.0)let cs2 = NSLayoutConstraint(item: self.greetingLabel, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1.0, constant: -10)let cs3 = NSLayoutConstraint(item: self.greetingLabel, attribute: .width, relatedBy: .equal, toItem: self.view, attribute: .width, multiplier: 0.70, constant: 0)self.view.addConstraints([cs1, cs2, cs3])}@objc func didTapButton(sender: UIButton) {guard let vm = self.viewModel else { return }vm.showGreeting()}} let model = Person(firstName: "Wasin", lastName: "Thonkaew")let view = GreetingViewController()let viewModel = GreetingViewModel(person: model)view.viewModel = viewModelPlaygroundPage.current.liveView = view.view 

And again back to our feature assessment:

  • Distribution — it is not clear in our tiny example, but, in fact, the MVVM’s View has more responsibilities than the MVP’s View. Because the first one updates its state from the View Model by setting up bindings, when the second one just forwards all events to the Presenter and doesn’t update itself.
  • Testability — the View Model knows nothing about the View, this allows us to test it easily. The View might be also tested, but since it is UIKit dependant we might want to skip it.
  • Easy of use — its has the same amount of code as the MVP in our example, but in the real app where we’d have to forward all events from the View to the Presenter and to update the View manually, MVVM would be much skinnier if we used bindings.

The MVVM is very attractive, since it combines benefits of the aforementioned approaches, and, in addition, it doesn’t require extra code for the View updates because of the bindings on the View side. Nevertheless, testability is still on a good level.


5. VIPER

The examined above architectural patterns have one disadvantage. If we try to divide the architecture into layers, it is likely we will have difficulty with the Presenter or with the View Model. Which layer do they belong to? This question has no simple answer: we can introduce a separate Presentation layer for the Presenter, or it can belong to the Application Logic. The same with MVVM. This ambiguity creates another problem.

It is very difficult to separate the Application Logic from the Domain Model Logic. So often there’s no separation and are in the same layer. Besides, the presence of an Application Logic in a Presenter sometimes makes it difficult to test different Use Cases. Another problem in previous architectures is assembly and navigation. In large projects for several dozens of scenes, this is a responsibility of a separate module Router.

In 2012  a remarkable article was published. The Clean Architecture and several speeches on the subject. Later, in the Mutual Mobile, we’ve adapted a little for iOS, and a new pattern VIPER enters. It is the acronym of View, Interactor, Presenter, Entity, Router–basic components that make up the application. See how they interact below. This gives the LEGO building experience transferred into the iOS app design.

By now, we agree that the granularity in responsibilities is very good. VIPER makes another iteration on the idea of separating responsibilities, and this time we have five layers.

  • View — As with MVP (Passive View), it is a visualization of the data that comes from the Presenter. The View communicates with the Presenter through a protocol at a higher level than the level of UI classes. The Presenter is not aware of specific classes that make up a hierarchy of the View. To share data between the View and the Presenter, it is convenient to use separate structures (i.e. classes that have no methods that could change its state). Only the View and the Presenter know about these classes.
  • Interactor — This layer contains business logic related to the data (Entities) or networking, like creating new instances of entities or fetching them from the server. For those purposes we’ll use some Services and Managers which are not considered as a part of VIPER module but an external dependency.
  • Presenter — This layer contains the UI related (but UIKit independent) business logic, invokes methods on the Interactor.
  • Entities — Our plain data objects, not the data access layer, because that is a responsibility of the Interactor.
  • Router — This layer is responsible for the segues between the VIPER modules. Wireframe and Presenter have the responsibilities for the navigation in VIPER.

Basically, VIPER module can be a one screen or the whole user story of our application — think of authentication, which can be one screen or several related ones. How small are our “LEGO” blocks supposed to be? — It’s up to us.

If we compare it with the other patterns, we’ll see a few differences of the distribution of responsibilities:

  • Model (data interaction) logic shifted into the Interactor with the Entities as dumb data structures.
  • Only the UI representation duties of the Controller/Presenter/ViewModel moved into the Presenter, but not the data altering capabilities.
  • VIPER is the first pattern which explicitly addresses navigation responsibility, which is supposed to be resolved by the Router.

Proper way of doing routing is a challenge for the iOS applications, the other patterns (MVC, MVP, MVVM) simply don’t address this issue.

The example doesn’t cover routing or interaction between modules, as those topics are not covered by the other patterns at all.

/*** VIPER iOS Design Pattern**/import UIKitimport PlaygroundSupportstruct Person { let firstName: Stringlet lastName: String}struct GreetingData {  let greeting: Stringlet subject: String}protocol GreetingProvider {func provideGreetingData()}protocol GreetingOutput: class {func receiveGreetingData(greetingData: GreetingData)}class GreetingInteractor: GreetingProvider {weak var output: GreetingOutput!func provideGreetingData() {let person = Person(firstName: "Wasin", lastName: "Thonkaew")let subject = person.firstName + " " + person.lastNamelet greeting = GreetingData(greeting: "Hello", subject: subject)self.output.receiveGreetingData(greetingData: greeting)}}protocol GreetingViewEventHandler {func didTapShowGreetingButton()}protocol GreetingView: class {func setGreeting(greeting: String)}class GreetingPresenter: GreetingOutput, GreetingViewEventHandler {weak var view: GreetingView!var greetingProvider: GreetingProvider!func didTapShowGreetingButton() {self.greetingProvider.provideGreetingData()}func receiveGreetingData(greetingData: GreetingData) {let greeting = greetingData.greeting + " " + greetingData.subjectself.view.setGreeting(greeting: greeting)}}class GreetingViewController : UIViewController, GreetingView {var eventHandler: GreetingViewEventHandler!var showGreetingButton: UIButton!var greetingLabel: UILabel!override func viewDidLoad() {super.viewDidLoad()self.view.frame = CGRect(x: 0, y: 0, width: 320, height: 480)self.setupUIElements()self.layout()}func setGreeting(greeting: String) {self.greetingLabel.text = greeting}func setupUIElements() {self.title = "Test"self._setupButton()self._setupLabel()}private func _setupButton() {self.showGreetingButton = UIButton()self.showGreetingButton.setTitle("Click me", for: .normal)self.showGreetingButton.setTitle("You badass", for: .highlighted)self.showGreetingButton.setTitleColor(UIColor.white, for: .normal)self.showGreetingButton.setTitleColor(UIColor.red, for: .highlighted)self.showGreetingButton.translatesAutoresizingMaskIntoConstraints = falseself.showGreetingButton.addTarget(self, action: #selector(didTapButton(sender:)), for: .touchUpInside)self.view.addSubview(self.showGreetingButton)}private func _setupLabel() {self.greetingLabel = UILabel()self.greetingLabel.textColor = UIColor.whiteself.greetingLabel.textAlignment = .centerself.greetingLabel.translatesAutoresizingMaskIntoConstraints = falseself.view.addSubview(self.greetingLabel)}func layout() {self._layoutButton()self._layoutLabel()self.view.layoutIfNeeded()}private func _layoutButton() { let cs1 = NSLayoutConstraint(item: self.showGreetingButton, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1.0, constant: 1.0)let cs2 = NSLayoutConstraint(item: self.showGreetingButton, attribute: .centerY, relatedBy: .equal, toItem: self.view, attribute: .centerY, multiplier: 1.0, constant: 1.0)self.view.addConstraints([cs1, cs2])}private func _layoutLabel() { let cs1 = NSLayoutConstraint(item: self.greetingLabel, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1.0, constant: 1.0)let cs2 = NSLayoutConstraint(item: self.greetingLabel, attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottom, multiplier: 1.0, constant: -10)let cs3 = NSLayoutConstraint(item: self.greetingLabel, attribute: .width, relatedBy: .equal, toItem: self.view, attribute: .width, multiplier: 0.70, constant: 0)self.view.addConstraints([cs1, cs2, cs3])}@objc func didTapButton(sender: UIButton) {self.eventHandler.didTapShowGreetingButton()}}let view = GreetingViewController()let presenter = GreetingPresenter()let interactor = GreetingInteractor()view.eventHandler = presenterpresenter.view = viewpresenter.greetingProvider = interactorinteractor.output = presenterPlaygroundPage.current.liveView = view.view

Yet again, we back to the features:

  • Distribution — undoubtedly, VIPER is a champion in distribution of responsibilities.
  • Testability — no surprises here, better distribution — better testability.
  • Easy of use — finally, two above come in cost of maintainability as we already guessed. We have to write a huge amount of interface for classes with very small responsibilities.


So what about LEGO?

While using VIPER, we might feel like building The Empire State Building from LEGO blocks, and that is a signal that we have a problem. Maybe, it’s too early to adopt VIPER for our application and we should consider something simpler. Some people ignore this and continue shooting out of cannon into sparrows. We assume they believe that their apps will benefit from VIPER at least in the future, even if now the maintenance cost is unreasonably high. If we believe the same, then we’d recommend trying Generamba — a tool for generating VIPER skeletons.

That’s all about in this article.


Conclusion

In this article, we understood Why Are Architecture Patterns important in iOS. This article reviewed some popular ones and compare them in theory and practice going over a few tiny examples.

Thanks for reading! I hope you enjoyed and learned about Architecture patterns importance in iOS Application. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING!!???

iOS – How To Respond To The Application Launch In iOS ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (How To Respond To The Application Launch In iOS ?).

In this article, We will learn how to respond to the application launch in iOS. We will discuss about initialize our app’s data structures, prepare our app to run, and respond to any launch-time requests from the system in iOS. We also describe why the app launched in iOS.

A famous quote about learning is :

” Research shows that you begin learning in the womb and go right on learning until the moment you pass on. Your brain has a capacity for learning that is virtually limitless, which makes every human a potential genius. “

So Let’s begin.


Overview

The system launches our app when the user taps our app’s icon on the Home screen. If our app requested specific events, the system might also launch our app in the background to handle those events. For a scene-based app, the system similarly launches the app when one of our scenes needs to appear onscreen or do some work.

All apps have an associated process, which the UIApplication object represents. Apps also have an app delegate object—an object that conforms to the UIApplicationDelegate protocol—which responds to important events happening within that process. Even a scene-based app uses an app delegate to manage fundamental events like launch and termination. At launch time, UIKit automatically creates the UIApplication object and our app delegate. It then starts our app’s main event loop.


Provide a Launch Storyboard

When the user first launches the app on a device, the system displays the launch storyboard until the app is ready to display its UI. Displaying the launch storyboard assures the user that our app launched and is doing something. If our app initializes itself and readies its UI quickly, the user may see the launch storyboard only briefly.

Xcode projects automatically include a default launch storyboard for us to customize, and we can add more launch storyboards as necessary. To add new launch storyboards to our project, do the following:

  1. Open your project in Xcode.
  2. Choose File > New > File.
  3. Add a Launch Screen resource to our project.

Add views to our launch storyboard and use Auto Layout constraints to size and position them so that they adapt to the underlying environment. UIKit displays exactly what we provide, using our constraints to fit our views into the available space. We can use  Human Interface Guidelines for for design guidance.

In iOS 13 and later, always provide a launch storyboard for your app. Don’t use static launch images.


Initialize App’s Data Structures

We put our app’s launch-time initialization code in one or both of the following methods:

  • application(_:willFinishLaunchingWithOptions:)
  • application(_:didFinishLaunchingWithOptions:)

UIKit calls these methods at the beginning of our app’s launch cycle. We use them to:

  • Initialize our app’s data structures.
  • Verify that our app has the resources it needs to run.
  • Perform any one-time setup when our app launches for the first time. For example, install templates or user-modifiable files in a writable directory.
  • Connect to any critical services that our app uses. For example, connect to the Apple Push Notification service if our app supports remote notifications.
  • Check the launch options dictionary for information about why our app launched.

For apps that aren’t scene-based, UIKit loads our default user interface automatically at launch time. Use the application(_:didFinishLaunchingWithOptions:) method to make additional changes to that interface before it appears onscreen. For example, we might install a different view controller to reflect what the user was doing the last time they used the app.


Move Long-Running Tasks off the Main Thread

When the user launches the app, make a good impression by launching quickly. UIKit doesn’t present the app’s interface until after the application(_:didFinishLaunchingWithOptions:) method returns. Performing long-running tasks in that method or the application(_:willFinishLaunchingWithOptions:) method might make the app appear sluggish to the user. Returning quickly is also important when launching to the background because the system limits the app’s background execution time.

Move tasks that are not critical to the app’s initialization out of the launch-time sequence. For example:

  • Defer the initialization of features that the app doesn’t need immediately.
  • Move important, long-running tasks off the app’s main thread. For example, run them asynchronously on a global dispatch queue.


Determine Why App Launched

When UIKit launches the app, it passes along a launch options dictionary to the application(_:willFinishLaunchingWithOptions:) and application(_:didFinishLaunchingWithOptions:) methods with information about why the app launched. The keys in that dictionary indicate important tasks to perform immediately. For example, they might reflect actions that the user started elsewhere and wants to continue in the app. Always check the contents of the launch options dictionary for keys that we expect, and respond appropriately to their presence.

For a scene-based app, examine the options that UIKit passes to the application(_:configurationForConnecting:options:) method to determine why it created the scene.

The example shows the app delegate method for an app that handles background location updates. When the location key is present, the app starts location updates immediately instead of deferring them until later. Starting location updates allows the Core Location framework to deliver the new location event.

class AppDelegate: UIResponder, UIApplicationDelegate, 
               CLLocationManagerDelegate {
    
   let locationManager = CLLocationManager()
   func application(_ application: UIApplication,
              didFinishLaunchingWithOptions launchOptions:
              [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
       
      // If launched because of new location data,
      //  start the visits service right away.
      if let keys = launchOptions?.keys {
         if keys.contains(.location) {
            locationManager.delegate = self
            locationManager.startMonitoringVisits()
         }
      }
       
      return true
   }
   // other methods…
}

The system doesn’t include a key unless our app supports the corresponding feature. For example, the system doesn’t include the remoteNotification key for an app that doesn’t support remote notifications.

That’s all about in this article.


Conclusion

In this article, We understood how to respond to the application launch in iOS. This article described about initialize our app’s data structures, prepare our app to run, and respond to any launch-time requests from the system in iOS.

Thanks for reading ! I hope you enjoyed and learned about the Application Launch Concepts in iOS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING!!???

iOS – How To Prepare UI To Run In The Background In iOS ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (How To Prepare UI To Run In The Background In iOS ?).

In this article, we will learn about how to prepare UI to run in the background in iOS. We will discuss how to prepare our app to be suspended.

A famous quote about Learning is :

” You don’t understand anything until you learn it more than one way. “

So Let’s begin.


Overview

Apps move to the background state for many reasons. When the user exits a foreground app, that app moves to the background state briefly before UIKit suspends it. The system may also launch an app directly into the background state, or move a suspended app into the background, and give it time to perform important tasks.

When our app is in the background in iOS, it should do as little as possible, and preferably nothing. If our app was previously in the foreground, use the background transition to stop tasks and release any shared resources. If our app enters the background to process an important event, process the event and exit as quickly as possible.

All state transitions result in UIKit sending notifications to the appropriate delegate object:

  • In iOS 13 and later—A UISceneDelegate object.
  • In iOS 12 and earlier—The UIApplicationDelegate object.

We can support both types of delegate objects, but UIKit always uses scene delegate objects when they are available. UIKit notifies only the scene delegate associated with the specific scene that is entering the background.


Quiet App upon Deactivation

The system deactivates apps for several reasons. When the user exits the foreground app, the system deactivates that app immediately before moving it to the background. The system also deactivates apps when it needs to interrupt them temporarily—for example, to display system alerts. In the case of a system panel, the system reactivates the app when the user dismisses the panel.

During deactivation, UIKit calls one of the following methods of our app:

  • For apps that support scenes—The sceneWillResignActive(_:) method of the appropriate scene delegate object.
  • For all other apps—The applicationWillResignActive(_:) method of the app delegate object.

Use deactivation to preserve the user’s data and put our app in a quiet state by pausing all major work; specifically:

  • Save user data to disk and close any open files.
  • Suspend dispatch and operation queues.
  • Don’t schedule any new tasks for execution.
  • Invalidate any active timers.
  • Pause gameplay automatically.
  • Don’t commit any new Metal work to be processed.
  • Don’t commit any new OpenGL commands.


Release Resources upon Entering the Background

When our app transitions to the background, release memory and free up any shared resources our app is holding. For an app transitioning from the foreground to the background, freeing up memory is especially important. The foreground has priority over memory and other system resources, and the system terminates background apps as needed to make those resources available. Even if our app wasn’t in the foreground, perform checks to ensure that it consumes as few resources as possible.

Upon entering the background, UIKit calls one of the following methods of our app:

  • For apps that support scenes—The sceneDidEnterBackground(_:) method of the appropriate scene delegate object.
  • For all other apps—The applicationDidEnterBackground(_:) method of the app delegate object.

During a background transition, perform as many of the following tasks as makes sense for our app:

  • Discard any images or media that we read directly from files.
  • Discard any large, in-memory objects that we can recreate or reload from disk.
  • Release access to the camera and other shared hardware resources.
  • Hide sensitive information (such as passwords) in our app’s user interface.
  • Dismiss alerts and other temporary interfaces.
  • Close connections to any shared system databases.
  • Unregister from Bonjour services and close any listening sockets associated with them.
  • Ensure that all Metal command buffers have been scheduled.
  • Ensure that all OpenGL commands, we previously submitted have finished.

We don’t need to discard named images that we loaded from our app’s asset catalog. Similarly, we don’t need to release objects that adopt the NSDiscardableContent protocol or that we manage using an NSCache object. The system automatically handles the cleanup of those objects.

Make sure our app is not holding any shared system resources when it transitions to the background. If it continues accessing resources like the camera or a shared system database after transitioning to the background, the system terminates our app to free up that resource. If we use a system framework to access a resource, check the framework’s documentation for guidelines about what to do.


Prepare UI for the App Snapshot

After our app enters the background and our delegate method returns, UIKit takes a snapshot of our app’s current user interface. The system displays the resulting image in the app switcher. It also displays the image temporarily when bringing our app back to the foreground.

Our app’s UI must not contain any sensitive user information, such as passwords or credit card numbers. If our interface contains such information, remove it from our views when entering the background. Also, dismiss alerts, temporary interfaces, and system view controllers that obscure our app’s content. The snapshot represents our app’s interface and should be recognizable to users. When our app returns to the foreground, we can restore data and views as appropriate.

For apps that support state preservation and restoration, the system begins the preservation process shortly after our delegate method returns. Removing sensitive data also prevents that information from being saved in our app’s preservation archive.


Respond to Important Events in the Background

Apps don’t normally receive any extra execution time after they enter the background. However, UIKit does grant execution time to apps that support any of the following time-sensitive capabilities:

  • Audio communication using AirPlay, or Picture in Picture video.
  • Location-sensitive services for users.
  • Voice over IP.
  • Communication with an external accessory.
  • Communication with Bluetooth LE accessories, or conversion of the device into a Bluetooth LE accessory.
  • Regular updates from a server.
  • Support for Apple Push Notification service (APNs).

Enable the Background Modes capability in Xcode if our app supports background features.

That’s all about in this article.


Conclusion

In this article, We understood how to prepare UI to run in the Background in iOS. We also discussed how to prepare our app to be suspended.

Thanks for reading ! I hope you enjoyed and learned about UI Preparation concepts during Background in iOS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

iOS – How To Manage App’s Life Cycle In iOS ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (How To Manage App’s Life Cycle In iOS ?).

In this article, We will understand how to manage App’s Life Cycle in iOS. We will discuss how to respond to system notifications when our app is in the foreground or background, and handle other significant system-related events.

For Understanding the App’s Lifecycle concepts, We will discuss on the below topics:

  • Overview
  • Respond to The Scene-Based Life-Cycle Events
  • Responds to App-Based Life-Cycle Events
  • Respond to Other Significant Events

A famous quote about Learning is :

” One learns from books and example only that certain things can be done. Actual learning requires that you do those things. “

So Let’s begin.


Overview

The current state of our app determines what it can and cannot do at any time. For example, a foreground app has the user’s attention, so it has priority over system resources, including the CPU. By contrast, a background app must do as little work as possible, and preferably nothing, because it is offscreen. As our app changes from state to state, we must adjust its behavior accordingly.

When our app’s state changes, UIKit notifies us by calling methods of the appropriate delegate object:

  • In iOS 13 and later, use UISceneDelegate objects to respond to life-cycle events in a scene-based app.
  • In iOS 12 and earlier, use the UIApplicationDelegate object to respond to life-cycle events.

If we enable scene support in our app, iOS always uses our scene delegates in iOS 13 and later. In iOS 12 and earlier, the system uses our app delegate.


Respond to The Scene-Based Life-Cycle Events

If our app supports scenes, UIKit delivers separate life-cycle events for each. A scene represents one instance of our app’s UI running on a device. The user can create multiple scenes for each app, and show and hide them separately. Because each scene has its own life cycle, each can be in a different state of execution. For example, one scene might be in the foreground while others are in the background or are suspended.

Scene support is an opt-in feature. To enable basic support, add the UIApplicationSceneManifest key to our app’s Info.plist file.

The following figure shows the state transitions for scenes. When the user or system requests a new scene for our app, UIKit creates it and puts it in the unattached state. User-requested scenes move quickly to the foreground, where they appear onscreen. A system-requested scene typically moves to the background so that it can process an event. For example, the system might launch the scene in the background to process a location event. When the user dismisses our app’s UI, UIKit moves the associated scene to the background state and eventually to the suspended state. UIKit can disconnect a background or suspended scene at any time to reclaim its resources, returning that scene to the unattached state.

We use scene transitions to perform the following tasks:

  • When UIKit connects a scene to our app, configure our scene’s initial UI and load the data our scene needs.
  • When transitioning to the foreground-active state, configure our UI and prepare to interact with the user.
  • Upon leaving the foreground-active state, save data and quiet our app’s behavior.
  • Upon entering the background state, finish crucial tasks, free up as much memory as possible, and prepare for our app snapshot.
  • At scene disconnection, clean up any shared resources associated with the scene.
  • In addition to scene-related events, we must also respond to the launch of our app using our UIApplicationDelegate object.


Responds to App-Based Life-Cycle Events

In iOS 12 and earlier, and in apps that don’t support scenes, UIKit delivers all life-cycle events to the UIApplicationDelegate object. The app delegate manages all of your app’s windows, including those displayed on separate screens. As a result, app state transitions affect our app’s entire UI, including content on external displays.

App State Transitions

The following figure shows the state transitions involving the app delegate object. After launch, the system puts the app in the inactive or background state, depending on whether the UI is about to appear onscreen. When launching to the foreground, the system transitions the app to the active state automatically. After that, the state fluctuates between active and background until the app terminates.

We use app transitions to perform the following tasks:

  • At launch, initialize our app’s data structures and UI.
  • At activation, finish configuring our UI and prepare to interact with the user.
  • Upon deactivation, save data and quiet our app’s behavior.
  • Upon entering the background state, finish crucial tasks, free up as much memory as possible, and prepare for our app snapshot.
  • At termination, stop all work immediately and release any shared resources.


Respond to Other Significant Events

In addition to handling life-cycle events, apps must also be prepared to handle the events listed in the following below points. We can use our UIApplicationDelegate object to handle most of these events. In some cases, we may also be able to handle them using notifications, allowing us to respond from other parts of our app.

  • Memory warnings – Received when our app’s memory usage is too high. Reduce the amount of memory our app uses.
  • Protected data becomes available/unavailable – Received when the user locks or unlocks their device. We use applicationProtectedDataDidBecomeAvailable(_:) and applicationProtectedDataWillBecomeUnavailable(_:) methods to check protected data availability.
  • Handoff tasks – Received when an NSUserActivity object needs to be processed. We can use application(_:didUpdate:) method to handoff tasks.
  • Time changes – Received for several different time changes, such as when the phone carrier sends a time update. We can use applicationSignificantTimeChange(_:) method to see time changes.
  • Open URLs – Received when your app needs to open a resource. We can use application(_:open:options:) method to open URLs.

That’s all about in this article.


Conclusion

In this article, We understood how to manage App’s Life Cycle in iOS. We also discussed how to respond to system notifications when our app is in the foreground or background, and handle other significant system-related events in iOS.

Thanks for reading ! I hope you enjoyed and learned about App’s Lifecycle Management Concepts in iOS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

iOS – How To Select The Best Method Of Scheduling Background Runtime In iOS ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article (How To Select The Best Method Of Scheduling Background Runtime In iOS ?).

In this article, We will understand how to select the best method of scheduling background runtime for our app in iOS. Selecting the right strategies for our app in iOS depends on how it functions in the background.

A famous quote about Learning is :

” Change is the end result of all true learning. “


So Let’s begin.


Overview

If our app needs computing resources to complete tasks when it’s not running in the foreground, we can select from a number of strategies to obtain background runtime. Selecting the right strategies for our app depends on how it functions in the background.

Some apps perform work for a short time while in the foreground and must continue uninterrupted if they go to the background. Other apps defer that work to perform in the background at a later time or even at night while the device charges. And some apps need background processing time at varied and unpredictable times, such as when an external event or message arrives.


Different Methods Of Scheduling Background Runtime

In this section, we select one or more methods for our app based on how you schedule activity in the background.


1. Continue Foreground Work in the Background

The system may place apps in the background at any time. If our app performs critical work that must continue while it runs in the background, use beginBackgroundTask(withName:expirationHandler:) to alert the system. Consider this approach if our app needs to finish sending a message or complete saving a file.

The system grants our app a limited amount of time to perform its work once it enters the background. Don’t exceed this time, and use the expiration handler to cover the case where the time has depleted to cancel or defer the work.

Once our work completes, call endBackgroundTask(_:) before the time limit expires so that our app suspends properly. The system terminates our app if we fail to call this method.

If the task is one that takes some time, such as downloading or uploading files, use URLSession.


2. Defer Intensive Work

To preserve battery life and performance, we can schedule backgrounds tasks for periods of low activity, such as overnight when the device charges. Use this approach when our app manages heavy workloads, such as training machine learning models or performing database maintenance.

Schedule these types of background tasks using BGProcessingTask, and the system decides the best time to launch our background task.


3. Update Our App’s Content

Our app may require short bursts of background time to perform content refresh or other work; for example, our app may fetch content from the server periodically, or regularly update its internal state. In this situation, use BGAppRefreshTask by requesting BGAppRefreshTaskRequest.

The system decides the best time to launch our background task, and provides our app up to 30 seconds of background runtime. Complete our work within this time period and call setTaskCompleted(success:), or the system terminates our app. 


4. Wake Our App with a Background Push

Background pushes silently wake our app in the background. They don’t display an alert, play a sound, or badge our app’s icon. If our app obtains content from a server infrequently or at irregular intervals, use background pushes to notify our app when new content becomes available. A messaging app with a muted conversation might use a background push solution, and so might an email app that process incoming mail without alerting the user.

When sending a background push, set content-available: to 1 without alertsound, or badge. The system decides when to launch the app to download the content. To ensure our app launches, set apns-priority to 5, and apns-push-type to background.

Once the system delivers the remote notification with application(_:didReceiveRemoteNotification:fetchCompletionHandler:), our app has up to 30 seconds to complete its work. One our app performs the work, call the passed completion handler as soon as possible to conserve power. If we send background pushes more frequently than three times per hour, the system imposes rate limitations.


5. Request Background Time and Notify the User

If our app needs to perform a task in the background and show a notification to the user, use a Notification Service Extension. For example, an email app might need to notify a user after downloading a new email. Subclass UNNotificationServiceExtension and bundle the system extension with our app. Upon receiving a push notification, our service extension wakes up and obtains background runtime through didReceive(_:withContentHandler:).

When our extension completes its work, it must call the content handler with the content we want to deliver to the user. Our extension has a limited amount of time to modify the content and execute the contentHandler block.

That’s all about in this article.


Conclusion

In this article, We understood how to select the best method of scheduling background runtime in iOS.

Thanks for reading ! I hope you enjoyed and learned about selecting best method for scheduling background runtime concept in iOS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

You can find Other articles of CoolmonkTechie as below link :

You can also follow other website and tutorials of iOS as below links :

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

iOS – 3 Best Quick Ways To Handle Multithreading In iOS

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, We will learn about three best available options to handle multithreading in iOS. Production applications will often need to perform heavier operations such as downloading high-resolution images or a executing non-cached database queries. To prevent stalling the main thread (and a hit in frame rate), Apple has provided a few tools to help us. We will discuss below available options to handle multithreading:

  • Grand Central Dispatch
  • NSOperation and NSOperationQueue
  • performSelectorInBackground

A famous quote about Learning is :

” I am always ready to learn although I do not always like being taught. “


So Let’s begin.


1. Grand Central Dispatch

Grand Central Dispatch is a technology that abstracts away the low-level details of multithreading. When using GCD, we only have to think about the tasks we want to perform. These tasks can then be added to serial or concurrent queues. Moreover, we can add tasks to groups and run code after all tasks within the group complete.

Let’s walk through an example where we download an image from a remote URL and then use it to populate a UIImageView.

// Assume we have an `imageView` property on self
private func loadWallpaper() {
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) { [weak self] in
        guard
            let wallpaperURL = NSURL(string: "http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-157301.jpg"),
            let imageData = NSData(contentsOfURL: wallpaperURL)
        else {
            return
        }

        dispatch_async(dispatch_get_main_queue()) {
            self?.imageView.image = UIImage(data: imageData)
        }
    }
}

Most uses of GCD start with a call to dispatch_async, which takes in a queue to use and the block to execute. In our example, we’d like to execute the wallpaper download on a background queue, so we make use of the system-defined global queue with a background quality of service (QoS), DISPATCH_QUEUE_PRIORITY_BACKGROUND. The flag passed into dispatch_get_global_queue should always be 0.

Now we have the block of work to execute. We construct a NSURL via its fail-able String initializer and then fetch the data associated with that resource via NSData(contentsOfURL:). If the above step completes successfully (else we just return from the block), we now have our data at hand.

To update imageView‘s image property, we need to make sure we return to the main thread via dispatch_async(dispatch_get_main_queue()) { /* ... */ }Remember in iOS, all UI updates should be performed on the main thread. Inside the main thread block, we set the image using the NSData initializer on UIImage.

Now that we’ve seen a one-off block example, let’s dive into how we can accomplish groups of dependent tasks. Imagine we wanted to download multiple wallpapers and present an alert to the user when all of the images finish loading. Dispatch groups will be our best friends in these scenarios.

First, let’s refactor the loadWallpaper function from the previous example to accept a dispatch_group_t and a target URL.

private func loadWallpaper(group: dispatch_group_t, url: String) {
    dispatch_group_async(group, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0)) { [weak self] in
        defer {
            dispatch_group_leave(group)
        }

        guard
            let wallpaperURL = NSURL(string: url),
            let imageData = NSData(contentsOfURL: wallpaperURL)
        else {
            // In production scenarios, we would want error handing here
            return
        }

        // Use imageData in some manner, e.g. persisting to a cache, present in view hierarchy, etc.
        print("Image downloaded \(url)")
    }
}

The function has been modified slightly to accept a parameter group of type dispatch_group_t (we’ll go into how to create these groups in the next snippet) and a target URL. Additionally, our previous call to dispatch_async has been replaced with dispatch_group_async, signalling that the block should be associated with group. Lastly, after completing our work with the resulting imageData we must notify group that the block is complete via dispatch_group_leave.

To use loadWallpaper(_:url:) a call site could look like so:

private func fetchAllWallpapers() {
        let urls = [
            "http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-329991.jpg",
            "http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-329805.jpg",
            "http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-330201.jpg"
        ]

        let wallpaperGroup = dispatch_group_create()

        urls.forEach {
            dispatch_group_enter(wallpaperGroup)
            loadWallpaper(wallpaperGroup, url: $0)
        }

        dispatch_group_notify(wallpaperGroup, dispatch_get_main_queue()) { [weak self] in
            let alertController = UIAlertController(title: "Done!", message: "All images have downloaded", preferredStyle: .Alert)
            alertController.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil))

            self?.presentViewController(alertController, animated: true, completion: nil)
        }
    }

We start by creating a dispatch group, wallpaperGroup, using dispatch_group_create(). With the group in hand, we loop over all of the wallpaper URLs, first signalling to the group that we are about to start an operation by making a call to dispatch_group_enter(wallpaperGroup) (each group entry call must pair with a group leave call). We then proceed to call loadWallpaper(_:url:).

To run code after completion of the group, we specify a block in a dispatch_group_notify call. In our case, we’ll simply present a UIAlertController letting the user know that all of the downloads have finished.

While GCD can be extremely powerful, it can be a bit cumbersome to work with in practice. To help with this, we can use Swifty GCD wrapper .

protocol ExcutableQueue {
    var queue: dispatch_queue_t { get }
}

extension ExcutableQueue {
    func execute(closure: () -> Void) {
        dispatch_async(queue, closure)
    }
}

enum Queue: ExcutableQueue {
    case Main
    case UserInteractive
    case UserInitiated
    case Utility
    case Background

    var queue: dispatch_queue_t {
        switch self {
        case .Main:
            return dispatch_get_main_queue()
        case .UserInteractive:
            return dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0)
        case .UserInitiated:
            return dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)
        case .Utility:
            return dispatch_get_global_queue(QOS_CLASS_UTILITY, 0)
        case .Background:
            return dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)
        }
    }
}

enum SerialQueue: String, ExcutableQueue {
    case DownLoadImage = "myApp.SerialQueue.DownLoadImage"
    case UpLoadFile = "myApp.SerialQueue.UpLoadFile"

    var queue: dispatch_queue_t {
        return dispatch_queue_create(rawValue, DISPATCH_QUEUE_SERIAL)
    }
}

Using this wrapper, our example above could be rewritten as:

Queue.Background.execute {
    guard
        let url = NSURL(string: "http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-157301.jpg"),
        let data = NSData(contentsOfURL: url)
    else {
        return
    }

    Queue.Main.execute { [weak self] in
        self?.imageView.image = UIImage(data: data)
    }
}


2. NSOperation and  NSOperationQueue

NSOperations and NSOperationQueues provide you with a higher-level API, when compared to GCD. They were first introduced in iOS 4 and are actually implemented with GCD under the hood. Typically, we’ll want to use this API over GCD, unless you’re performing a simple unit of work on a specific queue. NSOperations provide us with powerful functionality such as cancellation and dependencies.

To start, we’ll port the wallpaper downloading example to use an NSBlockOperationNSBlockOperation is a simple wrapper on a block of work that can be added to a queue.

private func loadWallpaper(queue: NSOperationQueue, url: String) {
    guard let wallpaperURL = NSURL(string: url) else { return }

    let downloadOperation = NSBlockOperation {
        guard let imageData = NSData(contentsOfURL: wallpaperURL) else { return }

        NSOperationQueue.mainQueue().addOperationWithBlock { [weak self] in
            self?.imageView.image = UIImage(data: imageData)
        }
    }

    queue.addOperation(downloadOperation)
}

The initializer for NSBlockOperation simply takes a block to run. In our case, we’ll download the data from wallpaperURL and return to the main queue to set the image property on imageView. After initializing downloadOperation, we add it to queue.

When creating an NSOperationQueue, we have a few points of customization.

let queue = NSOperationQueue()
queue.maxConcurrentOperationCount = 1

// If you want to hold the queue, use the `suspended` property
queue.suspended = true

The maxConcurrentOperationCount property allows us to set a limit on how many operations may run concurrently in a given queue. Setting this to 1, implies our queue will be serial (queing order may not be preserved, as operations only run when their ready flag is set to true). If this property isn’t set, it defaults to NSOperationQueueDefaultMaxConcurrentOperationCount, which is dictated by system conditions.

By default, all operations that are ready (ready property is true) are run when added to a queue. We can halt all execution on a queue by setting the suspended property to true.

NSOperations become really powerful when we separate them out into operation subclasses. To demonstrate this, let’s make a wallpaper resizing operation. We’ll need to subclass a custom wrapper of NSOperation that has the proper KVO notifications in place.

class ResizeImageOperation: Operation {

    enum Error {
        case FileReadError
        case ResizeError
        case WriteError
    }

    let targetSize: CGSize
    let path: NSURL
    var error: Error?

    init(size: CGSize, path: NSURL) {
        self.targetSize = size
        self.path = path
    }

    override func execute() {
        // Need to signal KVO notifications for operation completion
        defer {
            finish()
        }

        guard let sourceImage = UIImage(contentsOfFile: path.absoluteString) else {
            error = Error.FileReadError
            return
        }

        let finalWidth: CGFloat, finalHeight: CGFloat
        let ratio = sourceImage.size.width / sourceImage.size.height

        // Scale aspect fit the image
        if sourceImage.size.width >= sourceImage.size.height {
            finalWidth = targetSize.width
            finalHeight = finalWidth / ratio
        } else {
            finalHeight = targetSize.height
            finalWidth = finalHeight * ratio
        }

        let imageSize = CGSize(width: finalWidth, height: finalHeight)
        UIGraphicsBeginImageContextWithOptions(imageSize, true, 0.0)
        defer { UIGraphicsEndImageContext() }

        let rect = CGRect(origin: .zero, size: imageSize)
        sourceImage.drawInRect(rect)

        guard
            let resizedImage = UIGraphicsGetImageFromCurrentImageContext(),
            let imageData = UIImageJPEGRepresentation(resizedImage, 1.0)
        else {
            error = Error.ResizeError
            return
        }

        guard imageData.writeToFile(path.absoluteString, atomically: true) else {
            error = Error.WriteError
            return
        }
    }
}
  • To help with error handling, we add a nested Error enum with a few cases.
  • ResizeImageOperation can be initialized with a target size and path to write,
  • The meat of the operation is placed in the execute method (overridden from Operation). We need to make sure to defer a call to finish(), so that the Operation superclass can signal the proper KVO notifications.
  • We then proceed with the resizing the image (scale aspect fit) and saving it to disk.

Now that we have a resizing operation in hand, let’s refactor our download operation a bit to work with it:

private func downloadWallpaper(url: NSURL, path: NSURL) -> NSOperation {
    return NSBlockOperation {
        guard
            let imageData = NSData(contentsOfURL: url),
            let image = UIImage(data: imageData)
        else { return }

        UIImageJPEGRepresentation(image, 1.0)?.writeToFile(path.absoluteString, atomically: true)
    }
}

We now return an NSOperation and have the operation write the image data to disk. Lastly, to make the download and resize operations dependent, we can use them like so:

// Assume self has `imageView` and `wallpaperQueue` properties

if
    let cacheDirectory = NSSearchPathForDirectoriesInDomains(.CachesDirectory, .UserDomainMask, true).first,
    let cacheDirectoryURL = NSURL(string: cacheDirectory)
{

    let targetURL = cacheDirectoryURL.URLByAppendingPathComponent("wallpaper.jpg")
    let downloadOperation = downloadWallpaper(NSURL(string: "http://wallpapers.wallhaven.cc/wallpapers/full/wallhaven-329991.jpg")!, path: targetURL)

    let resizeOperation = ResizeImageOperation(size: CGSize(width: imageView.bounds.size.width * 2, height: imageView.bounds.size.height * 2), path: targetURL)
    resizeOperation.addDependency(downloadOperation)

    resizeOperation.completionBlock = { [weak self, weak resizeOperation] in
        if let error = resizeOperation?.error {
            print(error)
            return
        }

        guard
            let path = resizeOperation?.path,
            let imageData = NSData(contentsOfFile: path.absoluteString)
        else {
            return
        }

        NSOperationQueue.mainQueue().addOperationWithBlock {
            self?.imageView.image = UIImage(data: imageData)
        }
    }

    wallpaperQueue.suspended = true
    wallpaperQueue.addOperation(downloadOperation)
    wallpaperQueue.addOperation(resizeOperation)
    wallpaperQueue.suspended = false
}
  • The key line to notice is resizeOperation.addDependency(downloadOperation). That’s how we express the resizing operation’s dependency on downloadOperation.
  • Moreover, in the completion block of resizeOperation, we check for errors and proceed with displaying the resized image.
  • Note: we make sure to suspend the queue first, then add the operations. This prevents the operations from beginning immediately upon addition.


3. PerformSelectorInBackground

To wrap up, let’s show a simple example of performSelectorInBackground. Assuming self has a method sleepAndPrint(_:), we can make the following call:

performSelectorInBackground("sleepAndPrint:", withObject: "supsup")

If our target selector had no argument, the selector would simply be "sleepAndPrint").

func sleepAndPrint(message: String) {
    NSThread.sleepForTimeInterval(1)
    print(message)
}

That’s all about in this article.


Conclusion

In this article, We understood about three best available options to handle multithreading in iOS. We’ve discussed about GCD, NSoperations, and NSObject‘s performSelectorInBackground method as means of performing work in a multithreaded fashion. If we have small units of work to perform, we’ll want to reach for GCD or performSelectorInBackground. On the other hand, if we have larger operations that may have dependencies, NSOperation should be our tool of choice.

Thanks for reading ! I hope you enjoyed and learned about three best available options to handle multithreading in iOS. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

iOS – How To Make Our iOS Applications More Secure ?

Hello Readers, CoolMonkTechie heartily welcomes you in this article.

In this article, We will learn about iOS App Security. Mobile applications are the center of most peoples’ technology usage. They deal with a lot of private and sensitive user data like your personal health information or banking information. Protecting this data as well as possible is heavily important and the topic of this article.

We’ll discuss concrete techniques for making our iOS apps more secure. Our best practices cover means for securely storing data as well as sending & receiving data over the network. We’ll see why it is so hard to get security right and how we can improve our app security by using services from Apple and other providers.

We will focus on three main topics related to iOS App Security:

  • Storing user data safely.
  • Secure data transportation.
  • How to use Apple’s new cryptographic APIs.

A famous quote about Security and Learning is :

” Learning how to live with insecurity is the only security. “


So Let’s begin.

Chances are that our app handles private data that we don’t want to end up in the wrong hands. Therefore, we need to make sure to store this data safely and make data transportation as secure as possible.


Best Practices for Storing User Data

If we are developing iOS apps lots of security features are already provided by the OS. All iOS devices with an A7 processor or later also have a coprocessor called the Secure Enclave. It powers iOS security features in a hardware-accelerated way.


Apple’s App Sandbox

All apps running on iOS run in a sandbox to make sure the app can only access data which is stored in the app’s unique home directory. If an app wants to access data outside of its home directory it needs to use services provided by iOS, like the ones available for accessing iCloud data or the photo album. Therefore, no other app can read or modify data from our app.

Apple’s App Sandbox is powered by UNIX’s user permissions and makes sure that apps get executed with a less privileged “mobile” user. Everything outside the app’s home directory is mounted read-only. All system files and resources are protected. The available APIs don’t allow apps to escalate privileges in order to modify other apps or iOS itself.

For performing specific privileged operations an app needs to declare special entitlements. These entitlements get signed together with the app and are not changeable. Examples of services that need special entitlements are HealthKit or audio input. Some entitlements are even restricted to be only used if Apple gives you access to them. This includes services like CarPlay. They are stronger protected because misusing them could have fatal consequences.

Next to entitlements giving us special rights, apps can make use of the iOS extensions system. The OS has many points to be used by app extensions. App extensions are single-purpose executables bundled with the app. They run in their own address space and get controlled by the OS.

Additionally, iOS has methods to prevent memory-related security bugs. Address space layout randomization (ASLR) randomizes the assigned memory regions for each app on every startup. This makes the exploitation of memory-corruption-bugs much less likely. Also, memory pages are marked as non-executable with ARM’s Execute Never (XN) feature to stop malicious code from being executed.


Data Protection API

All iOS versions since iOS 4 have a built-in security feature called Data Protection. It allows an app to encrypt and decrypt the files stored in their app directory. The encryption and decryption processes are automatic and hardware-accelerated. Data Protection is available for file and database APIs, including NSFileManager, CoreData, NSData, and SQLite.

The feature is enabled by default but can be configured on a per-file basis to increase security. Every file can be configured to use one of 4 available protection levels. By default, all files are encrypted until the first user authentication but it might make sense to increase the protection level for certain data.

The four available protection levels include:

  • No protection: The file is always accessible and not encrypted at all
  • Complete until first user authentication: This is enabled by default and decrypts the file after the user unlocks their device for the first time. Afterward, the file stays decrypted until the device gets rebooted. Locking the device doesn’t encrypt the data again.
  • Complete unless open: The file is encrypted until the app opens the file for the first time. The decryption stays alive even when the device gets locked by the user.
  • Complete: The file is only accessible when the device is unlocked.

We can specify the protection level when we create files like this:

try data.write(to: fileURL, options: .completeFileProtection)

But we are also able to change the protection level of existing files by setting the resource values:

try (fileURL as NSURL).setResourceValue( 
                  URLFileProtection.complete,
                  forKey: .fileProtectionKey)

It is important to understand which protection levels fits our needs. By default, we should use the highest protection level possible. However, if we need access to files in the background while the phone is locked we can’t use complete data encryption for them.


Keychain

The keychain is our secure place to store small chunks of data. It is a hardware-accelerated secure data storage that encrypts all of its contents. It is used by the system to store data like passwords and certificates but we as an app developer have also access to this data storage.

Our app or app group has its own space in the keychain and no other app has access to it. This way, we don’t need to store encryption keys in our app and can rely on the system to provide the highest level of security.

The keychain is the secure key-value storage replacement for NSUserDefaults. NSUserDefaults are not encrypted at all and should be avoided for sensitive data.

For every keychain item, we can define specific access policies for accessibility and authentication. We can require user presence (requesting Face ID or Touch ID unlock) or that the biometric ID enrolment didn’t change since the item was added to the keychain.

As an additional feature of the iOS Keychain, we can decide if we want to store the information in the local keychain which is only available on this specific device, or in the iCloud Keychain which gets synchronized across all Apple devices. This gives us the ability to share the information between our iPhone, iPad and Mac counterparts.

Even though the Keychain Services API should be used whenever possible, its interface is not exactly nice to use in Swift. If we plan to use such functionality more often in our codebase consider wrapping it with a nicer Swift API.

let query: [String: Any] = [
    kSecClass as String: kSecClassInternetPassword,
    kSecAttrAccount as String: account,
    kSecAttrServer as String: server,
    kSecValueData as String: password
]

let status = SecItemAdd(query as CFDictionary, nil)

This code snippet stores some credentials to the keychain. A lot of casting is necessary and in the end, we call SecItemAdd which synchronously stores the credentials and returns either a success or error status code.


Best Practices for Secure Data Transportation

Next to storing the user data safely, we should make sure that the communication between our app and its remote counterparts is secured. This prevents attackers from collecting private data by sniffing the network traffic or by running malicious servers.


HTTPs

Most network communication is done over the HTTP protocol between a client and a server. By default, HTTP connections are not encrypted. It is easily possible for attackers to sniff data from our local network or to perform man-in-the-middle attacks.

Since iOS 9, there is a new feature called App Transport Security (ATS). It improves the security of network communication in our apps. ATS blocks insecure connections by default. It requires all HTTP connections to be performed using HTTPS secured with TLS.

ATS can be configured in many ways to loosen up these restrictions. We can, therefore, allow insecure HTTP connections for specific domains or change the minimum TLS version used for HTTPS.

If our app contains an in-app browser we should use the NSAllowsArbitraryLoadsInWebContent configuration which allows our users to browse the web normally and still makes sure that all other network connections in our app use the highest security standards.


SSL Pinning

By default, HTTPS connections are verified by the system: it inspects the server certificate and checks if it’s valid for this domain. This should make sure the connected server is not malicious. However, there are still ways for attackers to perform more complex man-in-middle attacks.

The system certificate trust validation checks if the certificate was signed by a root certificate of a trusted certificate authority. To circumvent this security mechanism attackers would need to explicitly trust another malicious certificate in the user’s device settings or compromise a certificate authority. The attacker could then perform a man-in-the-middle attack to read all messages sent between client and server.

To prevent these kinds of attacks an app can perform additional trust validation of server certificates. This is called SSL or Certificate Pinning. We can implement SSL Pinning by including a list of valid certificates (or its public keys or its hashes) in our app bundle. The app can, therefore, check if the certificate used by the server is on this list and only then communicate with the server.

Implementing this validation from scratch should be avoided since implementation mistakes are very likely and lead to even more security vulnerabilities. We can recommend using an Open Source framework like TrustKit.

Introducing SSL Pinning, unfortunately, introduces the risk of bricking our app. Since we hardcode the trusted certificates, the app itself needs to be updated if a server certificate expires. To avoid such a situation, pin the future certificates in the client app before releasing new server certificates.


Push Notifications

To send push notifications to our users, we need to use Apple’s APNS services. If we want to use end-to-end encryption or if we just don’t want to give Apple the (theoretical) chance to read your messages you can use UNNotificationServiceExtension extensions to modify the messages on the client-side.

This allows us to send either encrypted messages to our clients or use placeholders for sensitive data. The messages will simply be used as a wakeup call for the app. The app can then decrypt the message or respectively for placeholder messages fetch the necessary information from the local device and replace the placeholders with the sensitive data. The clear text message will then be shown on the user’s lock screen without any sensitive information being sent to Apple’s servers.

In the following example, we can see how easily we can change our message content in our notification service extension.

class NotificationService: UNNotificationServiceExtension {

    override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
        guard let mutableContent = request.content.mutableCopy() as? UNMutableNotificationContent else {
            fatalError("Cannot convert notification content to mutable content")
        }

        mutableContent.title = decryptText(mutableContent.title)
        mutableContent.body = decryptText(mutableContent.body)

        contentHandler(mutableContent)
    }

    // ...

}


End-to-end encryption

End-to-end encryption is the “holy grail” for secure data transportation. It allows us to encrypt messages in a way that only the sender and receiver can decrypt them and neither Apple or our servers can read the cleartext data.

End-to-end encryption is not easy to implement and requires a lot of experience in cryptographic processes. If our team doesn’t have the experience it is very advisable to consult a third party expert helping with the implementation of the encryption mechanism.


CloudKit

If our app doesn’t need a server , we can use Apple’s CloudKit. CloudKit allows us to store data in iCloud containers while using our Apple ID as the login mechanism for our app. This way, we don’t need to implement all of these services on our own.

CloudKit was made with security in mind. As an app developer, we don’t have access to concrete user data and the communication is encrypted by default.

All the communication between our app and the server can be done using Apple’s client-side CloudKit framework. If we have an additional Android or Web app, we can still use CloudKit using its JavaScript and Web services.

To make this even better: CloudKit is completely free of charge to a certain amount. We can reach millions of users without fearing costs for traffic, data storage or requests.


Best Practices of Using Apple’s cryptographic APIs

The iOS SDK includes APIs to handle common cryptographic tasks for us. As we said above it is generally a good idea to rely on proven crypto implementations and not reimplement them ourself.


Apples CryptoKit

Apples CryptoKit is a new API that was introduced in iOS 13 and provides lower-level APIs to perform cryptographic operations or implement security protocols.

CryptoKit is based on top of more lower-level APIs. They were available before but introduced additional risk factors since developers often used them in a wrong way.

CryptoKit also allows us to use the SecureEnclave to get cryptographically safe functions that are performant and optimized for the device’s hardware.

If we want to support older iOS versions, we can use those lower-level APIs or use well known open-source third-party libraries like CryptoSwift.


Hashing data

Hash functions are functions that convert data of arbitrary size to fixed-size values. Good hash functions should minimize duplication of output values (so-called collisions) and be very fast to compute. Swift includes hashing functionality in the Swift Standard Library, but these functions are heavily focused on being fast and have a relative high collision rate. This makes them a good fit for performance-critical operations, but not so much for security related operations.

Securely hashing data is simple using CryptoKit. We just need to call the hash function on one of our Structs and choose a hash algorithm. CryptoKit supports the most common ones from SHA512 to SHA256.

let data = ...
let dataDigest = SHA512.hash(data: data)
let hashString = dataDigest.description


Authenticating Data using Message authentication codes

A message authentication code (MAC) is used to authenticate the sender of a message and confirm the integrity of that message. It allows the receiver to verify the origins of messages and detect changes to the message’s content.

To use this kind of integrity checks we can, for example, use CryptoSwift’s hashed authentication codes, also known as HMACs. The HMAC struct is a generic type that can be used with all the hash functions included in CryptoSwift.

To create a message authentication code , we can use this simple code snippet.

let key = SymmetricKey(size: .bits256)

let authenticationCode = HMAC<SHA256>.authenticationCode(for: messageData, using: key)

We can verify the message by using:

let isValid = HMAC<SHA256>.isValidAuthenticationCode(
    Data(authenticationCode),
    authenticating: messageData,
    using: key
)

As we can see, we need to create a symmetric key first and securely share it between the sender and receiver.


Encrypting Data using symmetric keys

Encrypting and decrypting data using a symmetric key is simple, too. We can use one of two available ciphers: ChaChaPoly (ChaCha20-Poly1305) or AES-GCM in CryptoSwift:

let encryptedData = try! ChaChaPoly.seal(data, using: key).combined

let sealedBox = try! ChaChaPoly.SealedBox(combined: encryptedData)

let decryptedData = try! ChaChaPoly.open(sealedBox, using: key)

We should always make sure not to hardcode these symmetric keys in our app though. We can generate a symmetric key at runtime and then store it safely in the keychain. That way, no one has access to our key to decrypt data.


Performing Key Agreement

In a lot of cases, we will need to perform some form of key exchange to exchange cryptographic keys over an insecure channel. With key agreement protocols like Elliptic-curve Diffie–Hellman (ECDH), we can derive a common secret.

1. Create private/public key-pairs for Alice and Bob

let alicePrivateKey = P256.KeyAgreement.PrivateKey()
let alicePublicKey = alicePrivateKey.publicKey
let bobPrivateKey = P256.KeyAgreement.PrivateKey()
let bobPublicKey = bobPrivateKey.publicKey

Both Alice and Bob create their own private/public key-pairs and share their public keys.

2. Deriving shared secret

let aliceSharedSecret = try! alicePrivateKey.sharedSecretFromKeyAgreement(with: bobPublicKey)

let bobSharedSecret = try! bobPrivateKey.sharedSecretFromKeyAgreement(with: alicePublicKey)

We were now able to derive a common secret by using the own private key together with the counterpart’s public key. aliceSharedSecret and bobSharedSecret are now the same.

3. The created secret number should not be used as an encryption key by itself. Instead it can be used to generate a much larger and more secure encryption key using HKDF or X9.63 key derivation.

let usedSalt = "Secure iOS App".data(using: .utf8)!

let symmetricKey = aliceSharedSecret.hkdfDerivedSymmetricKey(
    using: SHA256.self,
    salt: protocolSalt,
    sharedInfo: Data(),
    outputByteCount: 32
)

That’s generally how you could implement it! Also note that Apple has an implementation of Diffie-Hellman in iOS as part of Secure Transport.


Creating and Verifying Signatures

If we want to send messages and make sure that the sender is the person we thought it is we can use signatures. To do so, we need a private/public key pair first.

let signingKey = Curve25519.Signing.PrivateKey()
let signingPublicKey = signingKey.publicKey

Using the private key any form of data can be signed.

let data = ...
let signature = try! signingKey.signature(for: data)

This signature is then sent together with the actual data to the receiver which can use the public key to validate the signature.

let isSignatureValid = signingPublicKey.isValidSignature(signature, for: data)

That’s all about in this article.


Conclusion

In this article, We understood about Apple’s iOS security Best Practices. Creating secure and robust iOS applications is not easy. However, we can improve security in our iOS apps without much effort by sticking to best practices. Protecting user data must be a high priority and should never be ignored.

Thanks for reading ! I hope you enjoyed and learned about Apple’s iOS security Best Practices. Reading is one thing, but the only way to master it is to do it yourself.

Please follow and subscribe us on this blog and and support us in any way possible. Also like and share the article with others for spread valuable knowledge.

If you have any comments, questions, or think I missed something, feel free to leave them below in the comment box.

Thanks again Reading. HAPPY READING !!???

Exit mobile version