ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [iOS] μœˆλ„μš°λž€? (feat. UIWindow)
    iOS/πŸ€– App 2021. 7. 5. 17:43

    μ•ˆλ…•ν•˜μ„Έμš”πŸΆ

     

    이번 μ‹œκ°„μ—λŠ” μœˆλ„μš°μ— λŒ€ν•΄μ„œ κ³΅λΆ€ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

     

    μœˆλ„μš°λŠ” UIWindow 였브젝트λ₯Ό κ°€λ¦¬ν‚€λŠ” λ§μΈλ°μš”.

     

     

     

    μœˆλ„μš°λΌλŠ” κ°œλ…μ΄ ν•„μš”ν•˜κΈ° μ‹œμž‘ν•  λ•ŒλŠ” μ•„λ§ˆ μŠ€ν† λ¦¬λ³΄λ“œ 없이 UIλ₯Ό 처음 μ½”λ“œλ‘œ κ΅¬ν˜„ν•΄λ³Ό λ•Œ 일 것 κ°™μ•„μš”.

     

     

    이 κΈ€μ—μ„œλŠ” μ–Έμ œ 직접 μœˆλ„μš°λ₯Ό μƒμ„±ν•΄μ•Όλ˜λŠ”μ§€μ— λŒ€ν•΄μ„œλ„ λ‹€λ£¨μ—ˆμŠ΅λ‹ˆλ‹€.

     

    두 개의 κ³΅μ‹λ¬Έμ„œλ₯Ό μ’…ν•©ν•΄μ„œ μ •λ¦¬ν•˜λ‹€λ³΄λ‹ˆ λ‚΄μš©μ΄ μ’€ λ§Žμ•„μ§„ 것 κ°™λ„€μš”.

     

     

    μš”μ•½ ν•΄λ³΄μžλ©΄

    μœˆλ„μš°λŠ” 뷰듀을 λ‹΄λŠ” μ»¨ν…Œμ΄λ„ˆμ΄λ‹€.

     

    μœˆλ„μš°λŠ” 이벀트λ₯Ό μ „λ‹¬ν•΄μ£ΌλŠ” λ§€κ°œμ²΄μ΄λ‹€.

     

    iOS 앱은 μ½˜ν…μΈ λ₯Ό 화면에 보여주기 μœ„ν•΄μ„œ μ΅œμ†Œ 1개 μ΄μƒμ˜ μœˆλ„μš°λ₯Ό 가지고 μžˆλ‹€. (보톡 1개)

     

    μ‹œμŠ€ν…œ μœˆλ„μš°μ—μ„œ μƒμ„±λœ μ΄λ²€νŠΈλ“€μ€ Key Window 둜 전달이 λœλ‹€.

     

     

     

    이 κΈ€μ—λŠ” μ—†λŠ” 것

    External Display 에 κ΄€λ ¨λœ λ‚΄μš©

     

     

    그럼 μ‹œμž‘ν•΄λ³Όκ²Œμš”!!!πŸ”₯


     

    μ •μ˜

    μ•± UI 의 배경막 역할을 ν•˜κ³  뷰에 이벀트λ₯Ό μ „λ‹¬ν•˜λŠ” 였브젝트

     

    μš°μ„  μ•Œμ•„μ•Όν•  점은 UIWinodw 도 UIView 의 μ„œλΈŒν΄λž˜μŠ€λΌλŠ” κ²ƒμž…λ‹ˆλ‹€.

     

    그런데 UIView λŠ” UIResponder 의 μ„œλΈŒν΄λž˜μŠ€μ΄μ£ ?

     

    이벀트λ₯Ό μ²˜λ¦¬ν•˜λŠ” λ¦¬μŠ€ν°λ” 체인(Responder Chain) μ—λŠ” UIWindow κ°€ 항상 ν¬ν•¨λ©λ‹ˆλ‹€.

     

    μ΄λΆ€λΆ„μ—μ„œ '뷰에 이벀트λ₯Ό μ „λ‹¬ν•˜λŠ”' μ΄λΌλŠ” 역할이 μˆ˜ν–‰λ˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

     

    @MainActor λΌλŠ” μ–΄νŠΈλ¦¬λ·°νŠΈλŠ” Swift 5.5 λΆ€ν„° λ„μž…λ˜λŠ” κ°œλ…μœΌλ‘œ, 메인 μ“°λ ˆλ“œμ—μ„œ μ‹€ν–‰λ˜λŠ” ν΄λž˜μŠ€μž„μ„ κ°€λ¦¬ν‚΅λ‹ˆλ‹€.

     

    아직 베타 ν…ŒμŠ€νŠΈ 쀑이고 μ£Όμ œμ™€ λ²—μ–΄λ‚˜λ―€λ‘œ, λ‹€μŒμ— λ‹€λ£¨μ–΄λ³΄λŠ”κ²Œ 쒋을 것 κ°™μŠ΅λ‹ˆλ‹€.


     

    κ°œμš”

     

    UIWindow λŠ” 제일 밑에 μžˆλ„€...

     

     

    μš°μ„  그림에 λŒ€ν•΄μ„œ κ°„λ‹¨νžˆ 보자면, μœ„μ˜ μ •μ˜λŒ€λ‘œ UIWindow λŠ” λ·°λ“€ κ°€μž₯ λ’€μ—μ„œ 배경막 역할을 ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

     

    " κ·Έ μ˜†μ˜ Core Animation layers λ₯Ό 보면, λ ˆμ΄μ–΄λŠ” 뷰와 1 : 1 κ΄€κ³„λ‘œ ν‘œν˜„λ˜μ–΄ μžˆλŠ” μ˜€λΈŒμ νŠΈλ“€μž…λ‹ˆλ‹€.

    iOSμ—μ„œ λͺ¨λ“  뷰듀은 layer-backed λ·°λΌλŠ” 점과 관련이 μžˆλŠ”λ°μš”.

    κ΄€λ ¨λœ 글은 CALayer 에 λŒ€ν•΄μ„œ μ •λ¦¬ν•œ 이 글을 μ°Έκ³ ν•΄μ£Όμ„Έμš”! "

     

     

    λͺ¨λ“  iOS 앱은 적어도 ν•œ 개 μ΄μƒμ˜ μœˆλ„μš°λ₯Ό 가지고 μžˆμŠ΅λ‹ˆλ‹€.

     

    μ—¬κΈ°μ„œ μœˆλ„μš°λž€ UIWindow 였브젝트λ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€.

     

    iOS μ—μ„œ μœˆλ„μš° μžμ²΄λŠ” μ‹œμž‘μ μΈ μš”μ†Œλ₯Ό μ „ν˜€ ν¬ν•¨ν•˜κ³  μžˆμ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

     

    μœˆλ„μš°λŠ” κ·Έμ € ν•œ 개 μ΄μƒμ˜ λ·°λ₯Ό 포함할 수 μžˆλŠ” λΉ„μ–΄μžˆλŠ” μ»¨ν…Œμ΄λ„ˆ μž…λ‹ˆλ‹€.

    ( 그리고 μƒˆλ‘œμš΄ μ½˜ν…μΈ λ₯Ό 보여주기 μœ„ν•΄μ„œ μœˆλ„μš°λ₯Ό κ΅μ²΄ν•˜λŠ” λŒ€μ‹ , λ·°λ₯Ό κ΅μ²΄ν•©λ‹ˆλ‹€ )

     

    μœˆλ„μš° μžμ²΄λŠ” μ‹œκ°μ μΈ ν‘œν˜„μ„ ν¬ν•¨ν•˜μ§€ μ•ŠλŠ”λ‹€

     


    🟒 μœˆλ„μš°λŠ” λ‹€μŒκ³Ό 같은 μ±…μž„μ„ 가지고 μžˆμŠ΅λ‹ˆλ‹€:

     

    앱이 λ³΄μ—¬μ£ΌλŠ” μ½˜ν…μΈ λ“€μ„ ν¬ν•¨ν•˜λŠ” 역할을 ν•©λ‹ˆλ‹€.

     

    λ·°λ₯Ό ν¬ν•¨ν•œ λ‹€λ₯Έ μ•± λ‚΄ μ˜€λΈŒμ νŠΈλ“€μ—κ²Œ 이벀트λ₯Ό μ „λ‹¬ν•΄μ£ΌλŠ” 핡심적인 역할을 ν•©λ‹ˆλ‹€.

     

    μ•±μ˜ λ·° μ»¨νŠΈλ‘€λŸ¬μ™€ ν™”λ©΄ λ°©ν–₯μ „ν™˜ ( landscape & portrait ) 을 μš©μ΄ν•˜κ²Œ ν•˜κΈ° μœ„ν•΄ ν˜‘μ—…ν•©λ‹ˆλ‹€.


     

    μœˆλ„μš°λŠ” λ·° μ»¨νŠΈλ‘€λŸ¬μ™€ ν•¨κ»˜ λ™μž‘ν•˜λ©΄μ„œ 이벀트λ₯Ό ν•Έλ“€λ§ν•˜κ³  μ•±μ˜ λ™μž‘μ— ν•„μˆ˜μ μΈ μž‘μ—…λ“€μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.

     

    UIKit 은 μ•±μ˜ λ™μž‘ κ΅¬ν˜„μ΄ ν•„μš”ν•  λ•Œ

    λ‹€λ₯Έ μ˜€λΈŒμ νŠΈλ“€κ³Ό 같이 ν˜‘λ™ν•˜λ©΄μ„œ λŒ€λΆ€λΆ„μ˜ μœˆλ„μš° κ΄€λ ¨ μƒν˜Έμž‘μš© (window-related interactions) 듀을 μ²˜λ¦¬ν•©λ‹ˆλ‹€.

     

     


    🟒 μš°λ¦¬λŠ” λ‹€μŒ 두 가지 κ²½μš°μ— μœˆλ„μš°λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€:

     

    μ•±μ˜ μ½˜ν…μΈ λ₯Ό 화면에 보여주기 μœ„ν•˜μ—¬ Main window λ₯Ό μ œκ³΅ν•΄μ•Όν•  λ•Œ

     

    좔가적인 μ½˜ν…μΈ λ₯Ό 보여주기 μœ„ν•΄ 좔가적인 window λ₯Ό 생성해야 ν•  λ•Œ (external display λ₯Ό μ‚¬μš©ν•  경우)


     

    External Display λ₯Ό μ‚¬μš©ν•˜μ—¬ Window 의 κ°œμˆ˜κ°€ 2κ°œκ°€ 된 상황

     

    μœˆλ„μš°λ₯Ό μƒμ„±ν•˜κ³  μ„€μ •ν•˜λŠ” 방식은 μ½”λ“œλ‘œ μƒμ„±ν•˜κΈ° ν˜Ήμ€ μΈν„°νŽ˜μ΄μŠ€ λΉŒλ”λ₯Ό μ‚¬μš©ν•˜κΈ° 두 가지가 μžˆμŠ΅λ‹ˆλ‹€.

     

    μŠ€ν† λ¦¬λ³΄λ“œ 방식(μΈν„°νŽ˜μ΄μŠ€ λΉŒλ”λ₯Ό 이용) 으둜 iOS ν”„λ‘œμ νŠΈλ₯Ό κ΅¬μ„±ν•œλ‹€κ³  κ°€μ •ν•΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

     

     

    이 경우, Xcode λŠ” μ•±μ˜ 메인 μœˆλ„μš° λ₯Ό μžλ™μœΌλ‘œ μ œκ³΅ν•©λ‹ˆλ‹€.

     

    μŠ€ν† λ¦¬λ³΄λ“œλŠ” AppDelegate 였브젝트의 window 속성이 UIWindow 였브젝트둜 μ΄ˆκΈ°ν™” λ˜μ–΄μžˆμ–΄μ•Ό μ œλŒ€λ‘œ μž‘λ™ν•©λ‹ˆλ‹€.

     

    단, SceneDelegate κ°œλ…μ΄ λ“±μž₯ν•œ μ΄ν›„μ—λŠ” SceneDelegate μ˜€λΈŒμ νŠΈκ°€ window 속성을 가지고 μžˆμŠ΅λ‹ˆλ‹€.

     

     

    μœ„μ™€ 같이 SceneDelegate μ—μ„œ window λŠ” Optional<UIWindow> 둜 μ„ μ–Έλ˜μ–΄ μžˆμ§€λ§Œ,

    window 속성을 μ‚¬μš©ν•  μ‹œμ μ—λŠ” μ œλŒ€λ‘œ μ΄ˆκΈ°ν™” λ˜μ–΄μžˆμŒμ„ 보μž₯ν•©λ‹ˆλ‹€.

     

    Xcode κ°€ μžλ™μœΌλ‘œ μ΄ˆκΈ°ν™”μ‹œν‚€κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

     

    λ§Œμ•½ μŠ€ν† λ¦¬ λ³΄λ“œλ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šκ³  μ½”λ“œλ‘œ UI λ₯Ό κ΅¬μ„±ν•œλ‹€λ©΄, μœˆλ„μš°λ₯Ό 직접 μƒμ„±ν•΄μ•Όν•©λ‹ˆλ‹€.

     

     

    정리λ₯Ό ν•˜μžλ©΄ μœˆλ„μš° 생성을 κ³ λ €ν•΄μ•Όν•  4가지 κ²½μš°κ°€ μƒκΉλ‹ˆλ‹€.πŸ‘‡πŸ»πŸ‘‡πŸ»πŸ‘‡πŸ»


     

    iOS 12 버전 μ΄ν•˜ ν˜Ήμ€ AppDelegate 만 μ‚¬μš©ν•  경우

    a. Storyboard λ₯Ό μ‚¬μš©ν•  λ•Œ

    μœ„μ—μ„œ μ–ΈκΈ‰ν•œλŒ€λ‘œ window 속성이 μ œλŒ€λ‘œ μ΄ˆκΈ°ν™” λ©λ‹ˆλ‹€. λ”°λ‘œ 생성해쀄 ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€.

     

    b. UI λ₯Ό Programmatically ν•˜κ²Œ ꡬ성할 λ•Œ ( Storyboard λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šμ„λ•Œ )

    window κ°€ λ”°λ‘œ μ΄ˆκΈ°ν™”λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

    AppDelegate 의 didFinishWithLaunchingOptions: μ—μ„œ UIWindow() λ“±μœΌλ‘œ

    μƒμ„±ν•΄μ„œ 속성을 μ΄ˆκΈ°ν™” ν•΄μ£Όμ–΄μ•Ό ν•©λ‹ˆλ‹€.

     

     

    iOS 13 버전 이상 SceneDelegate λ₯Ό μ‚¬μš©ν•  λ•Œ

    (iOS 13 버전 μ΄μƒμ—μ„œλŠ” AppDelegate 와 SceneDelegate λ₯Ό λͺ¨λ‘ μ‚¬μš©ν•˜μ§€λ§Œ window 에 μ΄ˆμ μ„ λ§žμΆ”κ³  μƒκ°ν•΄λ³΄μ•˜μŠ΅λ‹ˆλ‹€.)

     

    a. Storyboard λ₯Ό μ‚¬μš©ν•  λ•Œ = 생성할 ν•„μš” ❌

     

    b. UI λ₯Ό Programmatically ν•˜κ²Œ ꡬ성할 λ•Œ ( Storyboard λ₯Ό μ‚¬μš©ν•˜μ§€ μ•Šμ„λ•Œ )

    SceneDelegate 의 willConnectTo: λ©”μ„œλ“œμ—μ„œ 직접 생성 ( 이 링크 μ°Έμ‘° )

     

    // scene(willConnectTo:options:) λ©”μ„œλ“œ λ‚΄λΆ€μ—μ„œ // 두 생성 λ°©μ‹μ˜ μ°¨μ΄λŠ”????? UIWindow(frame: UIScreen.main.bounds) UIWindow(frame: windowScene.coordinateSpace.bounds)

     

    앱이 싀행될 λ•ŒλŠ” μ–΄λ–€ μƒνƒœλ‘œ μ‹€ν–‰λ˜λŠ” κ²ƒκ³ΌλŠ” 상관 없이 메인 μœˆλ„μš°λŠ” 항상 μƒμ„±λ˜μ–΄μ•Ό ν•©λ‹ˆλ‹€.

     

    μœˆλ„μš°λ₯Ό μƒμ„±ν•˜κ³  μ„€μ •ν•˜λŠ” μž‘μ—… μžμ²΄λŠ” κ³ λΉ„μš©μ˜ μž‘μ—…μ΄ μ•„λ‹™λ‹ˆλ‹€.

     

    ν•˜μ§€λ§Œ background 둜 μ‹€ν–‰ 될 경우, μœˆλ„μš°λ₯Ό 'visible' ν•˜κ²Œ ν•˜λŠ” 것은 ν”Όν•΄μ•Όν•©λ‹ˆλ‹€.

     


    🟒 μœˆλ„μš°(UIWindow) 였브젝트λ₯Ό 톡해 λ‹€μŒκ³Ό 같은 μž‘μ—…λ„ ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

     

    μœˆλ„μš°μ˜ z μΆ• μ’Œν‘œλ₯Ό μ„€μ •ν•˜μ—¬, λ‹€λ₯Έ μœˆλ„μš°μ˜ 관계에 따라 λ³΄μ΄λŠ” 정도λ₯Ό μ‘°μ ˆν•  수 μžˆμŠ΅λ‹ˆλ‹€ (λ·° 계측과 μœ μ‚¬)

     

    μœˆλ„μš°λ₯Ό 보여주고, ν‚€λ³΄λ“œ 이벀트의 νƒ€κ²ŸμœΌλ‘œ μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

     

    μœˆλ„μš° μ’Œν‘œ μ‹œμŠ€ν…œμ˜ μ’Œν‘œλ₯Ό λ³€ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

     

    μœˆλ„μš°μ˜ Root ViewController λ₯Ό λ³€κ²½ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

     

    μœˆλ„μš°κ°€ ν‘œμ‹œλ˜κ³  μžˆλŠ” (κΈ°κΈ°)μŠ€ν¬λ¦°μ„ λ³€κ²½ν•  수 μžˆμŠ΅λ‹ˆλ‹€.


     

    μœˆλ„μš°λŠ” 그것 자체둜 μ–΄λ– ν•œ μ‹œκ°μ μΈ ν‘œν˜„λ¬Όμ„ 가지고 μžˆμ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

    (μœ„μ˜ κΈ€ λ‚΄μš©μ—μ„œλ„ λ‚˜μ™”μŠ΅λ‹ˆλ‹€. μœˆλ„μš°λŠ” λ·°λ₯Ό 포함할 수 μžˆλŠ” λΉ„μ–΄μžˆλŠ” μ»¨ν…Œμ΄λ„ˆλ‹€!!!!!!!!!)

     

    λŒ€μ‹ μ— μœˆλ„μš°λŠ” ν•œ 개 μ΄μƒμ˜ λ·°λ₯Ό μƒμ£Όμ‹œν‚€κ³  μžˆλŠ”λ°,

    이 뷰듀은 μœˆλ„μš°μ˜ Root ViewController 에 μ˜ν•΄ κ΄€λ¦¬λ˜λŠ” κ²ƒλ“€μž…λ‹ˆλ‹€.

     

    UIWindow λ₯Ό μ„œλΈŒν΄λž˜μ‹±ν•  일은 거의 μ—†μŠ΅λ‹ˆλ‹€.

     

    μœˆλ„μš°μ—μ„œ κ΅¬ν˜„ν•˜κ³  μ‹Άμ–΄ν• λ²•ν•œ λ™μž‘λ“€μ€ 더 μœ—-레벨인 λ·° μ»¨νŠΈλ‘€λŸ¬μ—μ„œ 보톡 더 μ‰½κ²Œ κ΅¬ν˜„ν• μˆ˜ μžˆμŠ΅λ‹ˆλ‹€.

     

    거의 μΌμ–΄λ‚˜μ§€ μ•Šμ„ μΌμ΄μ§€λ§Œ μ„œλΈŒν΄λž˜μ‹±μ„ ν•œλ‹€λ©΄, becomeKey() λ‚˜ resignKey() λ₯Ό μ˜€λ²„λΌμ΄λ”©ν•˜μ—¬ μœˆλ„μš°μ˜ ν‚€ μƒνƒœκ°€ 변경될 λ•Œ μ»€μŠ€ν…€ν•œ λ™μž‘μ„ κ΅¬ν˜„ν•˜κ³  싢을 경우일 κ²ƒμž…λ‹ˆλ‹€.

     

    μœˆλ„μš°κ°€ ν‘œμ‹œλ  μŠ€ν¬λ¦°μ„ ꡬ체적으둜 μ •ν•˜λŠ” 방법에 λŒ€ν•΄μ„œλŠ” UIScreen λ¬Έμ„œλ₯Ό ν•œλ²ˆ μ‚΄νŽ΄λ³΄λŠ”κ²ƒμ΄ 쒋을 것 κ°™μŠ΅λ‹ˆλ‹€.


     

    Understanding Keyboard Interactions

     

    ν„°μΉ˜ 이벀트의 경우 μ΄λ²€νŠΈκ°€ λ°œμƒν•œ μœˆλ„μš°μ— 직접 전달이 λ©λ‹ˆλ‹€.

    그런데 κ΄€λ ¨ μ’Œν‘œκ°’μ΄ μ—†λŠ” 이벀트 같은 κ²½μš°μ—λŠ” ν‚€ μœˆλ„μš° (Key Window) 둜 전달 λ©λ‹ˆλ‹€.

     

    그런데 κ΄€λ ¨ μ’Œν‘œκ°’μ΄ μ—†λŠ” μ΄λ²€νŠΈλŠ” μ–΄λ–€ μ΄λ²€νŠΈμΌκΉŒμš”?????

    μ‹œμŠ€ν…œμ΄ μƒμ„±ν•œ μœˆλ„μš°μ—μ„œ μƒμ„±λœ 이벀트λ₯Ό κ°€λ¦¬ν‚€λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€.

    가상 ν‚€λ³΄λ“œ 창을 화면에 λ„μšΈ λ•Œ μƒˆλ‘œ μΆ”κ°€λ˜λŠ” μœˆλ„μš° 쀑 ν•˜λ‚˜

     

    예λ₯Ό λ“€μ–΄ 가상 ν‚€λ³΄λ“œ 창은 μ‹œμŠ€ν…œμ΄ μƒμ„±ν•œ μœˆλ„μš°μž…λ‹ˆλ‹€.

    ν‚€λ³΄λ“œ μ°½μ—μ„œ κΈ€μžλ₯Ό μž…λ ₯ν•  λ•Œ λ°œμƒν•˜λŠ” μ΄λ²€νŠΈλ“€μ€ μ•±μ˜ ν‚€ μœˆλ„μš°λ‘œ 전달이 λ©λ‹ˆλ‹€.

    μ—¬κΈ°μ„œ UIInputView λΌλŠ” κ°œλ…μ΄ λ“±μž₯ν•˜λŠ”λ°, 곡뢀해봐야할 것 κ°™μŠ΅λ‹ˆλ‹€.

     

    ν•˜λ‚˜μ˜ μ‹œμ μ—λŠ” 였직 ν•œ 개의 μœˆλ„μš°λ§Œμ΄ ν‚€ μœˆλ„μš°κ°€ 될 수 μžˆμŠ΅λ‹ˆλ‹€.

     

    ν‚€ μœˆλ„μš°λŠ” isKeyWindow λΌλŠ” 속성을 톡해 κ²°μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

     

    μ•±μ—μ„œ External Display κ°€ μ—†λŠ” 경우 μœˆλ„μš°λŠ” 1개이기 λ•Œλ¬Έμ—

    λŒ€λΆ€λΆ„μ˜ 경우, μ•±μ˜ 메인 μœˆλ„μš°κ°€ ν‚€ μœˆλ„μš°μž…λ‹ˆλ‹€.

     

    ν•˜μ§€λ§Œ UIKit 은 ν•„μš”ν•  경우 λ‹€λ₯Έ μœˆλ„μš°λ₯Ό ν‚€ μœˆλ„μš°λ‘œ μ§€μ •ν•˜κΈ°λ„ ν•©λ‹ˆλ‹€.

     

    λ§Œμ•½ μ–΄λ–€ μœˆλ„μš°κ°€ ν‚€ μœˆλ„μš°μΈμ§€ μ•Œκ³  μ‹Άλ‹€λ©΄,

    didBecomeKeyNotification μ΄λ‚˜ didResignKeyNotification λ…Έν‹°λ₯Ό μ˜΅μ €λΉ™ν•΄ λ³΄μ„Έμš”.

    ( 확인 μ „μ—λŠ” ν‚€λ³΄λ“œμ°½μ΄ 뜨면 μ•± 메인 μœˆλ„μš°κ°€ KeyWindow κ°€ μ•„λ‹ˆκ²Œ λ˜κ² κ΅¬λ‚˜ 라고 μƒκ°ν–ˆλŠ”λ°,

    κ·ΈλŒ€λ‘œ KeyWindow μ˜€μŠ΅λ‹ˆλ‹€.

    κ·Έλž˜μ„œ ν‚€λ³΄λ“œ μœˆλ„μš°μ—μ„œ λ°œμƒν•œ μ΄λ²€νŠΈλŠ” KeyWindow 인 메인 μœˆλ„μš°λ‘œ μ „λ‹¬λ©λ‹ˆλ‹€!!)

     

    μ‹œμŠ€ν…œμ΄ μ•±μ˜ ν‚€ μœˆλ„μš°κ°€ 변경될 λ•Œ μœ„μ˜ λ…Έν‹°λ₯Ό λΏŒλ €μ€λ‹ˆλ‹€

     

    μ–΄λ–€ μœˆλ„μš°λ₯Ό ν‚€ μœˆλ„μš°λ‘œ κ°•μ œν•˜κ±°λ‚˜, ν‚€ μœˆλ„μš°λ₯Ό ν•΄μ œμ‹œν‚€κ³  μ‹Άλ‹€λ©΄ 이 클래슀의 μ μ ˆν•œ λ©”μ„œλ“œλ₯Ό μ°Ύμ•„μ„œ ν˜ΈμΆœν•˜μ„Έμš”.

     

    makeKey(), resignKey() λ₯Ό 가리킀고 μžˆμŠ΅λ‹ˆλ‹€.

     


     

    Changing the Window Level

     

    각각의 UIWindow μ˜€λΈŒμ νŠΈλŠ” μ„€μ • κ°€λŠ₯ν•œ windowLevel 속성이 μžˆμŠ΅λ‹ˆλ‹€. (μˆ˜μ •μ΄ κ°€λŠ₯함)

     

    이 속성값은 z μΆ• μ’Œν‘œ 값을 λ‚˜νƒ€λ‚΄λŠ” κ²ƒμž…λ‹ˆλ‹€.

     

    이 속성을 톡해 λ‹€λ₯Έ μœˆλ„μš°μ™€ λΉ„κ΅ν•˜μ—¬ μžμ‹ μ˜ μœ„μΉ˜λ₯Ό κ²°μ •ν•©λ‹ˆλ‹€.

     

    이 속성은 UIWindow.Level νƒ€μž…μ΄λ©°, 같은 레벨의 μœˆλ„μš°λŠ” λ‹€λ₯Έ 레벨의 μœˆλ„μš°λ³΄λ‹€ μ•ž ν˜Ήμ€ λ’€μͺ½μ— λ‚˜νƒ€λ‚©λ‹ˆλ‹€.

     

    그런데 같은 레벨 μ•ˆμ—μ„œμ˜ μœˆλ„μš° μˆœμ„œλŠ” 보μž₯λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

     

    μœˆλ„μš° 레벨의 κΈ°λ³Έ 값은 normal μž…λ‹ˆλ‹€.

     

    λŒ€λΆ€λΆ„μ˜ κ²½μš°λŠ” μ•±μ˜ μœˆλ„μš°λ“€μ˜ λ ˆλ²¨μ„ λ³€κ²½ν•  ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€.

     

    μƒˆλ‘œ μƒμ„±λœ μœˆλ„μš°λ“€μ€ 생성과 λ™μ‹œμ— normal 레벨둜 μ„€μ •λ©λ‹ˆλ‹€.

     

    normal μœˆλ„μš°λŠ” μ•±κ³Ό κ΄€λ ¨λœ μ½˜ν…μΈ λ₯Ό ν‘œμ‹œν•˜λŠ” μœˆλ„μš°μž„μ„ κ°€λ¦¬ν‚΅λ‹ˆλ‹€.

     

    더 높은 레벨의 μœˆλ„μš°λŠ” μ•± μ½˜ν…μΈ  μœ„μ— λ– μ•Όλ§Œν•˜λŠ” 정보λ₯Ό ν‘œμ‹œν•˜κΈ°μœ„ν•΄ 남겨둔 것 μž…λ‹ˆλ‹€.

     

    예λ₯Ό λ“€μ–΄ μ‹œμŠ€ν…œ μƒνƒœ λ°” (system status bar) ν˜Ήμ€ κ²½κ³  μ°½ (alert messages) κ°€ μžˆμŠ΅λ‹ˆλ‹€.

     

    κ·Έλž˜μ„œ μ €λŠ” 경고창이 λ‚˜νƒ€λ‚¬μ„ λ•Œμ˜ μœˆλ„μš° 레벨이 .alert 인지 정말 확인해보고 μ‹Άμ—ˆλŠ”λ°μš”πŸ”Ž

     

    UIApplication.shared.windows μ†μ„±μ—μ„œλŠ” μ‹œμŠ€ν…œμ΄ λ§Œλ“  μœˆλ„μš°λ₯Ό 확인할 수 μ—†λ‹€λŠ” 것을 μ•Œκ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€.

    " 이 λ¦¬μŠ€νŠΈλŠ” μ‹œμŠ€ν…œμ΄ λ§Œλ“  μœˆλ„μš°λ₯Ό ν¬ν•¨ν•˜κ³  μžˆμ§€ μ•ŠμŠ΅λ‹ˆλ‹€ "

     

    이후

    μ € κ²½κ³  μ°½μ΄λΌλŠ” 것이 μ•± λ‚΄μ—μ„œ UIAlertController 둜 μƒμ„±ν•œ κ²½κ³ μ°½κ³ΌλŠ”

    λ¬΄κ΄€ν•œ κ²ƒμ΄λΌλŠ” 것을 λ·° 디버깅을 톡해 ν™•μΈν–ˆμŠ΅λ‹ˆλ‹€.

     

     

     

     

    끝!


    πŸ€–πŸŸ’[우짱의 iOS λΈ”λ‘œκ·Έ]πŸ”΅πŸ’»

    iOSλ₯Ό κ³΅λΆ€ν•˜λ©΄μ„œ 배운 λ‚΄μš©μ„ κΈ°λ‘ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

     

     

     

    참고 자료 1: https://developer.apple.com/library/archive/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/Introduction/Introduction.html#//apple_ref/doc/uid/TP40009503-CH1-SW2

     

    참고 자료 2: https://developer.apple.com/documentation/uikit/uiwindow

    λŒ“κΈ€

μ–΄μ œλ³΄λ‹€ λ°œμ „ν•œ λ‚˜