본문 바로가기
TIL(Today I Learned)

2025.02.14 Today I Learned

by 승환파크 2025. 2. 14.

Swift의 이니셜라이저

Swift의 init은 클래스, 구조체, 열거형에서 새로운 인스턴스를 생성하는데 필수적인 요소이다.

init 의 역할

Swift에서 init은 객체가 생성될 때 호출되는 생성자(initializer) 역할을 한다. 클래스, 구조체, 열거형 모두 init 키워드를 사용할 수 있으며 이를 통해 초기 속성 값을 부여하거나 특정 로직을 실행할 수 있다.

struct User {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

let user = User(name: "Park", age: 27)

init과 deinit

init은 객체가 생성될 때 호출되는 메서드이고 deinit은 구조체와 열거형에는 존재하지 않고 클래스의 인스턴스가 해제될 때 호출된다.

class TestClass {
    init() {
        print("객체 생성")
    }
    
    deinit {
        print("객체 해제")
    }
}

var test: TestClass? = TestClass() // 객체 생성 출력
test = nil // 객체 해제 출력

 

기본 이니셜라이저(Default Initialzer)

구조체와 클래스에서 프로퍼티가 기본값을 가지면, Swift는 자동으로 기본 이니셜라이저를 제공한다.

struct Car {
    var brand = "현대"
    var model = "아반떼"
}

let myCar = Car() // 기본 이니셜라이저 사용
print(myCar.barnd) // "현대"

 

멤버와이즈 이니셜라이저(Memberwise Initializer)

구조체는 자동으로 멤버와이즈 이니셜라이저를 제공하며, 모든 프로퍼티를 포함하는 초기화 메서드를 생성한다.

struct Point {
    var x: Int
    var y: Int
}

let point = Point(x: 10, y: 20)

 

하지만 클래스에서는 멤버와이즈 이니셜라이저가 존재하지 않기 때문에 프로퍼티에 기본값이 없을 경우 반드시 init을 직접 구현해야 한다.

class Person {
    var name: String
    
    init(name: String) { // 직접 이니셜라이저를 구현해야 한다.
        self.name = name
    }
}

 

다양한 init 사용법

1. 기본 init

가장 기본적인 형태의 이니셜라이저이다.

struct Animal {
    var name: String
    init(name: String) {
        self.name = name
    }
}

let dog = Animal(name: "Dog")

2. 옵셔널 프로퍼티와 init

프로퍼티가 옵셔널이면, 기본적으로 nil을 가질 수 있어 init에서 값을 꼭 할당하지 않아도 된다.

class Book {
    var title: String?
}

let myBook = Book()  // title은 nil

3. 기본값이 있는 init

기본값을 설정하면 특정값을 넣지 않아도 인스턴스를 생성할 수 있다.

struct Laptop {
    var brand: String = "Apple"
    var model: String
    
    init(model: String) {
        self.model = model
    }
}

let macbook = Laptop(model: "MacBook Pro")  // brand는 "Apple"

4. 사용자 정의 init

이니셜라이저 내부에서 특정 로직을 수행할 수도 있다.

struct Temperature {
    var celsius: Double
    
    init(fahrenheit: Double) {
        self.celsius = (fahrenheit - 32) * 5/9
    }
}

let temp = Temperature(fahrenheit: 98.6)
print(temp.celsius)  // 37.0

 

convenience init(편의 이니셜라이저)

convenience init은 추가적인 이니셜라이저를 제공할 때 사용하며, 반드시 designated init 키워드를 호출해야 한다. 단, 구조체와 열거형에서는 convenience를 사용할 수 없다.

class User {
    var name: String
    var age: Int
    
    init(name: String, age: Int) {  // 지정 이니셜라이저
        self.name = name
        self.age = age
    }
    
    convenience init(name: String) {  // 편의 이니셜라이저
        self.init(name: name, age: 0)  // 지정 이니셜라이저 호출 필수
    }
}

let user1 = User(name: "Alice", age: 30)
let user2 = User(name: "Bob")  // 편의 이니셜라이저 사용

 

상속과 init

1. required init

required 키워드는 서브클래스에서 반드시 구현해야 하는 이니셜라이저를 의미한다.

예시로는 주로 사용하는 TableView 를 구현할 때 cell을 커스텀 셀로 만들어줄 때 UITableViewCell 클래스를 상속받아 작성하는데 그곳에서도 required init을 사용한 경우가 존재한다.

open class UITableViewCell: UIView {
    ...
    public required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
    ...
}

class customCell: UITableViewCell {
    ...
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    ...
}

2. override init

부모클래스의 init 을 오버라이드 할 때 사용한다.

class Vehicle {
    var speed: Int
    init(speed: Int) {
        self.speed = speed
    }
}

class Car: Vehicle {
    override init(speed: Int) {
        super.init(speed: speed)
        print("Car initialized!")
    }
}

let myCar = Car(speed: 100)  // "Car initialized!" 출력

 

failable init (실패 가능한 이니셜라이저)

객체 생성에 실패할 가능성이 있는 경우 init? 을 사용하여 nil 을 반환할 수 있다. (required init 부분의 예시 코드에도 init? 으로 작성된 것을 확인할 수 있다.)

struct Product {
    var name: String
    var price: Int
    
    init?(name: String, price: Int) {
        if price < 0 {
            return nil  // 가격이 음수면 객체 생성 실패
        }
        self.name = name
        self.price = price
    }
}

let validProduct = Product(name: "Laptop", price: 1000)  // 정상 생성
let invalidProduct = Product(name: "Invalid", price: -1)  // nil 반환

'TIL(Today I Learned)' 카테고리의 다른 글

Swift의 ARC  (0) 2025.03.01
2025.02.24 Today I Learned  (0) 2025.02.24
2025.02.05 Today I Learned  (0) 2025.02.05
2025.01.24 Today I Learned  (0) 2025.01.24
2025.01.16 Today I Learned  (1) 2025.01.16