View 란 무엇인가?

  • View는 UIView의 인스턴스이거나 UIView의 하위 클래스의 인스턴스이다.
  • 자신을 어떻게 그리는지 알고 있다.
  • 터치와 같은 Event를 처리할 수 있다.
  • 뷰 계층 구조상에 존재한다.
  • View들의 Root는 Application의 Window이다.

 

프로젝트의 View Hierarchy를 보면 UIWindowScene, UIWindow, UIViewController, UIView 등이 계층적으로 생성된 걸 볼 수 있다.

 

관리

AppDelegate (~ iOS 12)

iOS 12 까지는 Window 관리를 AppDelegate에서 하였습니다.

프로젝트를 생성후에, AppDelegate에 프로퍼티로는 var window: UIWindow? 가 있었죠.

 

SceneDelegate (iOS 13 ~)

iOS 13 부터는 Window 관리를 SceneDelegate에서 합니다.

여러개의 window를 사용할 수도 있다고 합니다.

이전 App Life Cycle 포스팅에서 SceneDelegate에서는 여러개의 Scene을 사용할 수 있다고 언급했었다.

그렇다면 Window랑 Scene은 같은 개념인 것인가?

 

 

여러개의 Scene

이 상황에서는 3개의 Scene이 존재한다. 

각각의 Scene들에 대해 SceneDelegate를 통해 Life Cycle을 관리할 수 있다.

 

 

UIWindowScene

  • UIScene의 서브 클래스로 App의 하나 이상의 Window를 관리한다.
  • 직접 생성하면 안된다. 대신 configuration time에 원하는 UIWindowScene에 대해 명시하라고 한다.
    • 방법으로는 info.plist의 scene configuration details 부분에 원하는 UIWindowScene의 Class 이름을 넣으면 된다고 한다.

그림과 같이 하나의 UIWindowScene에는 여러개의 Window를 가질 수 있다.

프로퍼티로는 [UIWindow] 와 UIScreen이 있다.

또한, UISceneDelegate를 채택하는 Protocol인 UIWindowSceneDelegate가 존재한다.

우리가 프로젝트를 생성한 후, SceneDelegate 코드를 보면 UIWindowSceneDelegate Protocol을 채택한 것을 볼 수 있다.

class SceneDelegate: UIResponder, UIWindowSceneDelegate

 

 

UISceneSession

App의 Scene들 중 하나의 Scene에 대한 정보를 갖고 있는 객체이다. 그래서 내부에 scene이라는 프로퍼티가 존재한다.\

옵셔널인 이유는 scene이 session으로부터 connect/disconnect 될 수 있기 때문인 것 같다.

 

 

UIWindow

App의 UI에 대한 배경과 Event를 View에 전달하는 객체이다.

 

class UIWindow: UIView

Window들은 VC와 함께 작동하여 EVent를 처리하고, App 작업의 기본이 되는 다른 작업들을 수행한다.

사용하는 경우는 아래와 같다.

  • App의 컨텐츠를 표시할 기본 Window를 제공한다.
  • 추가 컨텐츠를 표시할 때, 필요한 경우 추가 Window를 생성한다.

쉽게 말해, UIWindow는 "액자"이고, UIView는 끼워넣는 그림/사진이다.

 

 

UIWindowScene객체를 이용해서 앱의 UI를 관리함

UIWindowScene은 UIScene을 상속받은 class이다.

-> 위에서 3개의 Scene을 가진 메모 Application인 경우, 3개의 Scene(WindowScene) 인 것 같음...

(WindowScene vs Scene 에 대한 얘기가 전혀 없다..)

 

scene은 여러개의 window들과 view controller들을 포함하며 하나의 UI의 인스턴스를 표현

 scene은 UIWindowSceneDelegate객체를 가지고 있음 (각 same memory를 공유하며 동기화)

'iOS' 카테고리의 다른 글

[iOS] UIView / 레이아웃 업데이트 관련 메소드  (0) 2021.05.24
[iOS] View LifeCycle  (0) 2021.05.24
[iOS] HitTest  (0) 2021.05.21
[iOS] Responder / Responder Chain  (0) 2021.05.21
[iOS] State Preserving/Restoring ViewControlle  (0) 2021.05.20

