• Key Features

    • Xcode Preview

      • UIKit에서도 Preview를 사용할 수 있다.

        // UIViewController
        class LibraryViewController: UIViewController {
            // ...
        }
        
        #Preview("Library") {
            let controller = LibraryViewController()
            controller.displayCuratedContent = true
            return controller
        }
        
        // UIView
        class SlideshowView: UIView {
            // ...
        }
        
        #Preview("Memories") {
            let view = SlideshowView()
            view.title = "Memories"
            view.subtitle = "Highlights from the past year"
            view.images = ...
            return view
        }
        
    • View Controller lifecycle updates

      • viewIsAppearing 메소드 추가

        • viewWillAppear와 viewDidAppear 사이에 불린다.
        • 이때 viewController와 view의 traitCollection과 Geometry가 최신화된 상태라서 이에 의존하는 코드를 호출하기 최적
        • iOS 13까지의 back deploy 지원
      • viewcontroller Lifecycle

        • viewWillAppear는 view가 계층에 포함되기 전에 호출된다. 그리고 레이아웃도 안된 상태다.
          • 여기서는 traitCollection이나 뷰의 geometry 정보를 사용하는 것은 너무 이르다.
        • viewDidAppear는 CATransaction이 끝나고 호출된다. 여기서는 모든 애니매이션이 끝난 상태이므로 view의 속성을 바꾸기에는 너무 늦다.
        • viewIsAppearing은 viewWillAppear와 같은 Transaction에서 호출되므로 여기서 바꾸는 건 즉시 반영된다.
        • LayoutCallback(view~LayoutSubViews 계열)은 layoutSubViews()를 호출할 때마다 호출되지만, viewIsAppearing은 처음 뜰 때만 호출된다.

        스크린샷 2023-06-12 오후 12.08.13.png

    • Trait system enhancements

      • TraitCollection은 앱의 계층을 따라서 자동으로 데이터를 전파할 수 있는 방법.
        • UserInterfaceStyle, size class, preferred content size category 등의 system trait들이 이미 이를 사용중
      • 커스텀 데이터를 정의하는 기능 추가
        • SwiftUI의 environmentKey와의 브릿징 가능
      • trait을 override하는 API를 추가해서 특정 뷰 계층에 대해서 쉽게 trait을 변경할 수 있게 함
      • trait 변경에 대해서 override를 하지 않고도 콜백을 받을 수 있는 API 추가
    • Animated symbol images

      • SFSymbol에 animation지원 추가

        imageView.addSymbolEffect(.bounce)
        
        imageView.addSymbolEffect(.variableColor.iterative)
        imageView.removeSymbolEffect(ofType: .variableColor)
        
    • Empty States

      • 앱이 보여줄 수 있는 컨텐츠가 없는 상황에서 사용가능

        • 앱이 처음 실행되어서 보여줄 컨텐츠가 아직 안 만들어졌을 때
        • 제한된 환경(ex. 인터넷 연결 없음)때문에 컨텐츠를 보여줄 수 없을 때
      • 예시

        • empty

          var config = UIContentUnavailableConfiguration.empty()
          
          config.image = UIImage(systemName: "star.fill")
          config.text = "No Favorites"
          config.secondaryText =
              "Your favorite translations will appear here."
          
          viewController.contentUnavailableConfiguration = config
          
        • loading

          var config = UIContentUnavailableConfiguration.loading()
          viewController.contentUnavailableConfiguration = config
          
        • SwiftUI

          let config = UIHostingConfiguration {
              VStack {
                  ProgressView(value: progress)
                  Text("Downloading file...")
                      .foregroundStyle(.secondary)
              }
          }
          viewController.contentUnavailableConfiguration = config
          
      • 업데이트 하기

        override func updateContentUnavailableConfiguration(
            using state: UIContentUnavailableConfigurationState
        ) {
            var config: UIContentUnavailableConfiguration?
            if searchResults.isEmpty {
                config = .search()
            }
            contentUnavailableConfiguration = config
        }
        
        // Update search results for query
        searchResults = backingStore.results(for: query)
        setNeedsUpdateContentUnavailableConfiguration()
        
  • Internationalization

    • Dynamic line-height adjustments

      • 용어

        • baseline: 글자가 존재하는 기준선
        • line height: baseline 사이의 간격
        • x-height: 소문자의 최대 높이 상한선
        • ascender: x-height를 넘어가는 폰트 높이
        • descender: baseline 아래를 넘어가는 높이
      • 아랍어, 힌디 문자 등에서는 라틴 문자보다 더 많은 세로 공간을 요구한다.

        스크린샷 2023-06-12 오후 4.41.24.png

      • 그래서 UILable등의 텍스트 요소들에 가독성을 위해 자동으로 line-height 및 세로 영역을 조정해주는 기능이 추가되었다.

    • Improved line-breaking and hyphenation

      • 중국어, 독일어, 일본어, 한국어에 대한 line-breaking 개선

      • 어떤 Text Style을 적용했냐에 따라서 다르게 동작

      • 대부분은 자동적으로 동작하나 자세한 정보는 관련 세션 참조

        let label = UILabel()
        label.text = ~태국어~
        label.traitOverrides.typeSettingLanguage = Locale.Language(identifier: "th")
        
    • Retrieve UIImages by locale

      • 이미지도 localization이 적용된다.

        • ex. SF Symbol의 character.textbox는 8개의 variant를 가진다.
      • 기본적으로는 디바이스의 언어 설정을 따라간다.

      • iOS 17부터 특정 locale을 지정할 수 있는 기능 추가

        let locale = Locale(languageCode: .japanese)
        
        imageView.image = UIImage(
        	systemName: "character.textbox",
        	withConfiguration: UIImage.SymbolConfiguration(locale: locale)
        )
        
  • Improvements for iPad

    • Window dragging interaction
      • UINavigationBar 내부에서 드래그를 시작하면 window를 움직일 수 있다.
        • pan 혹은 swipe 제스쳐가 있어도 잘 동작할거다.
      • UINavigationBar를 쓰지 않는다면, UIWindowSceneDragInteraction을 임의의 뷰에다가 채택하면 된다.
        • 컨플릭을 막기 위해 다른 제스쳐와의 관계 설정도 가능
      • Catalyst에서도 잘 동작
    • Sidebar behavior in Stage Manager
      • 창 크기가 일정 이하로 작아지면 자동으로 sidebar가 숨겨진다.
        • 이후 창크기를 늘려도, 명시적으로 다시 띄우기 전까지는 숨겨진채로 남는다.
      • 이후 sidebar가 필요한 경우는 overlay로 뜨거나, 대체 동작을 수행한다.
        • overlay는 창이 거쳐도 유지되고, 내렸다가 다시 띄우면 창 크기에 맞춰서 tiled나 overlay로 뜬다.
      • 이 동작은 UISplitViewController가 double column이나 triple column 스타일로 생성된다.
      • 이 동작은 preferredDisplayMode와 preferredSplitBehavior를 오버라이드 해서 컨트롤할 수 있다.
    • Keyboard Scrolling
      • 키보드 숏컷으로 스크롤링 가능
        • Page Up, Page Down, Home, End
        • iOS 17부터 기본적으로 활성화
        • allowsKeyboardScrolling 프로퍼티를 오버라이드 해서 조정할 수 있음
    • Improved document support
      • 새로운 UIDocumentViewController 클래스
        • 시스템 document앱의 경험을 추가 설정 없이 기본 제공
          • 자동으로 title menu 설정, 공유, 드래그 앤 드롭, 키 커맨드 등
      • UIDocument가 UINavigationItemRenameDelegate를 채택
        • UINavigationItem의 Delegate로 채택하면 renaming 기능을 완전히 사용할 수 있다.
    • Apple Pencil
  • General enhancements

  • UIMenu API가 tvOS도 지원