스트리밍은 대부분의 브라우저와
Developer 앱에서 사용할 수 있습니다.
-
UIKit의 새로운 기능
향상된 메뉴 바 지원, 자동 관찰 추적, 새로운 UI 업데이트 방법 및 애니메이션 개선 등을 비롯한 UIKit의 최신 API로 앱을 최신화하세요. 또한 UIKit 앱에 SwiftUI 장면을 포함하는 방법을 알려드리고 SF Symbols 및 HDR 색상 선택기 등을 살펴보겠습니다.
챕터
- 0:00 - Introduction
- 0:59 - New design system
- 2:29 - Containers and adaptivity
- 3:21 - The menu bar
- 9:58 - Architectural improvements
- 10:21 - Automatic observation tracking
- 12:33 - New UI update method
- 15:45 - Improvements to animations
- 17:45 - Scene updates
- 18:55 - HDR Color support
- 20:38 - Swift notifications
- 21:20 - Migrate to a scene-based life cycle
- 22:40 - OpenURL support for file URLs
- 23:17 - SF Symbols 7
- 25:13 - Next steps
리소스
관련 비디오
WWDC25
- 새로운 디자인 시스템과 더 친숙해지는 법
- 새로운 디자인으로 UIKit 앱 빌드하기
- iPad 앱 디자인 향상하기
- SF Symbols 7의 새로운 기능
- UIKit 앱을 더욱 유연하게 만들기
WWDC24
WWDC23
WWDC21
-
비디오 검색…
안녕하세요, 'UIKit의 새로운 기능'에 오신 것을 환영합니다 저는 UI 프레임워크 팀의 매니저인 Dima입니다 iOS 및 iPadOS에서 tvOS, visionOS Mac Catalyst에 이르기까지 UIKit은 계속해서 당신의 앱의 기초가 되어주고 있습니다 이제 더 많은 개선 사항과 함께요 새로운 디자인 시스템에 대한 UIKit 지원을 간략히 설명하며 시작해보겠습니다 앱 콘텐츠가 다양한 장치와 화면에 맞춰 적응하도록 도와주는 개선 사항을 설명하고 메뉴 막대의 새로운 UIKit API를 소개하겠습니다 iPadOS에 탑재된 친숙한 macOS 요소죠 UIKit 아키텍처 관련 핵심 발전사항도 자세히 알아보며 UIKit의 핵심 기반 또한 재검토할 것입니다 또한 더 넓은 일반적인 프레임워크 개선 사항을 전달하겠습니다 새 디자인 시스템은 시스템 재료와 제어 기능 외관에 생동감을 주는데 그 중심엔 새로운 재료 Liquid Glass가 있습니다 반투명하고 역동적이며 살아 있는 것 같죠 스페큘러 하이라이트나 굴절과 같은 효과도 있습니다 막대 및 검색 필드부터 알림, 팝오버, Split View까지 UIKit 표준 구성 요소가 새 재료와 함께 새로워졌습니다
이제 탐색 슬라이드가 유동적으로 전환되고 중단이 가능해 앱의 반응성을 더 높였습니다
사용자는 애니메이션이 끝날 때까지 기다리지 않아도 콘텐츠와 상호작용할 수 있습니다
UI에 새로운 디자인을 입히기 위해 백그라운드 확장 뷰와 같은 새로운 도구도 도입했습니다 사이드바의 넓은 글래스 면 아래 표면에 콘텐츠를 둘 수 있어 시각적인 연속성을 유지합니다
사용자 지정 구성 요소를 위한 글래스 재료도 있습니다 스크롤하면 글래스 면 아래의 콘텐츠가 자연스럽게 흐려져 막대 버튼과 기타 제어 기능의 가독성을 향상해주는 스크롤 에지 효과도 만나보세요
UIKit 앱의 외관 업데이트를 위한 포괄적인 실습 가이드가 필요하면 '새로운 디자인으로 UIKit 앱 빌드하기'를 시청하세요 새로운 디자인 자체를 탐구하려면 '새로운 디자인 시스템과 더 친숙해지는 법'을 시청하세요 이제 앱 콘텐츠가 다양한 장치와 화면에 맞춰 적응하도록 도와주는 개선 사항을 설명하겠습니다 iOS 26에서 UISplitViewController는 Inspector 우선 지원을 받습니다 Inspector는 선택한 콘텐츠의 추가 사항을 제공합니다 예를 들어, 미리 보기는 Inspector로 보조 열의 사진 옆에 메타데이터를 표시합니다
또한 이제 Split View 제어 기능의 구분 기호를 드래그하여 열의 크기를 조정할 수도 있습니다 포인터를 사용할 때에 열의 크기를 재조정할 방향 표시를 위해 모양잉 변합니다 컨테이너 뷰 제어기의 개선 사항과 레이아웃 여백, 안전 영역과 같은 일반 레이아웃 개념에 대해 다시 알아보려면 'UIKit 앱을 더욱 유연하게 만들기'를 시청하세요 iOS 26에서는 iPad에 macOS의 메뉴 막대가 등장합니다 이제 상단에서 스와이프하면 앱의 전체 메뉴가 표시됩니다 하드웨어 키보드가 없어도 말이죠 앱의 기능에 빠르게 접근하는 좋은 방법이죠
메뉴 막대는 이미지, 하위 메뉴 인라인 섹션, 체크표시 등 모든 기능을 지원합니다 키보드 단축키가 없는 명령어까지 앱의 모든 명령어가 표시됩니다 사용할 수 없는 명령어도 비활성화 상태로 계속 표시돼 사용자가 앱의 모든 기능을 알 수 있도록 합니다
앱은 여전히 UIMenuBuilder로 메인 메뉴를 사용자화합니다 iOS 26에서 UIKit에는 다수의 새 API가 추가돼 메뉴 막대가 더 향상되었습니다 메인 메뉴 시스템 구성부터 시작하겠습니다 이 API를 사용하면 기존에 메인 메뉴에 제공된 시스템 명령을 앱이 사용자 지정할 수 있습니다 구성 API를 사용하면 앱이 토글 Inspector에 대한 새로운 명령어처럼 사전 정의된 로컬 메뉴 요소를 추가적으로 선택합니다 또한 어떤 항목을 포함하거나 생략할지 미리 선언할 수 있죠 각 요소 그룹을 세밀히 구성하고 스타일을 지정할 수도 있습니다 한 예로, 앱의 요구에 맞게 정의된 검색 명령을 최적화할 수 있겠죠 마지막으로, UIMenuBuilder 블록을 미리 제공해 맞춤 항목을 추가하면 앱과 공유 확장 프로그램이 키보드 단축키를 정의하는 데 동일한 코드를 사용하도록 합니다 메인 메뉴 시스템 구성을 사용하는 예를 살펴보겠습니다 먼저, 구성 객체를 만들어 앱이 메인 메뉴에서 원하는 명령을 기본적으로 지정합니다 한 예로, 시스템 인쇄 명령에 대한 지원을 선언해보겠습니다
Inspector 패널을 토글하는 새 명령어 등 특정 기본 명령어는 선택을 해제하겠습니다 구성을 통해 시스템 검색 명령을 단일 검색 항목으로 변환하는 등 기본 명령에 대한 공통 스타일을 지정할 수 있습니다 텍스트보다 콘텐츠를 검색하는 사진 또는 음악 앱에서 사용하기에 적합합니다 마지막으로, 메인 메뉴 시스템에서 구성을 설정해 구성을 원하는 요소의 초기 세트로 구축할 수도 있습니다 선택적으로 구축 핸들러를 제공할 수도 있죠 buildMenuWithBuilder 대신 호출되는 요소입니다 핸들러는 UIMenuBuilder에 대한 접근을 제공합니다 iOS 26에서 훨씬 더 편리해졌죠 더 빠른 성능을 자랑하며 진단 기능도 개선되었습니다
구성 설정 시 메뉴 막대 리빌드가 트리거되는 걸 볼 수 있습니다 이상적으로 앱은 가능한 한 빨리 한 번만 구성을 설정해야 합니다 application(_:didFinishLaunchingWithOptions:)처럼요 iOS 및 MacOS 26의 메뉴 막대에는 표준 동작과 메뉴가 새로 추가되었습니다 Perform Close는 Cmd-W에 매핑되어 기본적으로 창 장면을 닫습니다 웹 브라우저의 탭 등 앱의 다른 것들을 닫을 수도 있죠 '클립보드에서 새로 만들기' 메뉴 명령을 사용하면 붙여넣기 경고를 트리거하지 않고도 붙여넣기 보드 콘텐츠로 문서를 만들 수 있습니다 iOS 26에 도입된 newItem 메뉴에서 활용하기에 좋은 기능이죠 이제 텍스트 정렬과 사이드바 토글 Inspector 토글 시 표준 작업이 노출되어 앱에서 커스텀이 가능합니다 기본적으로 키보드 단축키는 키가 눌렸을 때 반복되지만 UIKeyCommand에서 repeatBehavior 속성을 설정하면 이 동작을 사용자화할 수 있죠
validateCommand를 사용하여 응답자별로 설정할 수도 있습니다 삭제 키를 눌러 이메일을 삭제하는 등 중요한 삭제 동작에서 특히 유용합니다 실수로 반복적으로 트리거하지 않도록 할 수 있기 때문입니다 일부 경우에는 메뉴 바의 일부가 집중 항목 또는 창 장면에 따라 동적 콘텐츠를 표시하기도 합니다 예를 들면 Safari와 같은 브라우징 앱은 히스토리 메뉴에서 현 브라우징 프로필의 히스토리를 표시할 수 있습니다
이를 지원하기 위해 응답자 체인에서 요소를 채워 넣는 포커스 기반 지연 메뉴 요소를 새로 사용합니다 메인 메뉴 구조 구성 시 포커스로 UIDeferredMenuElement를 생성하고 식별자를 할당해 구분합니다 그런 다음 메인 메뉴에 삽입합니다
지연된 요소를 충족해야 하면 UiKit은 항목을 제공할 수 있는 응답자를 찾을 때까지 응답자 체인을 따라갑니다 이 예시에서 브라우저 뷰 제어기는 providerForDeferredMenuElement를 오버라이드해 현 프로필에 대한 히스토리 항목을 제공합니다
브라우저 히스토리 요소에 대한 지연된 요소의 식별자를 확인하고 공급자를 반환해 히스토리 메뉴 항목을 로드하죠 포커스 기반 지연 요소는 메인 메뉴 시스템에서 값비싼 재구축을 수행할 필요 없이 키리스 명령어로 메뉴 막대를 최신 상태로 유지하기에 좋습니다 앱의 사용자 지정 항목 외에도 시스템은 여러 메뉴 입력값을 자동으로 제공합니다 앱은 설정 앱에서 설정을 열 수 있는 키보드 단축키를 얻습니다 문서 기반 앱의 경우 최근 항목 열기 메뉴에 최근 문서가 채워집니다 또한 시스템은 창 메뉴를 타일링 명령으로 보완합니다 앱에 대한 모든 열린 장면 목록을 포함하죠 각 장면의 제목을 채워 사용자가 구별할 수 있도록 합니다 마지막으로, 메뉴바를 만들 때 명심해야 할 사항이 있습니다 UIKit 앱에서 스토리보드에 정의된 메뉴 막대가 이제 지원되지 않아 앱이 스토리보드에 메뉴를 실행하지 않기 때문에 이를 프로그래밍으로 구현해야합니다
또한 메뉴 막대가 항상 있는 것은 아니니 메뉴 막대 없이도 앱의 기능에 접근할 수 있는지 확인해야 합니다 멋진 메뉴 막대 만드는 방법에 대해 자세히 알아보려면 'iPad 앱의 디자인 개선하기'를 시청하세요 UIKit 메인 메뉴의 개요를 보려면 'iPad 앱을 한층 더 개선하기'를 확인해 보세요 UIKit은 현대적인 패턴과 모범 사례, 향상된 SwiftUI 상호운용성 등 새로운 기능으로 계속 발전을 거치고 있습니다 iOS 26 또한 동일하죠 여러분께 공유할 새로운 아키텍처 개선 사항이 있습니다 첫 번째 주요 개선 사항은 UIKit의 Swift Observable 객체를 위한 내장 지원 기능입니다
UIKit은 이제 Swift 관찰을 중심 즉 update 메서드에 통합합니다 layoutSubviews()처럼 참조하는 모든 Observable을 자동 추적해 종속성을 연결하고 올바른 뷰를 무효화합니다 수동 setNeedsLayout이 필요 없죠 iOS 18에서 Info.plist에 UIObservationTrackingEnabled를 추가해 다시 배포할 수 있습니다 iOS 26에서는 기본적으로 활성화된 기능입니다 자동 관찰 추적의 몇 가지 예를 검토하겠습니다
읽지 않은 메시지를 나타내는 UILabel을 포함한 메시지 목록 보기 제어 기능이 있습니다
상태가 표시되는 위치와 상태 문자열을 제어하는 부울과 상태 문자열이라는 두 가지 속성을 가진 Observable 모델 객체가 뒷받침하죠 viewWillLayoutSubviews()에서 관찰 가능한 모델로 레이블의 알파를 업데이트해 숨김 혹은 표시하고 텍스트를 설정하죠 첫 번째 레이아웃에서 UIKit은 레이블을 채웁니다 자동 관찰 추적 기능 덕분에 showStatus와 statusText에 기록 종속성도 채워집니다 이 속성에 대한 모든 변경사항은 보기를 무효화하고 viewWillLayoutSubviews()를 재실행해 별도 코드 없이 레이블 동기화를 유지하죠 다음은 UIKit에서 관찰 가능한 객체를 사용하는 또 다른 예입니다 UICollectionView에서 셀을 구성할 때 자동 관찰 추적 기능의 이점을 강조합니다 각 목록 셀을 아이콘과 제목 부제목이 포함된 관찰 가능한 ListItemModel로 백킹합니다 셀 제공자 콜백 안에는 셀을 대기열에서 제거하고 configurationUpdateHandler를 할당합니다 이 핸들러는 관찰 추적을 지원하기 때문에 UIKit은 그 안에서 사용하는 어떤 Observable 객체에든 자동으로 종속성을 구축합니다
핸들러 내부는 Observable 목록 항목 모델로 목록 콘텐츠 구성을 채워넣고 적용합니다 다 됐네요! 이제 셀이 표시되는 동안 모델의 속성에 변경사항이 적용되면 UIKit이 핸들러를 재실행해 셀을 업데이트 해줄 것입니다 이제 UIKit에 일반 용도 업데이트 메서드가 추가돼 자동 특성 및 관찰 추적기능이 지원됩니다
UIView 및 UIViewController에 전부 updateProperties()라는 새 메서드가 추가되었습니다
이는 layoutSubviews() 직전에 실행되지만 독립적이라 레이아웃을 강제하지 않고 속성을 무효화할 수 있습니다 반대도 가능해 추가 패스를 피하고 세밀한 업데이트를 얻을 수 있죠
updateProperties()는 layoutSubviews()를 대체하는 것이 아니라 보완합니다 콘텐츠 채우기, 스타일 적용 또는 작동 구성에 사용하세요
당신이 읽은 모든 Observable을 자동으로 추적하며 setNeedsUpdateProperties()를 호출해 수동으로 트리거할 수 있죠 이 새 방법을 사용하는 구체적인 예를 검토하겠습니다
배지 뷰에 표시된 수를 보관하는 Observable BadgeModel 객체가 있습니다 막대 버튼 항목의 뷰 제어기는 배지 모델이 백킹합니다
updateProperties()에서 바 버튼 항목에 새 배지 API를 사용하고 모델에서 수를 곧바로 추출하면 Observable 모델 객체가 변할 때마다 updateProperties()가 실행되어 배지가 업데이트됩니다
뷰를 layoutSubviews() 대신 updateProperties()로 구성하면 크기 재조정과 같이 무관한 이벤트 코드를 재실행하지 않아도 돼서 불필요한 작업을 줄이고 성능을 개선할 수 있습니다 다른 업데이트 메서드에서 updateProperties()의 작동 방법을 설명하기 위해 UIKit 업데이트 패스의 작동 방식을 설명해보죠
UIKit 업데이트 뷰가 화면에 표시되기 전의 모습입니다 레이아웃 패스가 먼저죠 UIKit은 뷰 계층구조를 위에서부터 가로지르며 각 뷰의 특성을 업데이트하고 layoutSubviews()를 호출합니다 이 패스로 인해 다른 뷰에 레이아웃이 요구될 경우 모든 레이아웃이 마칠 때까지 레이아웃 패스가 반복됩니다
레이아웃이 자리를 잡으면 UIKit이 디스플레이 패스를 실행해 각 뷰에서 드로우 메서드를 호출하고 더 이상 어떤 뷰에도 디스플레이가 필요없을 때까지 이를 반복합니다 두 패스가 모두 끝나면 다음 프레임을 렌더링할 수 있게 되며 화면에 바로 표시할 수 있습니다
새로운 업데이트 속성 콜백이 어떻게 들어 맞는지 설명해보죠 탑다운 레이아웃 패스 중, UIKit은 특성 업데이트 직후와 layoutSubviews() 직전에 updateProperties()를 실행합니다 layoutSubviews()는 속성 업데이트 그리고 평상적 레이아웃 논리라는 두 가지 단계로 나뉘어 있습니다 속성 모음은 updateProperties()의 실행 전에 업데이트 되므로 이곳에서 안전히 읽을 수 있습니다 항상 layoutSubviews()보다 앞서 포함된 레이아웃 무효화가 가능하고 레이아웃 경로는 그 직후에 실행됩니다
새 updateProperties() 메서드 보완과 새 관찰 추적 기능을 위해 UIKit에서 애니메이션이 작동하는 방식을 개선했습니다
iOS 18 이하 버전의 수동 업데이트 작동 방식을 검토하겠습니다 UIView 애니메이션 클로저에서 먼저 Observable 객체에 새 값이 매겨진 후 필요 시 해당 객체 의존 뷰에서 layoutIfNeeded()이 호출되죠 첫 번째 단계는 무효화를 유발하고 두 번째 단계는 업데이트와 애니메이션 생성을 실행하므로 두 단계 모두 필요합니다 수동으로 속성과 뷰 의존성을 유지하면 오류가 빈번할 수 있고 업데이트 또는 애니메이션이 너무 많거나 적게 생성될 수 있죠 iOS 26의 UIViews에서 flushUpdates란 새 애니메이션을 사용할 수 있습니다 이를 활성화하면 UIKit은 보류하던 업데이트를 애니메이션 직전과 직후에 적용해 더 이상 layoutIfNeeded()를 호출할 필요가 없죠 flushUpdates를 작동시키려면 무효화 상태 변경사항을 애니메이션 클로저 내에만 적용해야 합니다 flushUpdates를 사용하는 방법 예시를 알아보겠습니다 먼저 flushUpdates를 UIView 애니메이션을 위한 옵션으로 패스하고 클로저 내부의 Observable 객체를 변경합니다 업데이트 메서드에서 해당 Observable 객체를 사용하는 모든 뷰가 필요한 업데이트를 자동으로 실행하게 됩니다 flushUpdates는 Observable 구동 애니메이션에 국한되지 않죠
이를 사용해 자동 레이아웃 제약 변경사항을 자동으로 애니메이션화 하는 방법 예시를 살펴보겠습니다 flushUpdates 클로저에서 기존 제약 중 하나를 새 상수로 설정하고 다른 제약을 활성화 및 비활성화합니다 종속 뷰가 자동으로 새로운 위치와 크기로 애니메이션됩니다 SwiftUI와 UIKit으로 같은 앱을 더 매끄럽게 만드는 방법을 보죠 새 대리자 매개변수를 쓰는 UIKit 앱에서 SwiftUI 장면이 지원돼 점진적인 SwiftUI 도입을 지원하며 UIKit 앱에 VisionOS의 몰입형 공간과 볼륨을 활용할 수 있도록 허용합니다
젠 가든 장면을 보여주는 명상 앱을 상상해보세요 iPhone 및 iPad에서 보는 2D 창과 VisionOS를 통한 몰입형 공간도요 몰입형 공간은 루트 SwiftUI 장면에 새 UIHostingSceneDelegate 매개변수를 구현해 보여드릴게요
호스팅 장면 위임자 사용법은 다른 장면 위임자와 동일합니다 새 장면이 연결될 때 UISceneConfiguration에 위임 클래스 유형을 설정하면 됩니다
프로그래밍으로 식별자를 패스하여 호스팅 위임자로부터 특정 SwiftUI 장면을 요청할 수 있습니다
이 예시에서는 몰입형 젠 가든 공간을 요청하죠 마지막으로 UIKit의 일반적인 개선 사항을 몇 가지 알려드릴게요 HDR 렌더링부터 시작하겠습니다 iOS 26에서는 HDR을 이미지뿐 아니라 색상에도 활용합니다 사용자 인터페이스를 강조하거나 새로운 경험을 구현할 수 있죠
이제 UIColor로 기본 SDR 색상과 노출 값을 지정하여 밝기부터 디스플레이 기능까지 자동으로 조정할 수 있습니다 노출값이 SDR 피크 화이트의 2.5배로 설정된 붉은 HDR 색상을 생성했습니다 UIColorPickerViewController와 UIColorWell에서 이제 HDR 색상 선택 기능을 활성화할 수도 있습니다 최대 노출값을 앱의 렌더링 역량에 따라 설정하면 됩니다 여기서는 색상 선택기의 최대 선형 노출값을 SDR 피크 화이트의 2배로 설정했습니다
iOS 18에서 UIImageView는 HDR에서 SDR로 지능적으로 폴백하여 UI의 주요 콘텐츠가 눈에 띄도록 합니다 iOS 26에서는 이 동작이 동영상으로 확장되며 맞춤형 콘텐츠에도 적용됩니다 새 UITraitHDRHeadroomUsage 특성으로 HDR 콘텐츠가 SDR로 폴백되어야 하는 시점을 모니터링하세요 HDR에 대한 자세한 내용을 보려면 'HDR로 앱에서 동적 이미지 경험 제공하기' 및 '앱에서 HDR 이미지 지원하기' 영상을 시청하세요
iOS 26에서 NSNotification.Name API와 UIKit으로 구축하면 각 알림이 전용 NotificationCenter.Message 유형으로 나타납니다 이렇게 하면 관찰자 등록 및 이벤트 세부사항 불러오기를 위한 강력히 입력된 값을 얻을 수 있습니다 다음은 키보드가 나타날 때 레이아웃을 조정하는 예입니다 keyboardWillShow 알림 유형에 대해 등록한 후 핸들러에서 메시지로부터 직접 애니메이션 지속 시간과 키보드 프레임을 추출합니다 userInfo 룩업이나 수동 캐스팅 없이도 이런 값을 사용해 제약 사항을 애니메이션화합니다 각 릴리즈와 함께 UIKit은 지속적으로 진화하고 있으며 매번 현대적이고 강력한 API를 제공합니다 그 도입 과정에서 기존의 레거시 메서드는 사용하지 않게 됩니다
UIScene 도입으로 앱의 휴대성과 유연성이 크게 개선되기에 여러 UIApplication 중심 API의 지원을 중단하는 과정에 있습니다
레거시 UIApplicationDelegate 콜백과 UIApplicationLaunchOptionKeys는 더이상 적용되지 않으며 UIWindow용 init(windowScene:) 이니셜라이저만 남습니다 다른 모든 이니셜라이저는 더 이상 사용되지 않습니다 iOS 26 이후 릴리즈에서 최신 SDK로 구축된 UIKit 앱은 전부 UIScene 라이프 사이클을 사용해야만 실행할 수 있습니다
UIScene 라이프 사이클을 멀티창 앱뿐 아니라 모든 곳에 활용하세요 활용법을 더 자세히 알아보려면 테크 노트 'UIKit 장면 기반 라이프 사이클로 마이그레이션하기'를 읽어보세요 UIRequiresFullScreen으로부터 마이그레이션을 돕는 새로운 API를 포함해 앱의 유연성을 극대화하는 방법에 대한 자세한 내용을 보려면 'UIKit 앱을 더욱 유연하게 만들기'를 시청하세요
다양한 문서 유형을 다루는 앱이라면 외부 뷰어를 자주 실행해야 할 수 있습니다 이제 iOS 26에서는 기존 openURL 메서드에 파일 URL이 허용되어 앱에서 기본적으로 지원되지 않는 문서도 배포가 가능해졌습니다 해당 파일 유형을 위한 기본 앱이 존재하는 경우 시스템이 앱을 실행하고 URL을 따라 전달합니다 그렇지 않으면 openurl은 거짓을 반환해 퀵 룩 미리보기 제어기를 사용하는 등 폴백을 직접 처리하는 옵션을 제공합니다
iOS 26에서는 SF Symbols도 개선되었습니다 SF Symbols 7는 기호를 그릴 수 있으며 두 가지 효과가 있습니다 사라지는 효과 드로우 오프는 드로우 애니메이션으로 기호를 가리고 나타나는 효과 드로우 온은 숨겨진 기호를 그려 나타냅니다
기호는 이제 변수 값의 새로운 모드인 변수 드로우를 지원합니다 이 진행률 표시기와 같은 경로를 따라 임의의 값을 그리죠 자동 기호 콘텐츠 전환과 함께 변수 값에 애니메이션을 적용할 수도 있습니다
매직 대치 전환 또한 특정 기호 간 특별한 드로우 애니메이션을 수행할 수 있습니다 한 예로, 원 기호와 채워진 체크표시 기호 사이에 전환을 사용하면 원이 채워지고 체크표시가 그려집니다 이 애니메이션은 버튼에 매우 유용하며, UIKit에서는 새 API로 UIButton에 기호 콘텐츠 전환을 손쉽게 적용할 수 있게 되었습니다
UIButton.Configuration에서 새 symbolContentTransition 속성으로 대체와 같은 기호 콘텐츠 전환을 명시하세요 선택 상태가 토글되는 등 버튼의 기호가 변하면 UIKit이 전환을 실행합니다 SF Symbols 7에는 다른 새로운 기능도 있습니다 새 색상 렌더링 모드 옵션도 그 중 하나입니다 앱은 단일 색상이 아니라 자동 생성된 그라디언트로 그라디언트를 명시하여 기호에 색을 칠할 수 있습니다
그리기 및 그라디언트 사용자화 방법을 모두 알고 싶다면 'SF Symbols 7의 새로운 기능'을 확인하세요 기호 효과를 적용하는 방법을 다시 알아보려면 '앱의 기호에 애니메이션 적용하기'를 확인하세요
다음 단계는 무엇일까요? iOS 26 SDK로 앱을 컴파일하세요 앱이 새 디자인에 어떻게 반응하나 검토하고 새로운 미학에 맞게 UI와 스타일을 다듬어보세요 UISplitViewController 및 UITabBarController같은 표준 컨테이너로 유연한 레이아웃을 지원하세요 새로운 메뉴 API로 앱의 메뉴도 구현하세요 updateProperties 메서드와 관찰 추적 기능을 도입해 코드를 정리하고 성능을 개선하세요 감사합니다 이 개선 사항을 활용해 당신의 앱이 얼마나 더 강력하고 멋지게 변할지 정말 기대됩니다
-
-
4:56 - Main menu system configuration
// Main menu system configuration var config = UIMainMenuSystem.Configuration() // Declare support for default commands, like printing config.printingPreference = .included // Opt out of default commands, like inspector config.inspectorPreference = .removed // Configure the Find commands to be a single "Search" element config.findingConfiguration.style = .search
-
5:39 - Main menu system build configuration
// Main menu system configuration // Have the main menu system build using this configuration, and make custom additions. // Call this early, e.g. in application(_:didFinishLaunchingWithOptions:), and call it once UIMainMenuSystem.shared.setBuildConfiguration(config) { builder in builder.insertElements([...], afterCommand: #selector(copy(_:))) let deleteKeyCommand = UIKeyCommand(...) builder.replace(command: #selector(delete(_:)), withElements: [deleteKeyCommand]) }
-
7:01 - Keyboard shortcut repeatability
// Keyboard shortcut repeatability let keyCommand = UIKeyCommand(...) keyCommand.repeatBehavior = .nonRepeatable
-
7:43 - Focus-based deferred menu elements (App Delegate)
// Focus-based deferred menu elements extension UIDeferredMenuElement.Identifier { static let browserHistory: Self = .init(rawValue: "com.example.deferred-element.history") } // Create a focus-based deferred element that will display browser history let historyDeferredElement = UIDeferredMenuElement.usingFocus( identifier: .browserHistory, shouldCacheItems: false ) // Insert it into the app’s custom History menu when building the main menu builder.insertElements([historyDeferredElement], atEndOfMenu: .history)
-
8:06 - Focus-based deferred menu elements (View Controller)
// Focus-based deferred menu elements class BrowserViewController: UIViewController { // ... override func provider( for deferredElement: UIDeferredMenuElement ) -> UIDeferredMenuElement.Provider? { if deferredElement.identifier == .browserHistory { return UIDeferredMenuElement.Provider { completion in let browserHistoryMenuElements = profile.browserHistoryElements() completion(browserHistoryMenuElements) } } return nil } }
-
10:54 - Using an Observable object and automatic observation tracking
// Using an Observable object and automatic observation tracking @Observable class UnreadMessagesModel { var showStatus: Bool var statusText: String } class MessageListViewController: UIViewController { var unreadMessagesModel: UnreadMessagesModel var statusLabel: UILabel override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() statusLabel.alpha = unreadMessagesModel.showStatus ? 1.0 : 0.0 statusLabel.text = unreadMessagesModel.statusText } }
-
11:48 - Configuring a UICollectionView cell with automatic observation tracking
// Configuring a UICollectionView cell with automatic observation tracking @Observable class ListItemModel { var icon: UIImage var title: String var subtitle: String } func collectionView( _ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath ) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) let listItemModel = listItemModel(for: indexPath) cell.configurationUpdateHandler = { cell, state in var content = UIListContentConfiguration.subtitleCell() content.image = listItemModel.icon content.text = listItemModel.title content.secondaryText = listItemModel.subtitle cell.contentConfiguration = content } return cell }
-
13:27 - Using automatic observation tracking and updateProperties()
// Using automatic observation tracking and updateProperties() @Observable class BadgeModel { var badgeCount: Int? } class MyViewController: UIViewController { var model: BadgeModel let folderButton: UIBarButtonItem override func updateProperties() { super.updateProperties() if let badgeCount = model.badgeCount { folderButton.badge = .count(badgeCount) } else { folderButton.badge = nil } } }
-
16:57 - Using the flushUpdates animation option to automatically animate updates
// Using the flushUpdates animation option to automatically animate updates // Automatically animate changes with Observable objects UIView.animate(options: .flushUpdates) { model.badgeColor = .red }
-
17:23 - Automatically animate changes to Auto Layout constraints with flushUpdates
// Automatically animate changes to Auto Layout constraints UIView.animate(options: .flushUpdates) { // Change the constant of a NSLayoutConstraint topSpacingConstraint.constant = 20 // Change which constraints are active leadingEdgeConstraint.isActive = false trailingEdgeConstraint.isActive = true }
-
18:07 - Setting up a UIHostingSceneDelegate
// Setting up a UIHostingSceneDelegate import UIKit import SwiftUI class ZenGardenSceneDelegate: UIResponder, UIHostingSceneDelegate { static var rootScene: some Scene { WindowGroup(id: "zengarden") { ZenGardenView() } #if os(visionOS) ImmersiveSpace(id: "zengardenspace") { ZenGardenSpace() } .immersionStyle(selection: .constant(.full), in: .mixed, .progressive, .full) #endif } }
-
18:28 - Using a UIHostingSceneDelegate
// Using a UIHostingSceneDelegate func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration { let configuration = UISceneConfiguration(name: "Zen Garden Scene", sessionRole: connectingSceneSession.role) configuration.delegateClass = ZenGardenSceneDelegate.self return configuration }
-
18:41 - Requesting a scene
// Requesting a scene func openZenGardenSpace() { let request = UISceneSessionActivationRequest( hostingDelegateClass: ZenGardenSceneDelegate.self, id: “zengardenspace")! UIApplication.shared.activateSceneSession(for: request) }
-
19:18 - HDR color support
// Create an HDR red relative to a 2.5x peak white let hdrRed = UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1.0, linearExposure: 2.5)
-
19:50 - HDR color picking
// Support picking HDR colors relative to a // maximum peak white of 2x colorPickerController.maximumLinearExposure = 2.0
-
20:06 - Mixing SDR and HDR content
// Mixing SDR and HDR content registerForTraitChanges([UITraitHDRHeadroomUsageLimit.self]) { traitEnvironment, previousTraitCollection in let currentHeadroomLimit = traitEnvironment.traitCollection.hdrHeadroomUsageLimit // Update HDR usage based on currentHeadroomLimit’s value }
-
20:54 - Adopting Swift notifications
// Adopting Swift notifications override func viewDidLoad() { super.viewDidLoad() let keyboardObserver = NotificationCenter.default.addObserver( of: UIScreen.self for: .keyboardWillShow ) { message in UIView.animate( withDuration: message.animationDuration, delay: 0, options: .flushUpdates ) { // Use message.endFrame to animate the layout of views with the keyboard let keyboardOverlap = view.bounds.maxY - message.endFrame.minY bottomConstraint.constant = keyboardOverlap } } }
-
24:26 - Using a symbol content transition to automatically animate symbol updates
// Using a symbol content transition to automatically animate symbol updates var configuration = UIButton.Configuration.plain() configuration.symbolContentTransition = UISymbolContentTransition(.replace)
-
-
- 0:00 - Introduction
Learn about UIKit's enhancements across iOS, iPadOS, tvOS, visionOS, and Mac Catalyst. This video covers the new design system, containers and adaptivity, APIs for the menu bar on iPadOS and Mac Catalyst, core architectural advancements, and general framework improvements.
- 0:59 - New design system
The new design system features Liquid Glass: a translucent, dynamic material that refreshes standard UIKit components and enhances navigation transitions. UIKit also has new API for bringing Liquid Glass to your custom UI.
- 2:29 - Containers and adaptivity
iOS 26 enhances 'UISplitViewController' with inspectors for detailed content display and dynamic column resizing.
- 3:21 - The menu bar
iOS 26 improves the menu bar on iPad, which is now accessible via a swipe from the top of the screen, to provide quick access to app functionality without a hardware keyboard. The menu bar should always display all app commands, even those that are disabled or without keyboard shortcuts. Customize the menu bar using the new API for main menu configuration, and implement dynamic menus based on the focused view. Standard actions like 'Close', and 'New from Clipboard' are introduced. Actions for text alignment, sidebar toggling, and inspector toggling are now exposed for customization. Make sure that actions are available in your app without relying on the menu bar.
- 9:58 - Architectural improvements
UIKit continues to evolve with new features for modern patterns, best practices and deeper SwiftUI interoperability.
- 10:21 - Automatic observation tracking
UIKit now automatically tracks Observable objects referenced in update methods such as 'layoutSubviews', eliminating the need for manual calls to 'setNeedsLayout'. This feature is enabled by default in iOS 26 and you can back-deploy it to iOS 18 with the 'UIObservationTrackingEnabled' Info.plist key. Changes to Observable model properties that update UI elements automatically trigger view invalidation and reruns of the relevant update methods, keeping the UI in sync without additional code.
- 12:33 - New UI update method
UIKit introduces a new method, 'updateProperties', available in 'UIView' and 'UIViewController'. This method runs independently before 'layoutSubviews' and allows you to populate content, apply styling, and configure behaviors more efficiently. 'updateProperties' automatically tracks Observables and can otherwise be manually triggered by calling 'setNeedsUpdateProperties'. By using this method, you can avoid unnecessary layout passes, improving your app's performance.
- 15:45 - Improvements to animations
In iOS 26, UIKit introduces 'flushUpdates', an animation option that automatically applies pending updates before and after animations, eliminating the need for manual 'layoutIfNeeded' calls. This simplifies code, reduces errors, and works with Observable objects and auto layout constraint changes.
- 17:45 - Scene updates
You can now integrate SwiftUI scenes into UIKit apps using the new 'UIHostingSceneDelegate' protocol. Create apps that adapt to different devices — like a meditation app with a 2D zen garden on iPhone and iPad and an immersive visionOS experience — by programmatically requesting a specific SwiftUI scene.
- 18:55 - HDR Color support
In iOS 26, UIKit also enhances HDR rendering beyond images to include colors. Create HDR colors using 'UIColor' and enable HDR color selection in color pickers. Use the new 'UITraitHDRHeadroomUsage' trait to monitor when your HDR content should fall back to SDR.
- 20:38 - Swift notifications
UIKit represents each notification as a dedicated 'NotificationCenter.Message' type in iOS 26, providing strongly typed notifications for easier event handling, as seen in an example of adjusting layout when the keyboard appears.
- 21:20 - Migrate to a scene-based life cycle
'UIScene' replaces 'UIApplication' as the standard for app development, making apps more portable and flexible. You must adopt the 'UIScene' life cycle because legacy methods are deprecated and, starting with the release following iOS 26, apps that have not adopted the scene life cycle will not launch.
- 22:40 - OpenURL support for file URLs
The 'openURL' method now allows apps to hand off non-native documents to default viewers or use quick look preview controllers if no default exists.
- 23:17 - SF Symbols 7
SF Symbols 7 introduces new drawing capabilities including 'Draw Off' and 'Draw On' effects, variable draw mode for drawing arbitrary values along a path, and special draw animations with Magic Replace transitions. UIKit now has API for easy adoption of these transitions in 'UIButton', and symbols can be colored with automatically-generated gradients.
- 25:13 - Next steps
To update your app for iOS 26, compile with the new SDK, refine UIs to match the new design, utilize standard containers and new menu APIs, and adopt the 'updateProperties' method and observation tracking for improved performance.