HitTest

이전 포스팅 Responder에 대해서 공부할 때, 잠깐 나왔던 개념이다.

 

정의는

Returns the farthest descendant of the receiver in the view hierarchy (including itself) that contains a specified point
지정된 점(point)을 포함하는 View 계층에서 리시버의 가장 먼 자손을 리턴한다.

라고 한다.

 

메소드이다.

 

point = 리시버의 bounds로 지점된 점

event = 메소드에 대한 호출을 보증하는 이벤트이다. 이벤트 처리코드 외부에서 이 메소드를 호출하는 경우에는 nil을 지정할 수 있다.

 

리턴 타입이 UIView?로 옵셔널이다.. nil이 반환될 수도 있다는 건데 -> 잠시 후에 알아보자

 

Discussion

이 메소드는 SubView의 point(inside:with:)를 호출하여 View 계층을 탐색하고, 어떤 하위 VIew가 터치 이벤트를 받아야 하는지 결정한다.

point 메소드의 파라미터는 hitTest와 같고, 반환타입만 다르다.

  • hitTest = 해당 point를 통해 리시버로부터 가장 먼 SubView를 반환
  • point = 해당 point가 리시버의 Bounds 내에 존재하는가?

point가 true를 반환하면, 하위 View 계층구조는 지정된 point를 포함하는 가장 앞에 있는 View를 찾을 때까지 재귀적으로 찾는다.

point가 false를 반환하면, View 계층 구조의 해당 분기가 무시된다.

(분기? -> hitTest는 Reverse DFS 방식으로 찾는다.)

ex) 

해당 View 계층일 때,

MainView -> View C -> View C.2 -> View C.1 -> View B ... 

순서로 찾게 된다.

 

왜? DFS면 DFS지 Reverse가 붙어?

-> iOS View 체계에서는 SubView가 SuperView보다 위(사용자에게 가까이)에 놓여진다.

-> 같은 SuperView를 가진 형제 View들의 경우에는 index가 늦은 View가 위에 놓여진다.

따라서, Reverse로 탐색할 때, hitTest가 성공한 최하단 SubView = 가장 위에 놓여진 View 가 된다.

 

 

hitTest 메소드의 동작 조건

  • hidden = false
  • alpha > 0.01
  • userInterationEnabled = true

리시버 Bounds 외부에 있는 point는 실제로 리시버 하위 View중 하나에 속하더라도, hit이 아니다.

-> Responder Chain에서의 GreenView와 같은 현상

 

hitTest 구현부

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (self.hidden || !self.userInteractionEnabled || self.alpha < 0.01 || ![self pointInside:point withEvent:event] || ![self _isAnimatedUserInteractionEnabled]) {
        return nil;
    } else {
        for (UIView *subview in [self.subviews reverseObjectEnumerator]) {
            UIView *hitView = [subview hitTest:[subview convertPoint:point fromView:self] withEvent:event];
            if (hitView) {
                return hitView;
            }
        }
        return self;
    }
}

조건문에 있듯이 hitTest의 동작 조건에 반하는 조건들이 if문에 걸려있다.

 

Why?

왜 hitTest를 알아야 하나?

Responder Chain 포스팅에서도 적었 듯

 

HitTest 테스트 포스팅

http://smnh.me/hit-testing-in-ios/

 

Hit-Testing in iOS

Hit-testing is the process of determining whether a point, such as touch-point, intersects a given graphical object, such as UIView, drawn on the screen. iOS uses hit-testing to determine which UIView is the frontmost view under the user’s finger that sh

smnh.me

 

 

 

 

 

'iOS' 카테고리의 다른 글

[iOS] View LifeCycle  (0) 2021.05.24
[iOS] UIWindowScene / UIWindow / UIView  (0) 2021.05.23
[iOS] Responder / Responder Chain  (0) 2021.05.21
[iOS] State Preserving/Restoring ViewControlle  (0) 2021.05.20
[iOS] App Life Cycle  (0) 2021.05.18

+ Recent posts