UIWindow의 역할, UINavigationController 역할, setNeedsLayout, setNeedsDisplay, UIStackView 장점과 단점, Closure

Groot·2023년 2월 23일
0

TIL

목록 보기
129/153
post-thumbnail
post-custom-banner

🌱 난 오늘 무엇을 공부했을까?

📌 면접스터디

📍 UIWindow의 역할

🔗 UIWindow 객체란?

  • 앱의 사용자 인터페이스에 대한 배경과 뷰에 이벤트를 전달하는 개체
  • @MainActor class UIWindow : UIView

🔗 특징

  • 뷰컨트롤러와 함께 작동해서 이벤트를 처리하고 앱 작동의 기본이 되는 다른 많은 작업을 수행
  • 스토리보드는 앱 대리자 객체에 window 프로퍼티가 있어야함.
    • Xcode 템플릿이 자동으로 제공
  • 앱에서 스토리보드를 사용하지 않는 경우 이 Window을 직접 만들어야 함.
  • 기본적인 window가 아닌 추가 window는 일반적으로 외부 화면에 콘텐츠를 표시하는 데 사용
  • 고유한 모양이 따로 없지만, root view controller에서 관리하는 하나이상의 뷰를 호스팅한다.
  • 인터페이스에 적합한 뷰를 추가해서 스토리보드 root view controller를 구성.
  • UIWindow를 하위 클래스로 만들 필요는 거의 없다. 왜냐하면 Window에서 구현할 수 있는 동작의 유형은 일반적으로 더 높은 수준의 뷰 컨트롤에서 쉽게 구현이 가능하기 때문에.

🔗 주요 역할

  • 일반적으로 아래의 작업을 수행해야 할 때 window를 사용
    • 앱의 콘텐츠를 표시하는 기본 Window을 제공
    • 추가 콘텐츠를 표시하려면 추가 Window(필요에 따라)을 만듬.
  • 또 다른 사용 상황
    1. 다른 Window와 비교하여 Window의 가시성에 영향을 주는 z-axis level 설정
    2. Window를 표시하고 키보드 이벤트의 대상으로 만듬.
    3. Window의 좌표계에서 좌표 값을 반환
    4. root view controller의 Window 변경
    5. Window가 표시되는 화면 변경

🔗 키보드 동작 이해

  • 터치 이벤트는 발생한 Window로 전달되지만, 해당 좌표 값이 없는 이벤트는 key window로 전달된다.
  • 한 번에 하나의 Window만 key window이 될 수 있으며 Window의 isKeyWindow 속성을 사용하여 상태를 결정
  • 어떤 Window이 핵심인지 알아야 하는 경우 didBecomeKeyNotificationdidResignKeyNotification 알림을 관찰
    • key window는 키보드 및 기타 비터치 관련 이벤트를 수신
  • 시스템은 앱의 주요 Window 변경에 대한 응답으로 이러한 알림을 보낸다.
  • Window가 key window가 되도록 강제로 정하거나, Window가 키 상태를 사임하도록 설정하려면 적절한 메서드를 호출해야함.


https://developer.apple.com/documentation/uikit/uiwindow
https://developer.apple.com/library/archive/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/WindowsandViews/WindowsandViews.html#//apple_ref/doc/uid/TP40009503-CH2-SW1

📍 UINavigationController 역할

🔗 UINavigationController란?

  • 계층으로 콘텐츠를 탐색하기 위해 스택 기반의 체계를 정의하는 컨테이너 뷰 컨트롤러
    • 컨테이너 뷰 컨트롤러 : 자체 내부에 다른 뷰 컨트롤러의 콘텐츠를 포함하는 컨트롤러
  • @MainActor class UINavigationController : UIViewController
  • 계층 구조의 각 수준에서 해당 수준의 콘텐츠를 표시하는 적절한 화면(사용자 정의 뷰 컨트롤러에서 관리)을 제공
  • 내비게이션 인터페이스에서 하나 이상의 하위 뷰 컨트롤러를 관리하는 컨테이너 뷰 컨트롤러
    • 한 번에 하나의 하위 뷰 컨트롤러만 표시
    • 뷰 컨트롤러에서 항목을 선택하면 새로운 뷰를 보여주고 이전 뷰를 숨긴다.
    • 인터페이스 상단에 있는 내비게이션 바에서 뒤로 버튼을 탭하면 상단 뷰 컨트롤러가 제거되어 아래에 있는 뷰 컨트롤러가 표시

