Xamarin.iOS의 통합 스토리보드

iOS 8에는 통합 스토리보드인 사용자 인터페이스를 만들기 위한 더 간단한 새로운 메커니즘이 포함되어 있습니다. 다양한 하드웨어 화면 크기를 모두 포괄하는 단일 스토리보드를 사용하면 빠르고 반응성이 뛰어난 보기를 "디자인 한 번, 다 사용" 스타일로 만들 수 있습니다.

개발자는 더 이상 i전화 및 iPad 디바이스에 대한 별도의 특정 스토리보드를 만들 필요가 없으므로 공통 인터페이스를 사용하여 애플리케이션을 디자인한 다음 다양한 크기 클래스에 맞게 해당 인터페이스를 사용자 지정할 수 있습니다. 이러한 방식으로 애플리케이션은 각 폼 팩터의 강점에 맞게 조정될 수 있으며 각 사용자 인터페이스를 조정하여 최상의 환경을 제공할 수 있습니다.

크기 클래스

iOS 8 이전에는 개발자가 세로 모드와 UIInterfaceIdiom 가로 모드, i전화 및 iPad 디바이스를 구분하는 데 사용 UIInterfaceOrientation 했습니다. iOS8에서 방향 및 디바이스는 크기 클래스를 사용하여 결정됩니다.

디바이스는 세로 축과 가로 축 모두에서 크기 클래스에 의해 정의되며 iOS 8에는 두 가지 유형의 크기 클래스가 있습니다.

  • 일반 – 큰 화면 크기(예: iPad) 또는 큰 크기의 인상을 주는 가젯(예: )을 위한 것입니다. UIScrollView
  • 압축 – 소형 디바이스(예: i전화)용입니다. 이 크기는 디바이스의 방향을 고려합니다.

두 개념을 함께 사용하는 경우 결과는 다음 다이어그램과 같이 서로 다른 방향 모두에서 사용할 수 있는 다양한 가능한 크기를 정의하는 2 x 2 그리드입니다.

A 2 x 2 grid that defines the different possible sizes that can be used in Regular and Compact orientations

개발자는 위의 그래픽에서 볼 수 있듯이 다양한 레이아웃을 생성할 수 있는 4가지 가능성 중 어느 것을 사용하는 뷰 컨트롤러를 만들 수 있습니다.

iPad 크기 클래스

크기로 인해 iPad는 두 방향 모두에 대한 일반 클래스 크기를 줍니다.

iPad Size Classes

i전화 크기 클래스

i전화 디바이스의 방향에 따라 다른 크기 클래스가 있습니다.

iPhone Size Classes

  • 디바이스가 세로 모드인 경우 화면에 가로 및 일반 세로로 컴팩트 클래스가 있습니다.
  • 디바이스가 가로 모드인 경우 화면 클래스는 세로 모드에서 반전됩니다.

i전화 6 더하기 크기 클래스

세로 방향의 경우 크기는 이전 i전화와 동일하지만 풍경은 다릅니다.

iPhone 6 Plus Size Classes

i전화 6 Plus에는 충분히 큰 화면이 있으므로 가로 모드에서 일반 너비 크기 클래스를 사용할 수 있습니다.

새 화면 크기 조정 지원

i전화 6 Plus는 화면 배율 3.0(원래 i전화 화면 해상도의 3배)의 새로운 Retina HD 디스플레이를 사용합니다. 이러한 디바이스에서 최상의 환경을 제공하려면 이 화면 크기를 위해 설계된 새 아트워크를 포함합니다. Xcode 6 이상에서 자산 카탈로그는 1x, 2x 및 3x 크기의 이미지를 포함할 수 있습니다. 단순히 새 이미지 자산을 추가하고 iOS는 i전화 6 Plus에서 실행할 때 올바른 자산을 선택합니다.

iOS의 이미지 로드 동작은 이미지 파일의 @3x 접미사도 인식합니다. 예를 들어 개발자가 애플리케이션의 번들에 다음 파일 이름이 MonkeyIcon.png있는 이미지 자산(다른 해상도)을 포함하는 경우 , MonkeyIcon@2x.pngMonkeyIcon@3x.png. i전화 6 Plus MonkeyIcon@3x.png 에서 개발자가 다음 코드를 사용하여 이미지를 로드하는 경우 이미지가 자동으로 사용됩니다.

UIImage icon = UIImage.FromFile("MonkeyImage.png");

동적 시작 화면

시작 화면 파일은 시작 화면으로 표시되며, iOS 애플리케이션은 앱이 실제로 시작 중이라는 피드백을 사용자에게 제공하기 위해 시작됩니다. iOS 8 이전에는 개발자가 애플리케이션이 실행될 각 디바이스 유형, 방향 및 화면 해상도에 대해 여러 Default.png 이미지 자산을 포함해야 합니다.

iOS 8을 새롭게 접하는 개발자는 자동 레이아웃 및 크기 클래스를 사용하여 모든 디바이스, 해상도 및 방향에 대해 작동하는 동적 시작 화면을 만드는 단일 원자성 .xib 파일을 Xcode에 만들 수 있습니다. 이렇게 하면 개발자가 필요한 모든 이미지 자산을 만들고 기본 데 필요한 작업량을 줄일 뿐만 아니라 애플리케이션의 설치된 번들의 크기가 줄어듭니다.

특성

특성은 환경이 변경될 때 레이아웃이 변경되는 방식을 결정하는 데 사용할 수 있는 속성입니다. 인터페이스 관용구() 및 표시 배율뿐만 아니라 속성 집합(HorizontalSizeClassUIUserInterfaceIdiomVerticalSizeClass 기준UIUserInterfaceSizeClass)으로 구성됩니다.

