최대 1 분 소요

원래 Swift에서는 외부 모듈의 internal 프로퍼티에 당연히! 접근할 수 없습니다. 접근레벨이 public이거나 open인 경우에만 외부에서 사용할 수 있습니다.

그런데 외부 모듈의 internal 프로퍼티에 접근할 수 있는 케이스🤩가 있습니다. UIAlertAction을 예로 설명해보겠습니다.

let action = UIAlertAction(title: "title", style: .default) { _ in
	print("alert!")
}

// 에러, handler는 공개되어 있지 않습니다.
let handler = action.handler??

위와 같은 UIAlertAction 코드가 있을 때 외부에서 handler에 접근할 방법이 없습니다. 그런데 다음과 같은 방법으로 handler에 접근할 수 있습니다.

// value(forKey:) 메서드를 통한 접근
let actionHandler = action.value(forKey: "handler")!
print(actionHandler)
// <__NSMallocBlock__: 0x600003c735a0>

handler를 가져왔지만, 타입이 NSMallocBlock 입니다. 이제 이것을 사용할 수 있도록 타입 캐스팅을 해보도록 하겠습니다. 위에서 정의한 handler의 타입은 (UIAlertAction) -> Void 입니다. 즉 함수입니다. 첫 번째 소스코드에서 클로저를 전달한 것(handler)을 볼 수 있습니다.

다음은 handler를 사용하기 위해 타입 캐스팅을 하는 코드입니다.

typealias AlertHandler = @convention(block) (UIAlertAction) -> Void

let actionHandler = action.value(forKey: "handler")!
let blockPtr = UnsafeRawPointer(Unmanaged<AnyObject>.passUnretained(actionHandler as AnyObject).toOpaque())
let handler = unsafeBitCast(blockPtr, to: AlertHandler.self)
handler(action)
// alert!!

handler를 타입 캐스팅하기 위해서는 위와 같은 과정이 필요합니다. actionHandler의 주소를 가져와서 변환?하는 것으로 보입니다.🤔 이러한 방식을 이용하면 다른 타입도 접근하여 가져올 수 있다고 보입니다.

반대로 외부 모듈의 internal 프로퍼티에 값을 할당할 수도 있습니다. 이때는 setValue(forKey:) 메서드를 사용합니다.

참고 URL


참고 사이트

카테고리:

업데이트:

댓글남기기