🔗 특징

  • 내비게이션 스택이라고 하는 정렬된 배열을 사용하여 자식 뷰 컨트롤러를 관리

  • 첫번째 뷰컨이 root view controller이고 스택의 가장 아래부분임.

  • 마지막 뷰컨이 현재 표시되는 뷰 컨트롤러이고 스택의 가장 윗부분임.

  • 내비게이션 바는 항상 존재하며 내비게이션 컨트롤러 자체에서 관리하며 하위 뷰 컨트롤러에서 제공하는 콘텐츠를 사용하여 내비게이션 바를 업데이트

    • isToolbarHidden 속성이 false이면 내비게이션 컨트롤러는 최상위 뷰 컨트롤러에서 제공하는 콘텐츠로 도구 모음을 유사하게 업데이트
  • 내비게이션 컨트롤러는 대리자 개체로 동작을 조정

    • 델리게이트 객체는 뷰 컨트롤러의 푸시 또는 팝핑을 재정의하고, 사용자 정의 애니메이션 전환을 제공하고, 내비게이션 인터페이스의 기본 방향을 지정
  • 탐색 컨트롤러와 관리하는 개체 간의 관계

  • 네비게이션도 View 객체를 가지고 있다.

    • 탐색 모음, 선택적 도구 모음 및 최상위 뷰 컨트롤러에 해당하는 콘텐츠 View를 통합한 View
  • 아래 이미지는 전체 탐색 인터페이스를 표시하기 위해 이러한 View가 구성되는 방법을 보여줌
    - 내비게이션 바 및 도구 모음 뷰의 내용이 변경되더라도 View 자체는 변경되지 않음.
    - 실제로 변경되는 유일한 View는 탐색 스택의 최상위 뷰 컨트롤러에서 제공하는 사용자 지정 콘텐츠 뷰.

  • 내비게이션 바의 모양 관련 속성을 사용자 지정할 수 있지만 frame, bounds, or alpha를 직접 변경해서는 안 된다.

  • 탐색 모음의 전체 모양을 사용자 지정하려면 UIAppearance API를 사용

https://developer.apple.com/documentation/uikit/uinavigationcontroller

📍 setNeedsLayout, setNeedsDisplay

🔗 setNeedsLayout

  • layoutSubviews()를 직접 호출하면 안되기 때문에 setNeedsLayout을 호출한다.
  • 수신기의 현재 레이아웃을 무효화하고 다음 업데이트 주기 동안 레이아웃 업데이트를 트리거
    • 요청을 기록하고 즉시 반환
    • 뷰의 하위 뷰 레이아웃을 조정하려면 애플리케이션의 메인 스레드에서 이 메서드를 호출
    • 즉시 업데이트를 강제하지 않고 대신 다음 업데이트 주기를 기다리기 때문에 해당 뷰가 업데이트되기 전에 여러 뷰의 레이아웃을 무효화하는 데 사용할 수 있다.
    • 이 동작을 통해 모든 레이아웃 업데이트를 하나의 업데이트 주기로 통합할 수 있으며 이는 일반적으로 성능에 더 좋다.

🔗 setNeedsDisplay

  • draw(_ rect: CGRect)를 직접 호출하면 안되기 때문에 setNeedsDisplay를 호출해서 뷰를 다시 그려야 함을 알린다.
  • 수신자의 전체 범위 사각형을 다시 그려야 하는 것으로 표시
    • 요청을 기록하고 즉시 반환
    • 뷰의 내용을 다시 그려야 함을 시스템에 알릴 수 있다.
    • 뷰는 무효화된 모든 뷰가 업데이트되는 시점인 다음 드로잉 주기까지 실제로 다시 그려지지 않는다.
  • 뷰의 내용이나 모양이 변경될 때만 뷰를 다시 그리도록 요청하려면 이 방법을 사용해야 함.
  • 뷰의 geometry(x, y값?)만 변경하면 일반적으로 뷰가 다시 그려지지 않습니다.
  • 기존 콘텐츠를 다시 표시하면 변경되지 않은 콘텐츠를 다시 그릴 필요가 없으므로 성능이 향상

🔗 공통점

  • 즉시 업데이트가 아닌 View의 메인 런 주기에 적용된다.

🔗 차이점

  • 각각 호출하게 되는 메서드가 다름.

📍 UIStackView 장점과 단점

🔗 UIStackView란?

  • 스택뷰를 사용하면 자동 레이아웃의 기능을 활용하여 장치의 방향, 화면 크기 및 사용 가능한 공간의 모든 변경 사항에 동적으로 적응할 수 있는 사용자 인터페이스를 생성할 수 잇다.