위의 모든 상태는 Apple이 특성 컬렉션() UITraitCollection으로 참조하는 컨테이너에 래핑됩니다. 여기에는 속성뿐만 아니라 해당 값도 포함됩니다.

특성 환경

특성 환경은 iOS 8의 새로운 인터페이스이며 다음 개체에 대한 특성 컬렉션을 반환할 수 있습니다.

  • 화면( UIScreens ).
  • Windows( UIWindows ).
  • 컨트롤러 보기( UIViewController ).
  • Views( UIView ).
  • 프레젠테이션 컨트롤러( UIPresentationController ).

개발자는 특성 환경에서 반환된 특성 컬렉션을 사용하여 사용자 인터페이스를 배치하는 방법을 결정합니다.

모든 특성 환경은 다음 다이어그램에 표시된 대로 계층 구조를 만듭니다.

The Trait Environments hierarchy diagram

위의 각 특성 환경에 있는 특성 컬렉션은 기본적으로 부모에서 자식 환경으로 흐릅니다.

특성 환경에는 TraitCollectionDidChange 현재 특성 컬렉션을 가져오는 것 외에도 뷰 또는 뷰 컨트롤러 하위 클래스에서 재정의할 수 있는 메서드가 있습니다. 개발자는 이 메서드를 사용하여 특성이 변경되었을 때 특성에 따라 달라지는 UI 요소를 수정할 수 있습니다.

일반적인 특성 컬렉션

이 섹션에서는 iOS 8로 작업할 때 사용자가 경험하게 될 일반적인 유형의 특성 컬렉션에 대해 설명합니다.

다음은 개발자가 i전화 볼 수 있는 일반적인 특성 컬렉션입니다.

속성
HorizontalSizeClass Compact
VerticalSizeClass Regular
UserInterfaceIdom 휴대폰
DisplayScale 2.0

위의 집합은 모든 특성 속성에 대한 값을 가지기 때문에 정규화된 특성 컬렉션을 나타냅니다.

또한 일부 값(Apple이 지정되지 않음이라고 지칭함)이 누락된 특성 컬렉션을 가질 수도 있습니다.

속성
HorizontalSizeClass Compact
VerticalSizeClass Unspecified
UserInterfaceIdom Unspecified
DisplayScale Unspecified

그러나 일반적으로 개발자가 특성 환경에 특성 컬렉션을 요청하면 위의 예제와 같이 정규화된 컬렉션을 반환합니다.

특성 환경(예: 뷰 또는 뷰 컨트롤러)이 현재 뷰 계층 구조 내에 없는 경우 개발자는 하나 이상의 특성 속성에 대해 지정되지 않은 값을 다시 가져올 수 있습니다.

또한 개발자는 Apple UITraitCollection.FromHorizontalSizeClass에서 제공하는 생성 방법 중 하나를 사용하여 새 컬렉션을 만드는 경우 부분적으로 정규화된 특성 컬렉션을 얻게 됩니다.

여러 특성 컬렉션에서 수행할 수 있는 한 가지 작업은 서로 비교하는 것입니다. 여기에는 한 특성 컬렉션에 다른 특성 컬렉션이 포함되어 있는지 묻는 작업이 포함됩니다. Containment의 의미는 두 번째 컬렉션에 지정된 특성의 경우 값이 첫 번째 컬렉션의 값과 정확히 일치해야 한다는 것입니다.

두 특성을 테스트하려면 테스트할 특성 값의 전달 방법을 UITraitCollection 사용합니다Contains.

개발자는 코드에서 수동으로 비교를 수행하여 뷰 또는 뷰 컨트롤러를 레이아웃하는 방법을 결정할 수 있습니다. 그러나 UIKit 이 메서드를 내부적으로 사용하여 모양 프록시와 같이 일부 기능을 제공합니다.

모양 프록시

모양 프록시는 개발자가 보기의 속성을 사용자 지정할 수 있도록 이전 버전의 iOS에서 도입되었습니다. 특성 컬렉션을 지원하도록 iOS 8에서 확장되었습니다.

이제 모양 프록시에는 전달된 지정된 특성 컬렉션에 대한 새 모양 프록시를 반환하는 새 메서드 AppearanceForTraitCollection가 포함됩니다. 개발자가 해당 모양 프록시에서 수행하는 모든 사용자 지정은 지정된 특성 컬렉션을 준수하는 뷰에만 적용됩니다.

일반적으로 개발자는 압축의 가로 크기 클래스를 지정한 것과 같이 부분적으로 지정된 특성 컬렉션을 AppearanceForTraitCollection 메서드에 전달하여 압축된 응용 프로그램의 보기를 가로로 사용자 지정할 수 있습니다.

UIImage

Apple이 Trait Collection을 추가한 또 다른 클래스는 .입니다 UIImage. 과거에 개발자는 애플리케이션에 포함할 비트맵 그래픽 자산의 @1X 및 @2x 버전을 지정해야 했습니다(예: 아이콘).

iOS 8은 개발자가 특성 컬렉션을 기반으로 이미지 카탈로그에 여러 버전의 이미지를 포함할 수 있도록 확장되었습니다. 예를 들어 개발자는 Compact Trait 클래스를 사용하기 위한 더 작은 이미지와 다른 컬렉션에 대한 전체 크기 이미지를 포함할 수 있습니다.

이미지 중 하나가 클래스 내에서 UIImageView 사용되는 경우 이미지 뷰는 해당 특성 컬렉션에 대한 이미지의 올바른 버전을 자동으로 표시합니다. 특성 환경이 변경되면(예: 사용자가 디바이스를 세로에서 가로로 전환) 이미지 보기는 새 특성 컬렉션과 일치하도록 새 이미지 크기를 자동으로 선택하고 표시되는 이미지의 현재 버전과 일치하도록 크기를 변경합니다.

