티스토리 뷰

프로그래밍/Swift

Swift 기초 공부5

시르베어 2025. 2. 2. 22:46

익스텐션

  • 구조체, 클래스, 열거형, 프로토콜 타입에 새로운 기능을 추가할 수 있음
  • 추가할 수 있는 기능 (저장 프로퍼티는 불가능, 기존의 프로퍼티에 감시자 불가능)
    1. 연산 타입 프로퍼티 / 연산 인스턴스 프로퍼티
    2. 타입 메서드 / 인스턴스 메서드
    3. 이니셜라이저
    4. 서브스크립트
    5. 중첩 타입
    6. 특정 프로토콜을 준수할 수 있도록 기능 추가
  • 기존에 존재하는 기능을 재정의할 수는 없음
  • 상속 : 수직확장, 익스텐션 : 수평확장
extension 확장할타입이름: protocol1, protocol2 ... {
    // 요구사항 구현
}
extension String { // 서브스크립트 확장
    subscript(add: String){ return Self+add }
}
struct A {
    var value: Int
    init(_ value: Int){
        self.value = value
    }
}
extension A { // 이니셜라이저 확장
    init(_ value: Double){
        self.value = Int(value)
    }
}

제네릭

  • 어떤 타입에도 유연하게 대응할 수 있음
  • 코드 중복을 줄일 수 있고 추상적인 표현도 가능
struct Stack<T> {
    var arr: [T] = []
    mutating func push(_ element: T){
        self.arr.append(element)
    }
    mutating func pop() -> T? {
        return self.arr.popLast()
    }
    ...
}
extension Stack {
    func isEmpty() -> Bool {
        return self.arr.isEmpty
    }
    func top() -> T? {
        return self.arr.last
    }
}

타입 제약

func substract<T>(_ a: T, _ b: T) -> T { // "Binary operator '-' cannot be applied to two 'T' operands" 에러 발생
    return a - b
}
func substract<T: BinaryInteger>(_ a: T, _ b: T) -> T {
    return a - b
}
  • 위의 코드에서 T가 BinaryInteger를 채택하면서 타입 제약을 해서 뺄셈을 진행할 수 있음

프로토콜 지향 프로그래밍

  • 프로토콜을 정의할 때는 프로토콜의 요구사항을 구현할 수 없음 -> 익스텐션에는 프로콜이 요구하는 기능을 실제로 구현할 수 있음 (단, 저장 프로퍼티는 구현할 수 없음)
protocol A {
    var data: Any { get }
    func dataPrint()
}
extension A {
    func dataPrint(){
        print("data = \\(self.data)")
    }
}
class a: A {
    var data: Any = "test"
}
let value: a = a()
value.dataPrint() // "data = test"

ARC

  • Auto Reference Counting (메모리 관리 기법)
  • 클래스의 인스턴스에만 적용
  • 참조 횟수가 0이 되는 순간 메모리에서 해제

강한참조

  • 인스턴스가 계속해서 메모리에 남아있어야 하는 명분을 만들어 주는 것
  • 인스턴스를 다른 인스턴스의 프로퍼티나 변수, 상수 등에 할당할 때 참조 횟수가 1 증가
  • nil을 할당해주면 참조 횟수 1 감소
  • 별도의 식별자를 명시하지 않으면 강한참조

강한참조 순환문제

  • 인스턴스끼리 서로가 서로를 강한참조 할때 발생할 수 있음
  • 메모리 누수 발생
  • 이런 상황에서 디이니셜라이저는 작동하지 않음 (디이니셜라이저는 메모리에서 해제될때 호출 - 메모리가 누수되면 작동하지 않음)
class Number {
    var partner: Number?
    let number: Int
    init(value: Int){
        self.number = value
    }
}
var A: Number? = Number(value: 10) // A 참조 1
var B: Number? = Number(value: 20) // B 참조 1
A?.partner = B // B 참조 2
B?.partner = A // A 참조 2
// 해당 소스에서 순환문제를 해결할려면 A?.partner = nil, B?.partner = nil을 처리해야함
A = nil // A 참조 1
B = nil // B 참조 1

약한참조

  • 인스턴스의 참조 횟수를 증가 시키지 않음 (weak 키워드 사용)
  • 옵셔널 변수만 약한 참조로 사용가능
class Number {
    weak var partner: Number?
    let number: Int
    init(value: Int){
        self.number = value
    }
    deinit {
        print("소멸")
    }
}
var A: Number? = Number(value: 10) // A 참조 1
var B: Number? = Number(value: 20) // B 참조 1
A?.partner = B // 참조가 증가하지 않음
B?.partner = A // 참조가 증가하지 않음
A = nil // A 참조 0
B = nil // B 참조 0

미소유참조

  • 인스턴스의 참조 횟수를 증가 시키지 않음 (unowned)
  • 자신이 참조하는 인스턴스가 메모리에서 해제되더라도 스스로 nil을 할당해주지않음 (즉, 메모리에서 해제한 뒤에 접근하면 런타임 에러가 발생한다) - 옵셔널 변수로 선언하지 않아도 됨

'프로그래밍 > Swift' 카테고리의 다른 글

UserDefaults, FileManager, CoreData  (1) 2025.03.06
class 키워드와 AnyObject 키워드  (0) 2025.02.02
Swift 기초 공부4  (0) 2025.02.02
Swift 기초 공부3  (0) 2025.02.02
Swift 기초 공부2  (0) 2025.01.30
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2026/01   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함