Swift Closure 문법

byron1st·2021년 9월 5일
0

Swift 배우기

목록 보기
1/3

SwiftUI에서 Core Data를 사용해보려고 아래 코드를 튜토리얼을 참고하여 작성했다.

import SwiftUI
import CoreData

@main
struct DoneListApp: App {
    lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "Model")
        container.loadPersistentStores { description, error in
            if let error = error {
                fatalError("Failed to load persistent stores: \(error)")
            }
        }
        
        return container
    }()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

Swift 문법은 정말 신기한(?) 것들이 많은데, 한줄 한줄 살펴보기로 하자. 첫째로 이해가 안 간 라인은 아래 코드다.

@main
struct DoneListApp: App {
    lazy var persistentContainer: NSPersistentContainer = {
	...
    	// wft... 이 신기한 문법은 무엇?
        container.loadPersistentStores { description, error in
            ...
        }
        ...
    }()
}

... 당췌 이게 무슨 코드란 말인가.

정답은 Closure 였다. Swift 에서 Closure의 뜻을 보면,

Closures are self-contained blocks of functionality that can be passed around and used in your code. (swift.org)

JavaScript, Go 언어와 마찬가지로 Swift 도 함수를 변수로 취급하여 다른 함수의 argument 로 넘겨줄 수 있다. 그리고 함수 안에 또 다른 함수를 정의하고, 내부에 정의된 함수가 외부의 변수를 참조하는 등의 행위를 할 수 있다.

즉, Closure 는 결국 그냥 함수라고 할 수 있다. 그래서 위의 코드는 아래와같이 정의하고 쓸 수도 있다.

@main
struct DoneListApp: App {
    lazy var persistentContainer: NSPersistentContainer = {
        ...        
        func handler (description: NSPersistentStoreDescription, error: Error?) -> Void {
            ...
        }
        container.loadPersistentStores(completionHandler: handler)
        ...
    }()
    ...
}

결국 Swift의 Closure expression 인 아래 문법은 Closure 문법을 간편하게 쓰기 위한 일종의 syntactic sugar 인 셈이다.

{ (parameters) -> return type in
    statements
}

Swift가 정말 이런 문법들이 많고, 저 Closure 문법과 함수 정의 문법 사이의 유사도가 거의 없어서 처음에 참 어렵다. (도대체 in 이라는 키워드를 쓰는건 누구 아이디어인지... in 때문에 난 처음에 for 루프 문법인줄 알았고, 실제로 for 루프 문법에서도 in 키워드를 쓴다)

참고로, DoneListApp 구조체의 변수인 persistentContainer를 정의하는 것도 Closure로 되어 있다.

@main
struct DoneListApp: App {
	lazy var persistentContainer: NSPersistentContainer = {
    ...
    return container
    }()
}

NSPersistentContainer 타입의 변수를 반환하는 Closure 함수를 바로 정의하고, 정의하자마자 바로 사용 () 함으로써, persistentContainer 변수를 정의하는 식이다. 이는 아래와 같다.

@main
struct DoneListApp: App {
	func initializeContainer() -> NSPersistentContainer {
    	...
        return container
    }
    
	lazy var persistentContainer: NSPersistentContainer = initializeContainer()
}

원래는 다른 언어라면, persistentContainer 변수의 초기값은 nil 일 것이고, 생성자(constructor 또는 init) 함수에서 처리하는 것이 일반적일 것이다.

profile
Fullstack software engineer specialized for Blockchain

0개의 댓글