UIImageAsset

Apple은 개발자에게 이미지 선택에 대한 더 많은 제어를 제공하기 위해 iOS 8에 UIImageAsset 새로운 클래스를 추가했습니다.

이미지 자산은 다양한 버전의 이미지를 모두 래핑하고 개발자가 전달된 특성 컬렉션과 일치하는 특정 이미지를 요청할 수 있도록 합니다. 이미지를 이미지 자산에서 즉시 추가하거나 제거할 수 있습니다.

이미지 자산에 대한 자세한 내용은 Apple의 UIImageAsset 설명서를 참조하세요.

특성 컬렉션 결합

개발자가 Trait Collections에서 수행할 수 있는 또 다른 함수는 결합된 컬렉션을 만드는 두 개의 함수를 함께 추가하는 것입니다. 여기서 한 컬렉션의 지정되지 않은 값은 두 번째 컬렉션의 지정된 값으로 바뀝니다. 이 작업은 클래스의 메서드를 FromTraitsFromCollections 사용하여 수행됩니다 UITraitCollection .

위에서 설명한 대로 특성 컬렉션 중 하나에서 특성이 지정되지 않고 다른 컬렉션에 지정된 경우 값은 지정된 버전으로 설정됩니다. 그러나 지정된 값의 여러 버전이 지정된 경우 마지막 특성 컬렉션의 값은 사용되는 값입니다.

적응형 뷰 컨트롤러

이 섹션에서는 iOS 보기 및 뷰 컨트롤러가 특성 및 크기 클래스의 개념을 채택하여 개발자의 애플리케이션에서 자동으로 적응하는 방법에 대해 자세히 설명합니다.

분할 보기 컨트롤러

iOS 8에서 가장 많이 변경된 뷰 컨트롤러 클래스 중 하나는 클래스입니다 UISplitViewController . 과거에 개발자는 애플리케이션의 iPad 버전에서 분할 보기 컨트롤러를 자주 사용한 다음 i전화 버전의 앱에 대해 완전히 다른 버전의 보기 계층 구조를 제공해야 했습니다.

