안녕하세요 주니오스입니다~! ✋

 

 

기본적으로 제공되는 frame프로퍼티의 경우 부모 좌표공간을 기준으로 현재 뷰의 위치를 알려줍니다.

 

(bounds의 경우 자신의 좌표 공간에서의 위치를 의미합니다.)

 

하지만 개발을 하다보면 특정 뷰의 위치(frame)를 특정 뷰를 기준으로 알고싶은 경우가 있습니다.

 

이때 사용할 수 있는 UIVIew의 인스턴스 매서드가 바로 convert입니다.

 

이번 글에서는 해당 매서드의 사용법에 대해 다뤄보려고 합니다.

 

공식 문서를 들어가 보면 총 3가지 매서드가 존재합니다.

https://developer.apple.com/documentation/uikit/uiview/1622442-convert

 

하지만 설명만 읽어서는 사실상 기능에 대한 파악이 힘듭니다.

 

convert(CGRect, to: UIView)

먼저 to매개변수가 존재하는 매서드부터 살펴보겠습니다.

 

먼저 해당 매서드를 호출하기 위해선 3가지 객체가 필요합니다.

 

1. convert매서드를 호출하는 호출 뷰

2. CGRect값

3. to에 전달된 UIView

 

CGRect가 대뜸 왜 등장하는 것인지 의문이 드실 수 있습니다. 🤔

 

모든 뷰들의 위치는 아시다시피 CGRect로 표현됩니다. (frame, bounds)

 

그리고 CGRect는 특정 기준 좌표계 내에서의 뷰의 크기(size)와 좌표(origin)를 가집니다.

 

여기서 기준 좌표계가 되는 것이 바로 1번, convert매서드를 호출하는 뷰입니다. 🙌

 

class ViewController: UIViewController {
    
    let testSuperView: UIView = {
        
        let superView = UIView()
        
        superView.frame = CGRect(origin: .zero, size: CGSize(width: 200, height: 200))
        superView.backgroundColor = .cyan
        
        return superView
    }()
    
    let testSubView: UIView = {
        
        let subView = UIView()
        
        subView.frame = CGRect(origin: CGPoint(x: 50, y: 50), size: CGSize(width: 100, height: 100))
        subView.backgroundColor = .black
        subView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        
        return subView
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        testSuperView.center = view.center
        view.addSubview(testSuperView)
        
        testSuperView.addSubview(testSubView)
        
        
    }
}

 

 

위 코드에서 testSubViewtestSuperView의 자식 클래스입니다.

 

그렇다면 testSubView.frame은 testSuperView좌표계를 기준으로한 testSubView위치라고 표현할 수 있습니다.

 

그렇다면 testSubView의 특정 좌표계를 기준으로한 CGRect값을 알고싶다면 아래 코드와 처럼 표현할 수 있는겁니다! 🤗

 

testSuperView.convert(testSubView.frame, to: (서브뷰의 기준좌표계가될 뷰))

 

해당 매서드는 CGRect를 반환합니다. 바로 testSubView의 CGRect이지요(to에 전달한 뷰에 대한).

 

뷰모뷰가 해당 매서드 호출에 개입된 이유는 자식뷰의 위치를 단지 특정하기 위해서일 뿐입니다.

 

bounds의 경우 자신의 좌표계를 기준으로한 현재 뷰의 위치입니다.

 

따라서 아래 코드도 동일한 값을 반환합니다.

 

testSubView.convert(testSubView.bounds, to: (서브뷰의 기준좌표계가될 뷰))

 

 

한가지 팁이 있는데요 👆

 

만약 to 매개변수에 nil값을 전달하는 경우 현재 window를 기준 좌표계로한 CGRect값을 얻으실 수 있습니다!

 

특정 뷰의 절대좌표를 얻을 수 있는 것이지요! 🥹

 

 

다음으로 from매개변수를 전달받는 경우입니다.

 

convert(CGRect, from: UIView)

이 매서드는 앞서다룬 매서드와 크게 다르지 않습니다.

 

역시 3가지 객체들이 필요합니다.

 

1. convert매서드를 호출하는 호출 뷰

2. CGRect값

3. from에 전달된 UIView

 

이 매서드는 CGRect값의 기준좌표계가 되는 뷰가 from매개변수로 전달됩니다.

 

앞서 제시한 코드를 다시 사용해 보겠습니다.

 

똑같이 testSubView의 특정 뷰의 좌표계를 기준으로한 CGRect값을 구해보겠습니다.

 

(서브뷰의 기준좌표계가될 뷰).convert(testSubView.frame, from: testSuperView)

 

아래 코드역시 동일한 동작을 수행합니다!

(서브뷰의 기준좌표계가될 뷰).convert(testSubView.bounds, from: testSubView)

 

🤗

 

활용

 

이것을 어떻게 활용할 수 있을까요?

 

저는 특정 뷰영역에 특정 뷰가 특정뷰의 영역과 겹치는 지 판단하는 로직을 한번 구성해 보았습니다.

 

// tableView를 기준으로한 Cell의 프레임을 detectAreat뷰의 좌표계로부터의 프레임
let frameFromDetactArea = tableView.convert(tableViewCell.frame, to: detectArea)

let isInside = (frameFromDetactArea.origin.y+frameFromDetactArea.height) >= 0 && frameFromDetactArea.origin.y <= detectArea.bounds.height
tableViewCell.onStateChange?(isInside)

 

아래 영상에 옅은 회색부분(잘안보이지만 중앙에 존재합니다. 😓)으로 표시된 영역이 detectArea입니다.

 

각각의 셀들은 위코드를 통해 현재 자신이 detectArea안인지 판단합니다.

 

뷰가 겹치는 지 확인

 

전체 코드입니다 🙌

 

 

[RxSwift+MVVM] 특정 뷰에속할 경우 상태가 변경되는 UITableViewCell입니다.

[RxSwift+MVVM] 특정 뷰에속할 경우 상태가 변경되는 UITableViewCell입니다. - Model.swift

gist.github.com

 

 

 

자 오늘은 convert를 사용해 보았습니다.

 

해당 매서드를 공부하며 특정 뷰의 위치및 크기를 표현하기 위해선 기준 좌표계가 필요하다는 것을 다시한번 상기할 수 있었습니다.

 

감사합니다~! ✋✋

 

 

 

 

convert를 활용한 다른 예시입니다!

 

버튼을 누르고 있을때만 표시되는 나만의 Alert 창 만들기

안녕하세요. WindowHyeok입니다. 오늘은 제목 그대로 특정 버튼을 누르고 있을때만 화면에 나타나는 커스텀 Alert창을 만들어 보려고 합니다. 회사 디자인팀에 요구에 따라 저는 버튼을 누르고 있을

velog.io