클로저를 사용한 프로퍼티 기본값 설정
사용자 정의 연산을 통해 저장 프로퍼티의 기본값을 설정하려면 클로저나 함수를 사용해 프로퍼티 기본값을 제공할 수 있다. 인스턴스를 초기화할 때 함수나 클로저가 호출되며 연산 결괏값을 프로퍼티 기본값으로 제공하게 된다. 그렇기에 클로저나 함수의 retrun
타입은 반드시 프로퍼티 타입과 일치해야 한다.
만약 프로퍼티의 기본값을 설정하기 위해 클로저를 사용하면 클로저가 실행되는 시점은 초기화할 때 인스턴스의 다른 프로퍼티 값이 설정되기 전이라는 걸 알아야 한다. 즉, 클로저 내부에서는 인스턴스의 다른 프로퍼티를 사용하여 연산할 수 없다.
- 클로저 내부에서 다른 프로퍼티를 사용하여 연산 불가
- 다른 프로퍼티에 기본값이 있어도 연산 불가
- 클로저 내부에서
self
프로퍼티 사용 불가 - 인스턴스 메서드 호출 불가
클로저를 통한 프로퍼티 기본값 설정
class SomeClass {
let someProperty: SomeType = {
// 새로운 인스턴스를 생성하고 사용자 정의 연산을 통한 후 return 함
return someValue // someType과 동인한 타입이 리턴되어야함
} () // 클로저를 실행하기 위한 소괄호.
// 만약 소괄호가 없다면 프로퍼티의 기본값은 클로저 그 자체가 되므로 주의
}
someProperty
의 타입이 만약 Int
라면 반환 값도 Int
로 타입이 동일해야 한다. 또, 클로저 뒤에 붙은 ( )
소괄호는 클로저를 실행하기 위한 소괄호로써, 만약 소괄호가 없다면 프로퍼티의 기본값은 클로저의 그 자체가 되므로 주의해야 한다.
struct Student {
var name: String?
var number: Int?
}
class SchoolClass {
var students: [Student] = {
// 새로운 인스턴스 생성 후, 사용자 정의 연산을 통한 후 반환 함
// 반환 되는 타입은 [Student]여야 함
var arr: [Student] = [Student]()
return arr
} ()
}
↪︎ 클로저를 통한 student 프로퍼티 기본값 설정
일단 코드를 보면 Student
구조체와 SchoolClass
가 있는데 students
프로퍼티는 Student
구조체의 인스턴스를 요소로 갖는 Array
타입이다. SchoolClass
클래스의 인스턴스를 초기화하게 되면 students
프로퍼티의 기본값을 제공하기 위해 클로저가 동작하게 한다.
struct Student {
var name: String?
var number: Int?
}
class SchoolClass {
var students: [Student] = {
var arr: [Student] = [Student]()
for num in 1...10 {
var student: Student = Student(name: nil, number: num)
arr.append(student)
}
return arr
} ()
}
let Aclass: SchoolClass = SchoolClass()
print(Aclass.students.count) //10
클로저가 동작하면 1부터 10까지의 학생을 생성하여 배열에 할당하게 되고, Aclass
인스턴스는 생성이 되는 동시에 students
프로퍼티에 10명의 학생이 있는 상태가 되게 된다.
iOS 활용
iOS
의 UI
등을 구현할 때, UI 컴포넌트
를 클래스의 프로퍼티로 구현하고, UI 컴포넌트
생성과 동시에 컴포넌트의 프로퍼티를 기본적으로 설정할 때 유용하게 사용된다.
인스턴스 소멸 디이니셜라이저
클래스의 인스턴스에서는 디이니셜라이저 Deinitializer를
구현할 수 있다. 단어 그대로 이니셜라이저의 반대 역할이다. 메모리에서 해제되기 직전 클래스 인스턴스와 관련해 원하는 정리 작업을 구현할 수 있다.
디이니셜라이저는 클래스의 인스턴스가 메모리에서 소멸되기 바로 직전에 호출되고, deinit
키워드를 사용하여 디이니셜라이저를 구현하면 자동으로 호출된다.
주의할 점은 클래스에서만 디이니셜라이저를 구현할 수 있다는 점이다.
deinit 키워드
를 사용함- 인스턴스 소멸 직전에 호출됨
- 모든 프로퍼티에 접근 가능. 프로퍼티 값 변경 가능
- 클래스에서만 디이니셜라이저 구현 가능
- 디이니셜라이저는 단 하나만 구현 가능
- 이니셜라이저와는 다르게 매개변수를 갖지 않음.
( )
소괄호 사용 안 함 - 자동으로 호출하기 때문에 별도의 코드로 호출 불가
- swift는 자동으로 필요하지 않은 인스턴스를 메모리에서 소멸시킴
- 인스턴스 내부에 외부 자원을 사용하거나 큰 파일을 저장해줘야 하는 경우 디이니셜라이저 사용
디이니셜라이저는 인스턴스를 소멸하기 바로 직전에 호출되기 때문에 인스턴스의 모든 프로퍼티에 접근 가능하고 프로퍼티 값을 변경할 수 있다.
import Darwin
class SomeClass {
deinit {
print("인스턴스가 메모리에서 소멸됩니다.")
}
}
var instance: SomeClass? = SomeClass()
instance = nil //인스턴스가 메모리에서 소멸됩니다.
디이니셜라이저를 간단하게 구현해보자면 위 코드처럼 사용하면 된다. 또 다른 예제를 한번 살펴보도록 하자!
class FileManager {
var fileName: String
init(fileName: String) {
self.fileName = fileName
}
func modifyFile() {
print("파일 수정 \(self.fileName)")
}
func openFile() {
print("파일 열기 \(self.fileName)")
}
func writeFile() {
print("파일 쓰기/저장 \(self.fileName)")
}
func closeFile() {
print("파일 닫기 \(self.fileName)")
}
deinit {
print("인스턴스를 메모리에서 소멸시킵니다.")
self.writeFile()
self.closeFile()
}
}
var fileManager: FileManager? = FileManager(fileName: "서근 개발블로그.txt")
if let manager: FileManager = fileManager {
manager.openFile()
manager.modifyFile()
}
fileManager = nil
FileManager
인스턴스가 파일을 불러와서 사용하고, 인스턴스 사용이 끝난 후에는 파일의 수정사항을 저장하고 다시 닫아주기 때문에 메모리에서 파일이 제거/해제되어야 하기 때문에 인스턴스가 메모리에서 해제되기 직전에 파일을 닫아주는 역할을 하게 된다.
여기서 디이니셜라이저를 활용하게 되면 메모리 관리에 탁월하고 설계한 로직에 따라 인스턴스가 메모리에서 해제되기 직전에 적절한 작업을 할 수 있다.
읽어주셔서 감사합니다🤟
'SWIFT > Grammar' 카테고리의 다른 글
Swift : 기초문법 [클로저 및 고차함수(map, filter, reduce)] (0) | 2022.01.19 |
---|---|
Swift : 기초문법 [접근 제어 - open, public, internal, fileprivate, private] (0) | 2022.01.18 |
Swift : 기초문법 [인스턴스 #3 초기화 위임, 실패가능한 이니셜라이저] (0) | 2022.01.15 |
Swift : 기초문법 [인스턴스 #2 기본 이니셜라이저, 멤버와이즈 이니셜라이저] (0) | 2022.01.15 |
Swift : 기초문법 [인스턴스 #1 이니셜라이저, 매개변수) (0) | 2022.01.15 |