Apple-CS-interview / iOS-CS-interview

7 stars 1 forks source link

탈출 클로저에 대하여 설명하시오. #21

Open Do-hyun-Kim opened 1 year ago

Do-hyun-Kim commented 1 year ago

탈출 클로저에 대하여 설명하시오.

비탈출 클로저에 대해 알아가기!!

Closure Capturing Values

func setHumanName() {
    var name = "김도현"

    print("현재 사람의 이름은 \(name) 입니다.")

    var closure: () -> Void = {
        // keyword: 이부분에서 캡쳐된 name값을 출력!!
        print("캡쳐된 이름은 \(name) 입니다.")
    }
    name = "김제니"
    print("두 번째 변경된 이름은 \(name) 입니다")
    // keyword: closure 사용하여 name값을 캡쳐
    closure()
}

setHumanName()

class Jenny {
    var name: String

    init(name: String) {
        self.name = name

    }

    // keyword: setNameClosure 없음 deinit 잘 호출됨 즉 setNameClosure에서 순환 참조 발생 으로 인해 헤체가 안되고 있음
   lazy var setNameClosure: () -> String = {
       //요기서 setNameClosure 내부 Context에서 self.name 을 캡쳐하고 있기에 순환 참조 발생을 일으키고 있다.
        self.name += "입니다"
        return self.name
    }

    deinit {
        print("Jenny Deinit!")
    }

}

var hyun: Jenny? = Jenny(name: "김도현")
print(hyun!.setNameClosure)
hyun = nil

📝 참고 사이트

Hminchae commented 1 year ago

클로저란?

어떤 기능을 하는 코드를 하나의 블럭으로 모아놓은 것. 함수도 클로저의 한 형태, 클로저의 큰 특징은 클로저가 선언된 위치에서 어떤 상태를 캡쳐하고 참조를 얻을 수 있다는 것임

Escaping Closure

탈출 클로저란 @escaping이 붙은 클로저로, 함수가 반환된 후 밖에서 실행시키는 클로저 를 말 함

-> 서버 비동기처리가 필요하거나, 특정 함수가 종료될때 특정 행동을 취하고 싶으면 탈출 클로저를 사용함

사용은 다음과 같이 해볼 수 있다.

func doSomethingAsync(completion: @escaping () -> Void) {
    // 비동기 작업 수행 후
    // completion 클로저를 나중에 호출
}
import Foundation

// 네트워크 요청을 수행하는 함수
func fetchURLData(from url: URL, completionHandler: @escaping (Data?, Error?) -> Void) {
    URLSession.shared.dataTask(with: url) { (data, response, error) in
        if let error = error {
            completionHandler(nil, error) // 클로저가 함수를 벗어나 호출됨
        } else if let data = data {
            completionHandler(data, nil) // 클로저가 함수를 벗어나 호출됨
        }
    }.resume()
}

// 네트워크 요청 실행
if let url = URL(string: "https://example.com/data.json") {
    fetchURLData(from: url) { (data, error) in
        if let error = error {
            print("에러 발생: \(error)")
        } else if let data = data {
            let responseString = String(data: data, encoding: .utf8)
            print("데이터 받아옴: \(responseString ?? "데이터 없음")")
        }
    }
}

non-escaping 과 escaping

참조

vichye-1 commented 1 year ago

탈출(escape)

non-escaping Closure

escaping Closure(@escaping)

func doSomeThing(closure: @escaping () -> ()) {

}

escaping을 무분별하게 쓰면 안 되는 이유

참고

ronick-grammer commented 1 year ago

클로저란

코드를 하나의 블럭으로 모아놓은 것을 의미한다. named closureunnamed closure 가 있으며 func 키워드로 시작해서 뒤에 이름이 붙는 클로저를 named closure라 하며 일반적으로 함수라고 부른다. 반면 func 키워드 없이 매개변수와 리턴타입을 정의하는 헤더부분과 구현부인 바디부분 이루어진 것을 unnamed closure라 한다. 보통 클로저라고 하면 이 unnamed closure라고 할 수 있다.

클로저는 참조타입이다.

클로저는 외부 변수를 참조할 때 기본적으로 strong 방식으로 캡처하기 때문에, 강한 참조 사이클이 발생할 수가 있어서 weak이나 unowned 방식으로 캡처할 수 있도록 하여 memory leak 상황을 방지할 수 있다.

비탈출(non-escaping) 클로저와 탈출(escaping) 클로저

non-escapingescaping 메카니즘은 함수의 매개변수로 클로저를 받을 때 적용된다.

📝 참고 사이트