iOS 8 UISplitViewController 에서 클래스는 두 플랫폼(iPad 및 i전화에서 모두 사용할 수 있으며, 이를 통해 개발자는 i전화 및 iPad 모두에 대해 작동하는 하나의 뷰 컨트롤러 계층 구조를 만들 수 있습니다.

i전화 가로에 있는 경우 분할 보기 컨트롤러는 iPad에 표시될 때와 마찬가지로 보기를 나란히 표시합니다.

특성 재정의

특성 환경은 가로 방향으로 iPad의 분할 보기 컨트롤러를 보여 주는 다음 그래픽과 같이 부모 컨테이너에서 자식 컨테이너로 계단식으로 연결됩니다.

A Split View Controller on an iPad in the landscape orientation

iPad에는 가로 방향과 세로 방향 모두에 일반 크기 클래스가 있으므로 분할 보기에는 마스터 보기와 세부 보기가 모두 표시됩니다.

크기 클래스가 두 방향 모두에서 압축된 i전화 분할 보기 컨트롤러는 아래와 같이 세부 정보 보기만 표시합니다.

The Split View Controller only displays the detail view

개발자가 가로 방향으로 i전화 마스터 보기와 세부 보기를 모두 표시하려는 애플리케이션에서 개발자는 분할 뷰 컨트롤러에 대한 부모 컨테이너를 삽입하고 특성 컬렉션을 재정의해야 합니다. 아래 그래픽에서 볼 수 있듯이 다음을 수행합니다.

The developer must insert a parent container for the Split View Controller and override the Trait Collection

A UIView 는 분할 뷰 컨트롤러의 부모로 설정되며 새 특성 컬렉션을 전달하고 SetOverrideTraitCollection 분할 보기 컨트롤러를 대상으로 하는 보기에서 메서드가 호출됩니다. 새 Trait 컬렉션HorizontalSizeClassRegular은 분할 뷰 컨트롤러가 가로 방향으로 i전화 마스터 보기와 세부 보기를 모두 표시하도록 설정하여 재정의합니다.

부모에 VerticalSizeClass 있는 Trait 컬렉션에 unspecified새 Trait 컬렉션을 추가할 수 있도록 설정되었으므로 자식 분할 뷰 컨트롤러에 대한 특성 컬렉션 Compact VerticalSizeClass 이 생성됩니다.

특성 변경

이 섹션에서는 특성 환경이 변경될 때 특성 컬렉션이 어떻게 전환되는지 자세히 살펴봅니다. 예를 들어 디바이스가 세로에서 가로로 회전되는 경우입니다.

The portrait to landscape Trait Changes overview

먼저 iOS 8은 전환이 수행되도록 준비하기 위해 몇 가지 설정을 수행합니다. 다음으로, 시스템은 전환 상태에 애니메이션 효과를 갖습니다. 마지막으로, iOS 8은 전환 중에 필요한 임시 상태를 클린.

iOS 8은 다음 표와 같이 개발자가 특성 변경에 참여하는 데 사용할 수 있는 몇 가지 콜백을 제공합니다.

단계 콜백 설명
설정
  • WillTransitionToTraitCollection
  • TraitCollectionDidChange
  • 이 메서드는 특성 컬렉션이 새 값으로 설정되기 전에 특성 변경의 시작 부분에서 호출됩니다.
  • 특성 컬렉션의 값이 변경되었지만 애니메이션이 발생하기 전에 메서드가 호출됩니다.
애니메이션 WillTransitionToTraitCollection 이 메서드에 전달되는 전환 코디네이터에는 AnimateAlongside 개발자가 기본 애니메이션과 함께 실행될 애니메이션을 추가할 수 있는 속성이 있습니다.
정리 WillTransitionToTraitCollection 전환이 일어난 후 개발자가 고유한 클린up 코드를 포함할 수 있는 메서드를 제공합니다.

WillTransitionToTraitCollection 메서드는 특성 컬렉션 변경 내용과 함께 뷰 컨트롤러에 애니메이션 효과를 주는 데 적합합니다. 이 WillTransitionToTraitCollection 메서드는 뷰 컨트롤러( UIViewController)에서만 사용할 수 있으며 같은 다른 특성 환경에서는 UIViews사용할 수 없습니다.

특성 TraitCollectionDidChange 이 변경됨에 따라 개발자가 UI를 업데이트하려는 클래스를 사용하는 UIView 데 적합합니다.

분할 보기 컨트롤러 축소

이제 분할 보기 컨트롤러가 두 열에서 하나의 열 보기로 축소되면 어떻게 되는지 자세히 살펴보겠습니다. 이 변경의 일부로 수행해야 하는 두 가지 프로세스가 있습니다.

  • 기본적으로 분할 보기 컨트롤러는 축소가 발생한 후 기본 뷰 컨트롤러를 뷰로 사용합니다. 개발자는 메서드를 재정의하고 GetPrimaryViewControllerForCollapsingSplitViewController 축소된 상태로 표시하려는 뷰 컨트롤러를 제공하여 이 동작을 재정의 UISplitViewControllerDelegate 할 수 있습니다.
  • 보조 뷰 컨트롤러는 기본 뷰 컨트롤러에 병합해야 합니다. 일반적으로 개발자는 이 단계에 대해 어떠한 조치도 취할 필요가 없습니다. 분할 보기 컨트롤러에는 하드웨어 디바이스를 기반으로 하는 이 단계의 자동 처리가 포함됩니다. 그러나 개발자가 이 변경 내용과 상호 작용하려는 몇 가지 특별한 경우가 있을 수 있습니다. 메서드 UISplitViewControllerDelegateCollapseSecondViewController 호출하면 세부 정보 보기 대신 축소가 발생할 때 마스터 뷰 컨트롤러를 표시할 수 있습니다.

분할 보기 컨트롤러 확장

이제 분할 보기 컨트롤러가 축소된 상태에서 확장될 때 발생하는 일을 좀 더 자세히 살펴보겠습니다. 다시 한 번 수행해야 하는 두 단계가 있습니다.

  • 먼저 새 기본 뷰 컨트롤러를 정의합니다. 기본적으로 분할 보기 컨트롤러는 축소된 보기에서 기본 뷰 컨트롤러를 자동으로 사용합니다. 다시 말하지만, 개발자는 의 메서드를 사용하여 이 동작을 GetPrimaryViewControllerForExpandingSplitViewController 재정의할 UISplitViewControllerDelegate 수 있습니다.
  • 기본 뷰 컨트롤러가 선택되면 보조 뷰 컨트롤러를 다시 만들어야 합니다. 다시 말하지만, 분할 보기 컨트롤러에는 하드웨어 디바이스에 따라 이 단계의 자동 처리가 포함됩니다. 개발자는 의 메서드를 호출하여 이 동작을 SeparateSecondaryViewController 재정의할 UISplitViewControllerDelegate 수 있습니다.

분할 보기 컨트롤러에서 기본 뷰 컨트롤러는 뷰의 확장 및 축소에서 모두의 UISplitViewControllerDelegate역할을 수행 CollapseSecondViewControllerSeparateSecondaryViewController 합니다. UINavigationController 는 보조 뷰 컨트롤러를 자동으로 푸시하고 팝하는 이러한 메서드를 구현합니다.

보기 컨트롤러 표시

Apple이 iOS 8에 적용한 또 다른 변경 사항은 개발자가 보기 컨트롤러를 표시하는 방식입니다. 과거에 애플리케이션에 리프 뷰 컨트롤러(예: 테이블 뷰 컨트롤러)가 있고 개발자가 다른 컨트롤러(예: 셀을 탭하는 사용자에 대한 응답으로)를 표시한 경우 애플리케이션은 컨트롤러 계층을 통해 탐색 뷰 컨트롤러로 다시 연결하고 메서드를 호출 PushViewController 하여 새 보기를 표시합니다.

이것은 탐색 컨트롤러와 실행 중인 환경 간에 매우 긴밀한 결합을 제공했습니다. iOS 8에서 Apple은 다음 두 가지 새로운 방법을 제공하여 이를 분리했습니다.

  • ShowViewController – 환경에 따라 새 뷰 컨트롤러를 표시하도록 조정합니다. 예를 들어 새 뷰를 UINavigationController 스택에 푸시하기만 하면 됩니다. 분할 보기 컨트롤러에서 새 뷰 컨트롤러는 왼쪽에 새 기본 뷰 컨트롤러로 표시됩니다. 컨테이너 뷰 컨트롤러가 없으면 새 보기가 모달 뷰 컨트롤러로 표시됩니다.
  • ShowDetailViewController – 분할 보기 컨트롤러와 비슷한 방식으로 ShowViewController작동하지만 세부 정보 보기를 전달되는 새 뷰 컨트롤러로 바꾸기 위해 분할 보기 컨트롤러에서 구현됩니다. i전화 애플리케이션에서 볼 수 있듯이 분할 보기 컨트롤러가 축소되면 호출이 메서드로 ShowViewController 리디렉션되고 새 보기가 기본 뷰 컨트롤러로 표시됩니다. 컨테이너 뷰 컨트롤러가 없으면 새 보기가 모달 뷰 컨트롤러로 표시됩니다.

이러한 메서드는 리프 뷰 컨트롤러에서 시작하여 새 보기의 표시를 처리할 올바른 컨테이너 뷰 컨트롤러를 찾을 때까지 뷰 계층 구조를 안내합니다.

개발자는 자체 사용자 지정 뷰 컨트롤러를 구현 ShowViewController 하고 ShowDetailViewController 구현하여 제공하는 것과 동일한 자동화된 기능을 UINavigationControllerUISplitViewController 얻을 수 있습니다.

작동 방식

이 섹션에서는 이러한 메서드가 iOS 8에서 실제로 구현되는 방법을 살펴보겠습니다. 먼저 새 GetTargetForAction 메서드를 살펴보겠습니다.

The new GetTargetForAction method

이 메서드는 올바른 컨테이너 뷰 컨트롤러를 찾을 때까지 계층 체인을 안내합니다. 예시:

  1. 메서드가 ShowViewController 호출되면 이 메서드를 구현하는 체인의 첫 번째 뷰 컨트롤러는 탐색 컨트롤러이므로 새 뷰의 부모로 사용됩니다.
  2. 대신 메서드를 호출한 ShowDetailViewController 경우 분할 보기 컨트롤러는 구현하는 첫 번째 뷰 컨트롤러이므로 부모로 사용됩니다.

이 메서드는 GetTargetForAction 지정된 작업을 구현하는 뷰 컨트롤러를 찾은 다음 뷰 컨트롤러에 해당 작업을 받을 것인지 묻는 방법으로 작동합니다. 이 메서드는 공용이므로 개발자는 기본 제공 ShowViewControllerShowDetailViewController 메서드처럼 작동하는 고유한 사용자 지정 메서드를 만들 수 있습니다.

적응형 프레젠테이션

iOS 8에서 Apple은 팝오버 프레젠테이션( UIPopoverPresentationController)도 적응형으로 만들었습니다. 따라서 팝오버 프레젠테이션 보기 컨트롤러는 일반 크기 클래스에 일반 팝오버 보기를 자동으로 표시하지만 전체 화면을 가로로 압축된 크기 클래스(예: i전화)로 표시합니다.

통합 스토리보드 시스템 내의 변경 내용을 수용하기 위해 제공된 뷰 컨트롤러를 관리하기 위해 새 컨트롤러 UIPresentationController개체가 만들어졌습니다. 이 컨트롤러는 뷰 컨트롤러가 표시될 때부터 해제될 때까지 만들어집니다. 관리 클래스이므로 뷰 컨트롤러가 뷰 컨트롤러(예: 방향)에 영향을 주는 디바이스 변경 내용에 응답할 때 뷰 컨트롤러를 통해 슈퍼 클래스로 간주될 수 있습니다. 그러면 프레젠테이션 컨트롤러가 제어하는 뷰 컨트롤러에 다시 공급됩니다.

개발자가 메서드를 사용하여 뷰 컨트롤러를 PresentViewController 제시하면 프레젠테이션 프로세스의 관리가 전달 UIKit됩니다. UIKit은 뷰 컨트롤러에 스타일이 설정된 경우를 제외하고 생성되는 스타일에 대한 올바른 컨트롤러를 처리합니다 UIModalPresentationCustom. 여기서 애플리케이션은 컨트롤러를 사용하는 대신 자체 PresentationController를 UIKit 제공할 수 있습니다.

사용자 지정 프레젠테이션 스타일

개발자는 사용자 지정 프레젠테이션 스타일을 사용하여 사용자 지정 프레젠테이션 컨트롤러를 사용할 수 있습니다. 이 사용자 지정 컨트롤러를 사용하여 연결된 보기의 모양과 동작을 수정할 수 있습니다.

크기 클래스 작업

이 문서에 포함된 적응형 사진 Xamarin 프로젝트는 iOS 8 통합 인터페이스 애플리케이션에서 크기 클래스 및 적응형 뷰 컨트롤러를 사용하는 작업 예제를 제공합니다.

애플리케이션은 Xcode의 인터페이스 작성기를 사용하여 통합 스토리보드를 만드는 것과 달리 코드에서 UI를 완전히 만들지만 동일한 기술이 적용됩니다.

이제 적응형 사진 프로젝트가 적응형 애플리케이션을 만들기 위해 iOS 8의 여러 Size 클래스 기능을 구현하는 방법을 자세히 살펴보겠습니다.

특성 환경 변경에 맞게 조정

i전화 적응형 사진 애플리케이션을 실행할 때 사용자가 디바이스를 세로에서 가로로 회전하면 분할 보기 컨트롤러에 마스터 및 세부 정보 보기가 모두 표시됩니다.

The Split View Controller will display both the master and details view as seen here

이 작업은 뷰 컨트롤러의 메서드를 UpdateConstraintsForTraitCollection 재정의하고 값에 VerticalSizeClass따라 제약 조건을 조정하여 수행됩니다. 예시:

public void UpdateConstraintsForTraitCollection (UITraitCollection collection)
{
    var views = NSDictionary.FromObjectsAndKeys (
        new object[] { TopLayoutGuide, ImageView, NameLabel, ConversationsLabel, PhotosLabel },
        new object[] { "topLayoutGuide", "imageView", "nameLabel", "conversationsLabel", "photosLabel" }
    );

    var newConstraints = new List<NSLayoutConstraint> ();
    if (collection.VerticalSizeClass == UIUserInterfaceSizeClass.Compact) {
        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("|[imageView]-[nameLabel]-|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("[imageView]-[conversationsLabel]-|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("[imageView]-[photosLabel]-|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("V:|[topLayoutGuide]-[nameLabel]-[conversationsLabel]-[photosLabel]",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("V:|[topLayoutGuide][imageView]|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.Add (NSLayoutConstraint.Create (ImageView, NSLayoutAttribute.Width, NSLayoutRelation.Equal,
            View, NSLayoutAttribute.Width, 0.5f, 0.0f));
    } else {
        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("|[imageView]|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("|-[nameLabel]-|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("|-[conversationsLabel]-|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("|-[photosLabel]-|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));

        newConstraints.AddRange (NSLayoutConstraint.FromVisualFormat ("V:[topLayoutGuide]-[nameLabel]-[conversationsLabel]-[photosLabel]-20-[imageView]|",
            NSLayoutFormatOptions.DirectionLeadingToTrailing, null, views));
    }

    if (constraints != null)
        View.RemoveConstraints (constraints.ToArray ());

    constraints = newConstraints;
    View.AddConstraints (constraints.ToArray ());
}

전환 애니메이션 추가

적응형 사진 애플리케이션의 분할 보기 컨트롤러가 축소에서 확장됨으로 이동하면 뷰 컨트롤러의 메서드를 재정의하여 WillTransitionToTraitCollection 애니메이션이 기본 애니메이션에 추가됩니다. 예시:

public override void WillTransitionToTraitCollection (UITraitCollection traitCollection, IUIViewControllerTransitionCoordinator coordinator)
{
    base.WillTransitionToTraitCollection (traitCollection, coordinator);
    coordinator.AnimateAlongsideTransition ((UIViewControllerTransitionCoordinatorContext) => {
        UpdateConstraintsForTraitCollection (traitCollection);
        View.SetNeedsLayout ();
    }, (UIViewControllerTransitionCoordinatorContext) => {
    });
}

특성 환경 재정의

위와 같이 적응형 사진 애플리케이션은 i전화 디바이스가 가로 보기에 있을 때 분할 보기 컨트롤러가 세부 정보와 마스터 보기를 모두 표시하도록 합니다.

이 작업은 뷰 컨트롤러에서 다음 코드를 사용하여 수행되었습니다.

private UITraitCollection forcedTraitCollection = new UITraitCollection ();
...

public UITraitCollection ForcedTraitCollection {
    get {
        return forcedTraitCollection;
    }

    set {
        if (value != forcedTraitCollection) {
            forcedTraitCollection = value;
            UpdateForcedTraitCollection ();
        }
    }
}
...

public override void ViewWillTransitionToSize (SizeF toSize, IUIViewControllerTransitionCoordinator coordinator)
{
    ForcedTraitCollection = toSize.Width > 320.0f ?
         UITraitCollection.FromHorizontalSizeClass (UIUserInterfaceSizeClass.Regular) :
         new UITraitCollection ();

    base.ViewWillTransitionToSize (toSize, coordinator);
}

public void UpdateForcedTraitCollection ()
{
    SetOverrideTraitCollection (forcedTraitCollection, viewController);
}

분할 보기 컨트롤러 확장 및 축소

다음으로 Xamarin에서 분할 뷰 컨트롤러의 확장 및 축소 동작이 어떻게 구현되었는지 살펴보겠습니다. AppDelegate에서 분할 뷰 컨트롤러를 만들 때 해당 대리자는 다음과 같은 변경 내용을 처리하도록 할당됩니다.

public class SplitViewControllerDelegate : UISplitViewControllerDelegate
{
    public override bool CollapseSecondViewController (UISplitViewController splitViewController,
        UIViewController secondaryViewController, UIViewController primaryViewController)
    {
        AAPLPhoto photo = ((CustomViewController)secondaryViewController).Aapl_containedPhoto (null);
        if (photo == null) {
            return true;
        }

        if (primaryViewController.GetType () == typeof(CustomNavigationController)) {
            var viewControllers = new List<UIViewController> ();
            foreach (var controller in ((UINavigationController)primaryViewController).ViewControllers) {
                var type = controller.GetType ();
                MethodInfo method = type.GetMethod ("Aapl_containsPhoto");

                if ((bool)method.Invoke (controller, new object[] { null })) {
                    viewControllers.Add (controller);
                }
            }

            ((UINavigationController)primaryViewController).ViewControllers = viewControllers.ToArray<UIViewController> ();
        }

        return false;
    }

    public override UIViewController SeparateSecondaryViewController (UISplitViewController splitViewController,
        UIViewController primaryViewController)
    {
        if (primaryViewController.GetType () == typeof(CustomNavigationController)) {
            foreach (var controller in ((CustomNavigationController)primaryViewController).ViewControllers) {
                var type = controller.GetType ();
                MethodInfo method = type.GetMethod ("Aapl_containedPhoto");

                if (method.Invoke (controller, new object[] { null }) != null) {
                    return null;
                }
            }
        }

        return new AAPLEmptyViewController ();
    }
}

이 메서드는 SeparateSecondaryViewController 사진이 표시되는지 테스트하고 해당 상태에 따라 작업을 수행합니다. 사진이 표시되지 않으면 마스터 뷰 컨트롤러가 표시되도록 보조 뷰 컨트롤러가 축소됩니다.

CollapseSecondViewController 메서드는 분할 보기 컨트롤러를 확장하여 스택에 사진이 있는지 확인하는 경우 해당 보기로 축소되는 경우에 사용됩니다.

보기 컨트롤러 간 이동

다음으로 적응형 사진 애플리케이션이 보기 컨트롤러 간에 이동하는 방식을 살펴보겠습니다. AAPLConversationViewController 클래스에서 사용자가 테이블에서 ShowDetailViewController 셀을 선택하면 메서드가 호출되어 세부 정보 보기를 표시합니다.

public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
    var photo = PhotoForIndexPath (indexPath);
    var controller = new AAPLPhotoViewController ();
    controller.Photo = photo;

    int photoNumber = indexPath.Row + 1;
    int photoCount = (int)Conversation.Photos.Count;
    controller.Title = string.Format ("{0} of {1}", photoNumber, photoCount);
    ShowDetailViewController (controller, this);
}

공개 표시기 표시

적응형 사진 애플리케이션에는 특성 환경의 변경 내용에 따라 공개 표시기가 숨겨지거나 표시되는 여러 위치가 있습니다. 이 작업은 다음 코드로 처리됩니다.

public bool Aapl_willShowingViewControllerPushWithSender ()
{
    var selector = new Selector ("Aapl_willShowingViewControllerPushWithSender");
    var target = this.GetTargetViewControllerForAction (selector, this);

    if (target != null) {
        var type = target.GetType ();
        MethodInfo method = type.GetMethod ("Aapl_willShowingDetailViewControllerPushWithSender");
        return (bool)method.Invoke (target, new object[] { });
    } else {
        return false;
    }
}

public bool Aapl_willShowingDetailViewControllerPushWithSender ()
{
    var selector = new Selector ("Aapl_willShowingDetailViewControllerPushWithSender");
    var target = this.GetTargetViewControllerForAction (selector, this);

    if (target != null) {
        var type = target.GetType ();
        MethodInfo method = type.GetMethod ("Aapl_willShowingDetailViewControllerPushWithSender");
        return (bool)method.Invoke (target, new object[] { });
    } else {
        return false;
    }
}

이러한 항목은 위에서 자세히 설명한 메서드를 GetTargetViewControllerForAction 사용하여 구현됩니다.

테이블 뷰 컨트롤러가 데이터를 표시하는 경우 위에서 구현한 메서드를 사용하여 푸시가 수행될지 여부와 그에 따라 공개 표시기를 표시하거나 숨길지 여부를 확인합니다.

public override void WillDisplay (UITableView tableView, UITableViewCell cell, NSIndexPath indexPath)
{
    bool pushes = ShouldShowConversationViewForIndexPath (indexPath) ?
         Aapl_willShowingViewControllerPushWithSender () :
         Aapl_willShowingDetailViewControllerPushWithSender ();

    cell.Accessory = pushes ? UITableViewCellAccessory.DisclosureIndicator : UITableViewCellAccessory.None;
    var conversation = ConversationForIndexPath (indexPath);
    cell.TextLabel.Text = conversation.Name;
}

ShowDetailTargetDidChangeNotification 형식

Apple은 분할 보기 컨트롤러 ShowDetailTargetDidChangeNotification내에서 크기 클래스 및 특성 환경 작업을 위한 새로운 알림 유형을 추가했습니다. 이 알림은 컨트롤러가 확장되거나 축소되는 경우와 같이 분할 보기 컨트롤러의 대상 세부 정보 보기가 변경되면 전송됩니다.

적응형 사진 애플리케이션은 이 알림을 사용하여 세부 정보 보기 컨트롤러가 변경되면 공개 표시기의 상태를 업데이트합니다.

public override void ViewDidLoad ()
{
    base.ViewDidLoad ();
    TableView.RegisterClassForCellReuse (typeof(UITableViewCell), AAPLListTableViewControllerCellIdentifier);
    NSNotificationCenter.DefaultCenter.AddObserver (this, new Selector ("showDetailTargetDidChange:"),
        UIViewController.ShowDetailTargetDidChangeNotification, null);
    ClearsSelectionOnViewWillAppear = false;
}

적응형 사진 애플리케이션을 자세히 살펴보고 Xamarin.iOS에서 통합 애플리케이션을 쉽게 만드는 데 크기 클래스, 특성 컬렉션 및 적응형 뷰 컨트롤러를 사용할 수 있는 모든 방법을 알아봅니다.

통합 Storyboards

iOS 8을 새롭게 접하는 통합 스토리보드를 통해 개발자는 여러 크기 클래스를 대상으로 하여 i전화 및 iPad 디바이스 모두에 표시할 수 있는 통합 스토리보드 파일을 만들 수 있습니다. 개발자는 통합 스토리보드를 사용하여 UI 관련 코드를 적게 작성하고 만들려는 인터페이스 디자인이 하나만 기본.

통합 스토리보드의 주요 이점은 다음과 같습니다.

  • i전화 및 iPad에 대해 동일한 스토리보드 파일을 사용합니다.
  • iOS 6 및 iOS 7에 이전 버전으로 배포합니다.
  • 다양한 디바이스, 방향 및 OS 버전에 대한 레이아웃을 미리 봅니다.

크기 클래스 사용

기본적으로 새 Xamarin.iOS 프로젝트는 크기 클래스를 사용합니다. 이전 프로젝트의 스토리보드 내에서 크기 클래스 및 적응형 Segues를 사용하려면 먼저 Xcode 6 통합 스토리보드 형식으로 변환해야 하며 스토리보드의 Xcode 파일 검사기 내에서 크기 클래스 검사 사용 상자가 선택됩니다.

동적 시작 화면

시작 화면 파일은 시작 화면으로 표시되며, iOS 애플리케이션은 앱이 실제로 시작 중이라는 피드백을 사용자에게 제공하기 위해 시작됩니다. iOS 8 이전에는 개발자가 애플리케이션이 실행될 각 디바이스 유형, 방향 및 화면 해상도에 대해 여러 Default.png 이미지 자산을 포함해야 합니다. 예: Default@2x.png, Default-Landscape@2x~ipad.png, Default-Portrait@2x~ipad.png

모든 기존 i전화 및 iPad 장치와 함께 새로운 i전화6 및 i전화 6 Plus 디바이스(및 예정된 Apple Watch)를 고려할 때, 이는 생성되고 기본 확인해야 하는 시작 화면 이미지 자산의 다양한 크기, 방향 및 해상도의 Default.png 큰 배열을 나타냅니다. 또한 이러한 파일은 상당히 클 수 있으며 결과물 애플리케이션 번들을 "bloat"하여 iTunes App Store에서 애플리케이션을 다운로드하는 데 필요한 시간을 늘리고(셀룰러 네트워크를 통해 배달할 수 없도록 할 수 있음) 최종 사용자의 장치에 필요한 스토리지의 양을 늘릴 수 있습니다.

iOS 8을 새롭게 접하는 개발자는 자동 레이아웃 및 크기 클래스를 사용하여 모든 디바이스, 해상도 및 방향에 대해 작동하는 동적 시작 화면을 만드는 단일 원자성 .xib 파일을 Xcode에 만들 수 있습니다. 이렇게 하면 개발자가 필요한 모든 이미지 자산을 만들고 기본 데 필요한 작업량을 줄일 뿐만 아니라 애플리케이션의 설치된 번들의 크기가 크게 줄어듭니다.

동적 시작 화면에는 다음과 같은 제한 사항과 고려 사항이 있습니다.

  • 클래스만 UIKit 사용합니다.
  • 개체 UIViewController 인 단일 루트 뷰를 UIView 사용합니다.
  • 애플리케이션의 코드에 연결하지 마세요(작업 또는 출선 추가 안 함).
  • 개체를 추가 UIWebView 하지 마세요.
  • 사용자 지정 클래스를 사용하지 마세요.
  • 런타임 특성을 사용하지 마세요.

위의 지침을 염두에 두고 기존 Xamarin iOS 8 프로젝트에 동적 시작 화면을 추가하는 방법을 살펴보겠습니다.

다음을 수행합니다.

  1. Mac용 Visual Studio 열고 솔루션을 로드하여 동적 시작 화면을 추가합니다.

  2. 솔루션 탐색기 파일을 마우스 오른쪽 단추로 클릭하고 MainStoryboard.storyboard Xcode 인터페이스 작성기를 사용하여>열기를 선택합니다.

    Open With Xcode Interface Builder

  3. Xcode에서 새>파일 파일>...을 선택합니다.

    Select File / New

  4. iOS>사용자 인터페이스>시작 화면을 선택하고 다음 단추를 클릭합니다.

    Select iOS / User Interface / Launch Screen

  5. 파일 LaunchScreen.xib 이름을 지정하고 만들기 단추를 클릭합니다.

    Name the file LaunchScreen.xib

  6. 그래픽 요소를 추가하고 레이아웃 제약 조건을 사용하여 지정된 디바이스, 방향 및 화면 크기에 맞게 배치하여 시작 화면의 디자인을 편집합니다.

    Editing the design of the launch screen

  7. LaunchScreen.xib에 변경 내용을 저장합니다.

  8. 애플리케이션 대상 및 일반 탭을 선택합니다.

    Select the Applications Target and the General tab

  9. Info.plist 선택 단추를 클릭하고 Xamarin 앱에 대해 선택한 Info.plist 다음 선택 단추를 클릭합니다.

    Select the Info.plist for the Xamarin app

  10. 앱 아이콘 및 이미지 시작 섹션에서 시작 화면 파일 드롭다운을 열고 위에서 만든 것을 LaunchScreen.xib 선택합니다.

    Choose the LaunchScreen.xib

  11. 변경 내용을 파일에 저장하고 Mac용 Visual Studio 돌아갑니다.

  12. Mac용 Visual Studio Xcode와의 변경 내용 동기화가 완료되기를 기다립니다.

  13. 솔루션 탐색기 리소스 폴더를 마우스 오른쪽 단추로 클릭하고 파일 추가>...를 선택합니다.

    Select Add / Add Files...

  14. LaunchScreen.xib 위에서 만든 파일을 선택하고 열기 단추를 클릭합니다.

    Select the LaunchScreen.xib file

  15. 애플리케이션을 빌드합니다.

동적 시작 화면 테스트

Mac용 Visual Studio i전화 4 Retina 시뮬레이터를 선택하고 애플리케이션을 실행합니다. 동적 시작 화면은 올바른 형식과 방향으로 표시됩니다.

The Dynamic Launch Screen displayed in the vertical orientation

Mac용 Visual Studio 애플리케이션을 중지하고 iPad iOS 8 디바이스를 선택합니다. 애플리케이션을 실행하면 시작 화면이 이 디바이스 및 방향에 대해 올바르게 형식이 지정됩니다.

The Dynamic Launch Screen displayed in the horizontal orientation

Mac용 Visual Studio 돌아가서 애플리케이션의 실행을 중지합니다.

iOS 7 작업

iOS 7과의 이전 버전과의 호환성을 기본 위해 iOS 8 애플리케이션에서 일반적인 Default.png 이미지 자산을 정상적으로 포함하기만 하면 됩니다. iOS는 이전 동작으로 돌아가서 iOS 7 디바이스에서 실행할 때 해당 파일을 시작 화면으로 사용합니다.

Xamarin에서 동적 실행 화면의 구현을 보려면 이 문서에 첨부된 동적 실행 화면 샘플 iOS 8 애플리케이션을 참조하세요.

요약

이 문서에서는 크기 클래스와 i전화 및 iPad 장치의 레이아웃에 미치는 영향을 간단히 살펴보았습니다. 특성, 특성 환경 및 특성 컬렉션이 크기 클래스와 함께 작동하여 통합 인터페이스를 만드는 방법을 설명했습니다. 적응형 뷰 컨트롤러와 통합 인터페이스 내에서 크기 클래스를 사용하는 방법을 간략하게 살펴보았습니다. Xamarin iOS 8 애플리케이션 내의 C# 코드에서 크기 클래스 및 통합 인터페이스를 완전히 구현하는 것을 살펴보았습니다.

마지막으로, 이 문서에서는 모든 iOS 8 디바이스에서 시작 화면으로 표시될 단일 동적 시작 화면을 만드는 기본 사항을 설명했습니다.