Search code examples
arraysswiftinitializationclosures

Swift what does the closure immediately after squared bracket wrapped array do


I am following the official tutorial of IOS dev from Apple. I encounter this small block and could not wrap my head around of it.

Landmark is the data model

@Published var landmarks: [Landmark]

var features: [Landmark]{
        landmarks.filter{$0.isFeatured}
    }

Apparently features is an array with Landmark type as its member. The landmarks.filter{$0.isFeatured} is simply trying to filter out those Landmarks that have their property isFeatured to be true.

But I've checked out the initialization of an array in Swift, those you see are like you using var features = landmarks.filter($0.isFeatured). And you barely see any example of [ something ] { something }

Is the sample code the proper way to initialize an array with closure?

For those who interested trying out yourself, you can try the toy code below in playground:

struct MyStruct: Codable {
    var isYes: Bool
    var name: String
}

let myArray = [
    MyStruct(isYes: true, name: "A"),
    MyStruct(isYes: true, name: "B"),
    MyStruct(isYes: false, name: "C"),
]

print("hello")
print(myArray)

var myArray2: [MyStruct]{
    myArray.filter{$0.isYes}
}

print(myArray2)

//var myArray3: [MyStruct] = myArray.filter($0.isYes)
//
//print(myArray3)

//var myArray4: [MyStruct] = {myArray.filter($0.isYes)}
//
//print(myArray4)

//var myArray5<MyStruct> = {myArray.filter($0.isYes)}
//
//print(myArray5)

var arrayB = myArray.filter{$0.isYes}
print(arrayB)

Solution

  • There is no "initialization" in that code. You are looking at a computed variable (property).

    features is, in effect, a function that returns a value (with the word return omitted because it is a one liner); it just runs afresh each time you say features.

    This could have been written as

    func features() -> [Landmark] {
        landmarks.filter{$0.isFeatured}
    }
    

    but one has a feeling that this is better expressed as a sort of property than as a method.

    Here's a simpler case to play with in a playground:

    struct Greeter {
        var greeting : String { "howdy" }
        func greet() -> String { "howdy" }
    }
    let greeter = Greeter()
    print(greeter.greeting)
    print(greeter.greet())