🔗 장점

  • 스택 뷰를 사용하면 오토 레이아웃을 직접 사용하지 않고도 내용을 배치할 수 있지만, 스택 뷰 자체의 위치를 ​​지정하려면 여전히 자동 레이아웃을 사용해야 함.
  • 스택 뷰를 사용하면 새로운 뷰가 추가될 때 자동으로 조절해주기 때문에 모든 레이아웃의 변경이 필요하지 않다.

🔗 단점

  • 내부에 있는 서브뷰들의 레이아웃이 스택 뷰의 환경설정에 따라 변화되기 때문에 각각의 서브뷰들의 세밀한 레이아웃 설정 부분이 어려울 수 있다.
  • 예) 공통 space 는 8인데 나는 특정 부분만 5로 띄어주고 싶은 상황
  • vertical 방식으로 사용중인 스택뷰의 특정 서브뷰만 Horizontal 방식으로 바꾸고 싶을 때 새로운 스택 뷰를 만들어서 넣어줘야 하는 번거로움

📍 Closure

🔗 클로저란?

  • 코드 안에서 전달되어 사용할 수 있는 로직을 가진 코드의 블럭
  • 일급 객체
    • 일급 객체는 전달 인자로 보낼 수 있고, 변수와 상수 등으로 저장하거나 전달할 수 있다. 함수의 반환 값이 될 수 있다.
  • 참조 타입

🔗 특징

  • 전역 함수는 이름이 있고 값을 캡처하지 않는 클로저
  • 중첩 함수는 이름이 있고 둘러싸는 함수에서 값을 캡처할 수 있는 클로저
  • 클로저 표현식은 주변 문맥에서 값을 캡처할 수 있는 가벼운 구문으로 작성된 명명되지 않은 클로저

🔗 클로저 축약

  • 문맥에서 매개변수 및 반환 값 유형 유추
    • 문맥을 보고 매개변수나 반환 타입을 생략할 수 있다.
  • 단일 표현식 클로저의 암시적 반환
    • return 키워드의 생략.
  • 단축 인수 이름
    • 인수의 이름을 따로 정하지 않고 $0, $1과 같은 형태로 사용가능.
  • 후행 클로저
    • 클로저의 표현식이 마지막인 경우 생략하고 { } 형태로 사용가능.

🔗 클로저의 값 캡쳐

  • 클로저는 정의된 주변 컨텍스트에서 상수와 변수를 캡처할 수 있다.
  • 캡쳐 된 상수와 변수를 정의한 원래 범위가 더 이상 존재하지 않더라도 본문 내에서 해당 상수와 변수의 값을 참조하고 수정할 수 있다.
  • 클로저는 참조 타입이기 때문에 클로저가 참조타입을 캡쳐할 때 그 참조타입이 클로저를 참조한다면 강한 순환참조가 생겨서 메모리 릭이 발생한다.

🔗 클로저의 탈출

  • 클로저를 매개 변수 중 하나로 사용하는 함수를 선언할 때 매개 변수의 유형 앞에 @escaping을 작성하여 클로저가 탈출할 수 있음을 나타낼 수 있다
  • 클로저가 탈출할 수 있는 한 가지 방법은 함수 외부에 정의된 변수에 저장되는 것
  • 비동기 처리에서 많이 사용된다.
    • 그 이유는 함수가 종료 된 뒤에 실행되는 비동기 처리의 실행을 보장해야 하기 때문에
  • self가 클래스의 인스턴스를 참조하는 경우 이스케이프 클로저에서 self를 캡처하면 강력한 참조 순환을 쉽게 만들 수 있다.
  • 이스케이프 클로저는 self가 구조체나 열거형의 인스턴스일 때 self에 대한 변경 가능한 참조를 캡처할 수 없다.
    • 값 유형은 공유 가변성을 허용하지 않는다.

🔗 자동클로저

  • 함수에 인수로 전달되는 표현식을 래핑하기 위해 자동으로 생성되는 클로저

    var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
    print(customersInLine.count)
    // Prints "5"
    
    let customerProvider = { customersInLine.remove(at: 0) }
    print(customersInLine.count)
    // Prints "5"
    
    print("Now serving \(customerProvider())!")
    // Prints "Now serving Chris!"
    print(customersInLine.count)
    // Prints "4"
  • 자동 클로저는 클로저를 호출할 때까지 내부 코드가 실행되지 않기 때문에 지연이 가능하다.

  • 지연 평가는 코드 평가 시기를 제어할 수 있기 때문에 부작용이 있거나 계산 비용이 많이 드는 코드에 유용하다.

profile
I Am Groot
post-custom-banner

0개의 댓글