Failable 초기화자(init?)는 Swift에서 타입의 인스턴스를 생성하는 과정이 실패할 수 있는 상황을 설명할 수 있도록 해줍니다. 이들은 종종 입력 데이터 검증이나 성공하지 못할 수 있는 변환을 위해 사용됩니다. failable 초기화자에서는 객체 생성이 실패함을 나타내기 위해 명시적으로 nil을 반환할 수 있습니다.
예시:
struct User { let name: String let age: Int init?(name: String, age: Int) { guard !name.isEmpty, age > 0 else { return nil } self.name = name self.age = age } }
이렇게 해서 잘못된 객체의 생성을 방지할 수 있습니다.
compactMap), 유효하지 않은 인스턴스를 필터링하는 데 편리합니다.질문: init?와 init!의 차이점은 무엇이며 언제 implicit unwrapping과 함께 failable 초기화자를 사용해야 하나요?
답변: init?는 옵셔널(<type?>)을 반환하며 초기화가 실패하면 nil이 반환되어 안전한 처리가 필요합니다. init!은 implicitly unwrapped optional(<type!>)을 반환하며, 초기화가 실패할 경우에도 nil이 반환되지만, 검증 없이 해당 객체를 사용하면 runtime-crash가 발생합니다. init!은 당신의 컨텍스트에서 초기화가 실패하지 않을 것이라고 확신하는 경우에만 사용하세요 (예: UIKit의 storyboard 작업 시).
let value = Int("abc") // value는 nil이 됩니다
이야기
JSON을 수동으로 파싱하면서 일반 초기화자를 사용하였습니다. 이로 인해 유효성 검증이 작동하지 않아 "빈" 사용자들이 생성되고, 애플리케이션이 유효하지 않은 데이터를 필터링하지 못했습니다.
이야기
잠재적으로 유효하지 않은 데이터와 함께
init!을 사용하는 것의 결과로 API 업데이트 후 애플리케이션이 크래시되었습니다: 입력 데이터 형식이 변경되었고, 객체를 추출할 때 nil의 암시적 추출로 인해 runtime 예외가 발생했습니다.
이야기
failable init의 커스텀 구현에서 일부 시나리오에 대해 nil을 명시적으로 반환하는 것을 잊은 결과, 구조체가 "더러운" 필드로 초기화되어 비즈니스 로직에서 버그를 일으켰습니다.