[iOS] 6주차 정리

Zoe·2022년 7월 19일
0

iOS

목록 보기
7/39

6주차 정리


✅ self / Self


struct MyStruct {
    static let club = "iOS부서"
    
    static func doPrinting() {
        print("소속은 \(self.club)입니다.")
    }
}

struct MyStruct {
    static let club = "iOS부서"
    
    func doPrinting() {
        print("소속은 \(MyStruct.club)입니다.")
    }
}
  • 타입 인스턴스 : 붕어빵 틀 자체를 의미
//프로토콜에서 Self의 사용
extension BinaryInteger {
    func squared() -> Self {  // 타입자체(Int)를 가르킴
        return self * self    // 인스턴스(7)를 가르킴
    }
}

✅ 클로저

  • 스위프트는 함수를 "일급객체"로 취급
  • 함수는 타입

    함수를 변수에 할당할 수 있음
    함수를 호출할 때, 함수를 파라미터로 전달할 수 있음
    함수에서 함수를 반환할 수 있음

1️⃣ 사용하는 이유

  • 익명 함수 : 함수를 실행할 때 전달하는 형태로 사용하기 때문에 이름이 필요없음
// 1) (클로저를 파라미터로 받는 함수)정의

func closureParamFunction(closure: () -> ()) {
    print("프린트 시작")
    closure()
}

// 파라미터로 사용할 함수/클로저를 정의
func printSwiftFunction() {          // 함수를 정의
    print("프린트 종료")
}

let printSwift = { () -> () in      // 클로저를 정의
    print("프린트 종료")
}

// 함수를 파라미터로 넣으면서 실행 (그동안에 배운 형태로 실행한다면)
closureParamFunction(closure: printSwiftFunction)
closureParamFunction(closure: printSwift)

// 2) 함수를 실행할때 클로저 형태로 전달 (클로저를 사용하는 이유)
closureParamFunction(closure: { () -> () in
    print("프린트 종료")           // 본래 정의된 함수를 실행시키면서, 클로저를 사후적으로 정의 가능
})                              // (활용도가 늘어남)

closureParamFunction(closure: { () -> () in
    print("프린트 종료 - 1")
    print("프린트 종료 - 2")
})

2️⃣ 클로저 사용 예시 : 테이블뷰 스와이프

func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
        // 오른쪽에 만들기
        
        let modity = UIContextualAction(style: .normal, title: "수정") { (UIContextualAction, UIView, success: @escaping (Bool) -> Void) in
            print("수정 클릭 됨")
            success(true)
        }
        modity.backgroundColor = .systemBlue
        
        
        let delete = UIContextualAction(style: .normal, title: "삭제") { (UIContextualAction, UIView, success: @escaping (Bool) -> Void) in
            print("삭제 클릭 됨")
            success(true)
        }
        delete.backgroundColor = .systemRed
        
        //actions배열 인덱스 0이 오른쪽에 붙어서 나옴
        return UISwipeActionsConfiguration(actions:[delete, modity])
 }

3️⃣ 클로저의 메모리 구조

  • 클로저는 힙에 저장
  • 코드 영역의 주소를 저장하는 클로저가 힙에 저장되는 것
  • 불변의 진리 : 함수의 직접적인 실행은 스택에서 진행
//캡처
var stored = 0


let closure = { (number: Int) -> Int in
    stored += number
    return stored
}

closure(3) // 3

closure(4) // 7

closure(5) // 12

stored = 0

closure(5) // 5
  • stored를 가리키고 있는 주소를 저장
  • 지속적으로 stored를 참조하도록 만든 것
// 함수 내에서 함수를 실행하고, 값을 리턴하는 일반적인 함수
func calculate(number: Int) -> Int {  
    var sum = 0
    
    func square(num: Int) -> Int {
        sum += (num * num)
        return sum
    }
    
    let result = square(num: number)
    
    return result
}

calculate(number: 10) //100
calculate(number: 20) //400
calculate(number: 30) //900

// 🌟 캡처가 발생
func calculateFunc() -> ((Int) -> Int) {
    
    var sum = 0
    
    func square(num: Int) -> Int {
        sum += (num * num)
        return sum
    }
    
    return square
}

// 변수에 저장하는 경우(Heap 메모리에 유지)
var squareFunc = calculateFunc()

squareFunc(10) // 100
squareFunc(20) // 500
squareFunc(30) // 1400

// 레퍼런스 타입
var dodoFunc = squareFunc
dodoFunc(20) // 1800
  • 실제로 클로저라는 의미 : 닫는다, 보관한다, 외부에 있는 변수를 지속적으로 저장하는 특성!
  • 스택 프레임을 쌓아서 없어지는 개념이 아니라 힙에 지속적으로 저장하는 것!

4️⃣ @escaping

  • 왜 사용할까 ? 원칙적으로는 함수의 실행이 끝나면 파라미터로 쓰이는 클로저도 제거되지만 @escaping키워드를 사용할 경우 함수가 종료되어도 클로저가 존재.
// 어떤 함수의 내부에 존재하는 클로저(함수)를 외부 변수에 저장할 경우

var aSavedFunction: () -> () = { print("출력") }

//aSavedFunction()

func performEscaping2(closure: @escaping () -> ()) {
    aSavedFunction = closure         // 클로저를 실행하는 것이 아니라  aSavedFunction 변수에 저장
    //closure()
}

//aSavedFunction()

performEscaping2(closure: { print("다르게 출력") })

//aSavedFunction()
  • performEscaping2의 실행을 벗어나서도 클로저의 메모리 주소가 계속 필요하므로 @escaping 키워드가 필요함!
  • 함수를 변수에 저장한다는 의미는 함수를 오랫동안 사용한다는 의미이고 이것은 힙의 메모리에 저장이 필요하다는 의미!
profile
iOS 개발자😺

0개의 댓글