Wednesday, April 19, 2023

Swift Functions as Parameters and Trailing Closure

Place the following code in an XCode Play Ground:


import UIKit


struct Person {

    let birthYear : Int

    let name : String

    let tag : String

}


//The build function allows a builder function to be passed in. That function

//can create a new person based on the paramaters passed in

extension Person {

    static func build(birthYear: Int, name: String, tag: String, builder: (_ birthYear: Int, _ name : String, _ tag: String) -> Person) -> Person {

        

        return builder(birthYear, name, tag)

    }

}


//Functions can have argument labels and parameter names


//Argument labels and Parameter names

func personBuilderOne(theBirthYear birthYear: Int, theName name: String, theTag tag: String) -> Person {

    return Person(birthYear: birthYear, name: name, tag: tag + " Builder One")

}


//No Argument labels, just parameter names

func personBuilderTwo(birthYear: Int, name: String, tag: String) -> Person {

    return Person(birthYear: birthYear, name: name, tag: tag + " Builder Two")

}


//Parameter names are not needed when calling

func personBuilderThree(_ birthYear: Int, _ name: String, _ tag: String) -> Person {

    return Person(birthYear: birthYear, name: name, tag: tag + " Builder Three")

}


//----------------------------------------------------------

//Notice how the signature changes for the function paramter

var person = Person.build(birthYear: 1900, name: "John", tag: "tag", builder: personBuilderOne(theBirthYear:theName:theTag:))

print(person)


person = Person.build(birthYear: 1900, name: "John", tag: "tag", builder: personBuilderTwo(birthYear:name:tag:))

print(person)


person = Person.build(birthYear: 1900, name: "John", tag: "tag", builder: personBuilderThree(_:_:_:))

print(person)

//----------------------------------------------------------



//The builder can be done by using a closure

//The closure params are contrived just to show how they are used

person = Person.build(birthYear: 1910, name: "Mary", tag: "tag") { bYear, theName, theTag in

    return Person(birthYear: bYear, name: theName, tag: theTag + " Closure")

}

print(person)


The output:

Person(birthYear: 1900, name: "John", tag: "tag Builder One")

Person(birthYear: 1900, name: "John", tag: "tag Builder Two")

Person(birthYear: 1900, name: "John", tag: "tag Builder Three")

Person(birthYear: 1910, name: "Mary", tag: "tag Closure")