유용한 convenience init을 이용한 초기화

임혜정·2024년 10월 12일
0

convenience init()은 swift에서만 사용되는 독특한 초기화방법이다. 기본적으로 초기화 메서드는 모든 저장 프로퍼티를 직접 초기화해야한다.

class Student {
    let name: String
    let age: Int
    let grade: Int
    
    // 기본 초기화 메서드 (Designated Initializer)
    init(name: String, age: Int, grade: Int) {
        self.name = name
        self.age = age
        self.grade = grade
    }
    
    // 편의 초기화 메서드 (Convenience Initializer)
    convenience init(name: String, grade: Int) {
        // 나이를 계산해서 기본 초기화 메서드 호출
        let estimatedAge = grade + 6
        self.init(name: name, age: estimatedAge, grade: grade)
    }
}

모든 프로퍼티가 옵셔널타입이 아니므로 모든 프로퍼티에 값을 할당해줘야함. 그러나 convenience init을 사용하면 전체 프로퍼티의 일부분만 초기화하여 인스턴스를 생성할 수 있다.


유용하게 쓸 수 있는 예시 몇개

1. uicolor값을 헥사코드(string)로 사용할 수 있도록 해주는 확장자

// MARK: - 헥사코드 사용예시 UIColor(hex: "#000000")

extension UIColor {
    convenience init(hex: String) {
        var hexSanitized = hex.trimmingCharacters(in: .whitespacesAndNewlines)
        hexSanitized = hexSanitized.replacingOccurrences(of: "#", with: "")
        
        var rgb: UInt64 = 0
        Scanner(string: hexSanitized).scanHexInt64(&rgb)
        
        let r = CGFloat((rgb & 0xFF0000) >> 16) / 255.0
        let g = CGFloat((rgb & 0x00FF00) >> 8) / 255.0
        let b = CGFloat(rgb & 0x0000FF) / 255.0
        let a = CGFloat(1.0)
        
        self.init(red: r, green: g, blue: b, alpha: a)
    }
}

설명 :
앞뒤 공백이랑 줄바꿈 날림 (trimmingCharacters)
"#" 기호도 제거 (replacingOccurrences)

16진수 → 정수로 변환:

Scanner 클래스로 UInt64로 바꿈

RGB 추출:

비트 연산으로 R, G, B 각각 뽑아냄
비트 시프트(>>)랑 AND(&) 연산 씀
255로 나눠서 0~1 사이 값으로 (CGFloat)

UIColor 만들기:
추출한 RGB 값이랑 알파값(1.0) 넣어서 UIColor 초기화

2. URL 생성을 위한 메서드

extension URL {
    convenience init?(baseURL: String, path: String) {
        guard let base = URL(string: baseURL) else { return nil }
        self.init(string: path, relativeTo: base)
    }
}

// 사용 예:
let url = URL(baseURL: "https://api.example.com", path: "/users")

baseURL 체크:

문자열로 받은 baseURL을 URL 객체로 변환
실패하면 바로 nil 리턴 (guard let 사용)

URL 생성:

path를 baseURL에 상대 경로로 붙여서 새 URL 만듦

특징:

convenience init 패턴 → 쓰기 편함
옵셔널 이니셜라이저 (init?) → 실패 가능성 있음
guard let으로 early exit → 안전성 높임

장점:

베이스 URL이랑 경로 따로 관리할 때 편함
API 호출 같은 거 할 때 코드 깔끔해짐

사용 예:
let url = URL(baseURL: "https://api.example.com", path: "/users")
주의할 점:

baseURL이 유효한 URL 형식 아니면 nil 반환함
path가 이상해도 URL 객체는 만들어질 수 있음 (상대 경로라)

응용한다면?

쿼리 파라미터도 쉽게 추가할 수 있게 하면 더 좋을 듯
path 유효성 검사 추가하면 더 안전할 것 같음

3. 이미지 리사이징

extension UIImage {
    convenience init?(named name: String, size: CGSize) {
        guard let original = UIImage(named: name) else { return nil }
        let renderer = UIGraphicsImageRenderer(size: size)
        let resized = renderer.image { _ in
            original.draw(in: CGRect(origin: .zero, size: size))
        }
        guard let cgImage = resized.cgImage else { return nil }
        self.init(cgImage: cgImage, scale: UIScreen.main.scale, orientation: .up)
    }
}

// 사용 예:
let resizedImage = UIImage(named: "profile", size: CGSize(width: 100, height: 100))

4. core data 관리 객체 생성

extension NSManagedObject {
    convenience init(context: NSManagedObjectContext) {
        let name = String(describing: type(of: self))
        let entity = NSEntityDescription.entity(forEntityName: name, in: context)!
        self.init(entity: entity, insertInto: context)
    }
}

// 사용 예:
let context = persistentContainer.viewContext
let user = User(context: context)
profile
오늘 배운걸 까먹었을 미래의 나에게..⭐️

0개의 댓글