Xamarin.Mac의 데이터 바인딩 및 키-값 코딩
이 문서에서는 Xcode의 인터페이스 작성기에서 UI 요소에 데이터 바인딩을 허용하기 위해 키-값 코딩 및 키-값 관찰을 사용하는 방법을 설명합니다.
개요
Xamarin.Mac 애플리케이션에서 C# 및 .NET을 사용하는 경우 개발자와 Xcode에서 Objective-C 작업하는 것과 동일한 키-값 코딩 및 데이터 바인딩 기술에 액세스할 수 있습니다. Xamarin.Mac은 Xcode와 직접 통합되므로 코드를 작성하는 대신 Xcode의 인터페이스 작성기를 사용하여 UI 요소를 사용하여 데이터 바인딩에 사용할 수 있습니다.
Xamarin.Mac 애플리케이션에서 키-값 코딩 및 데이터 바인딩 기술을 사용하면 UI 요소를 채우고 작업하기 위해 작성하고 기본 코드의 양을 크게 줄일 수 있습니다. 또한 프런트 엔드 사용자 인터페이스(Model-View-Controller)에서 백업 데이터(데이터 모델)를 추가로 분리하여 보다 기본 더 유연하고 유연한 애플리케이션 디자인을 얻을 수 있습니다.
이 문서에서는 Xamarin.Mac 애플리케이션에서 키-값 코딩 및 데이터 바인딩을 사용하는 기본 사항을 설명합니다. 이 문서에서 사용할 주요 개념과 기술을 다루므로 Hello, Mac 문서, 특히 Xcode 및 인터페이스 작성기 및 콘센트 및 작업 소개 섹션을 통해 작업하는 것이 좋습니다.
Xamarin.Mac Internals 문서의 섹션에 Objective-C대한 C# 클래스/메서드 노출을 살펴보고 C# 클래스 Objective-C 를 개체 및 UI 요소에 연결하는 데 사용되는 특성과 Export
특성을 설명 Register
합니다.
키-값 코딩이란?
KVC(키-값 코딩)는 인스턴스 변수 또는 접근자 메서드()를 통해 액세스하는 대신 키(특수 형식 문자열)를 사용하여 속성을 식별하여 개체의 속성에get/set
간접적으로 액세스하는 메커니즘입니다. Xamarin.Mac 애플리케이션에서 키-값 코딩 규격 접근자를 구현하면 KVO(키-값 관찰), 데이터 바인딩, 코어 데이터, Cocoa 바인딩 및 스크립트 기능과 같은 다른 macOS(이전의 OS X) 기능에 액세스할 수 있습니다.
Xamarin.Mac 애플리케이션에서 키-값 코딩 및 데이터 바인딩 기술을 사용하면 UI 요소를 채우고 작업하기 위해 작성하고 기본 코드의 양을 크게 줄일 수 있습니다. 또한 프런트 엔드 사용자 인터페이스(Model-View-Controller)에서 백업 데이터(데이터 모델)를 추가로 분리하여 보다 기본 더 유연하고 유연한 애플리케이션 디자인을 얻을 수 있습니다.
예를 들어 KVC 규격 개체의 다음 클래스 정의를 살펴보겠습니다.
using System;
using Foundation;
namespace MacDatabinding
{
[Register("PersonModel")]
public class PersonModel : NSObject
{
private string _name = "";
[Export("Name")]
public string Name {
get { return _name; }
set {
WillChangeValue ("Name");
_name = value;
DidChangeValue ("Name");
}
}
public PersonModel ()
{
}
}
}
먼저 특성이 [Register("PersonModel")]
클래스를 등록하고 클래스를 Objective-C노출합니다. 그런 다음 클래스에서 NSObject
상속해야 합니다(또는 상속 NSObject
되는 하위 클래스). 이렇게 하면 클래스가 KVC 규격이 될 수 있는 몇 가지 기본 메서드가 추가됩니다. 다음으로, 특성은 [Export("Name")]
속성을 노출 Name
하고 나중에 KVC 및 KVO 기술을 통해 속성에 액세스하는 데 사용할 키 값을 정의합니다.
마지막으로 속성 값에 대한 Key-Value Observed 변경 내용을 적용하려면 접근자가 해당 값 WillChangeValue
의 변경 내용과 메서드 호출(특성과 DidChangeValue
동일한 키를 지정)을 Export
래핑해야 합니다. 예시:
set {
WillChangeValue ("Name");
_name = value;
DidChangeValue ("Name");
}
이 단계는 Xcode의 인터페이스 작성기에서 데이터 바인딩에 매우 중요합니다(이 문서의 뒷부분에서 볼 수 있듯이).
자세한 내용은 Apple의 키-값 코딩 프로그래밍 가이드를 참조하세요.
키 및 키 경로
키는 개체의 특정 속성을 식별하는 문자열입니다. 일반적으로 키는 키-값 코딩 규격 개체의 접근자 메서드 이름에 해당합니다. 키는 ASCII 인코딩을 사용해야 하며 일반적으로 소문자로 시작하며 공백을 포함하지 않을 수 있습니다. 따라서 위의 Name
예제를 고려할 때 클래스의 Name
속성 키 값이 PersonModel
됩니다. 공개하는 속성의 키와 이름은 동일할 필요는 없습니다. 그러나 대부분의 경우 동일합니다.
키 경로는 트래버스할 개체 속성의 계층 구조를 지정하는 데 사용되는 점 구분 키의 문자열입니다. 시퀀스에서 첫 번째 키의 속성은 수신기를 기준으로 하며 각 후속 키는 이전 속성의 값을 기준으로 평가됩니다. 마찬가지로 점 표기법을 사용하여 C# 클래스에서 개체 및 해당 속성을 트래버스합니다.
예를 들어 클래스를 PersonModel
확장하고 속성을 추가 Child
한 경우:
using System;
using Foundation;
namespace MacDatabinding
{
[Register("PersonModel")]
public class PersonModel : NSObject
{
private string _name = "";
private PersonModel _child = new PersonModel();
[Export("Name")]
public string Name {
get { return _name; }
set {
WillChangeValue ("Name");
_name = value;
DidChangeValue ("Name");
}
}
[Export("Child")]
public PersonModel Child {
get { return _child; }
set {
WillChangeValue ("Child");
_child = value;
DidChangeValue ("Child");
}
}
public PersonModel ()
{
}
}
}
자식 이름 self.Child.Name
에 대한 키 경로는 키 값이 사용된 방식에 따라 간단하게 Child.Name
사용됩니다.
키-값 코딩을 사용하여 값 가져오기
이 메서드는 ValueForKey
요청을 수신하는 KVC 클래스의 인스턴스를 기준으로 지정된 키(a NSString
)에 대한 값을 반환합니다. 예를 들어 위에 정의된 클래스의 PersonModel
인스턴스인 경우Person
:
// Read value
var name = Person.ValueForKey (new NSString("Name"));
그러면 해당 인스턴스에 대한 속성 값이 Name
반환됩니다 PersonModel
.
키-값 코딩을 사용하여 값 설정
마찬가지로 요청을 SetValueForKey
수신하는 KVC 클래스의 인스턴스를 기준으로 지정된 키(a NSString
)에 대한 값을 설정합니다. 따라서 아래와 같이 클래스의 인스턴스를 PersonModel
사용합니다.
// Write value
Person.SetValueForKey(new NSString("Jane Doe"), new NSString("Name"));
속성 값을 Name
.로 변경합니다 Jane Doe
.
값 변경 관찰
KVO(키-값 관찰)를 사용하여 관찰자를 KVC 규격 클래스의 특정 키에 연결하고 해당 키의 값이 수정될 때마다 알림을 받을 수 있습니다(KVC 기술을 사용하거나 C# 코드에서 지정된 속성에 직접 액세스). 예시:
// Watch for the name value changing
Person.AddObserver ("Name", NSKeyValueObservingOptions.New, (sender) => {
// Inform caller of selection change
Console.WriteLine("New Name: {0}", Person.Name)
});
이제 클래스 인스턴스의 Person
PersonModel
속성이 수정될 때마다 Name
새 값이 콘솔에 기록됩니다.
자세한 내용은 Apple의 키-값 관찰 프로그래밍 가이드 소개를 참조하세요.
데이터 바인딩
다음 섹션에서는 C# 코드를 사용하여 값을 읽고 쓰는 대신 키-값 코딩 및 키-값 관찰 준수 클래스를 사용하여 Xcode의 Interface Builder에서 UI 요소에 데이터를 바인딩하는 방법을 보여 줍니다. 이러한 방식으로 데이터 모델을 표시하는 데 사용되는 뷰와 분리하여 Xamarin.Mac 애플리케이션을 보다 유연하고 쉽게 기본. 또한 작성해야 하는 코드의 양을 크게 줄입니다.
데이터 모델 정의
Interface Builder에서 UI 요소를 데이터 바인딩하려면 먼저 바인딩의 데이터 모델 역할을 하려면 Xamarin.Mac 애플리케이션에 정의된 KVC/KVO 규격 클래스가 있어야 합니다. 데이터 모델은 사용자 인터페이스에 표시될 모든 데이터를 제공하고 애플리케이션을 실행하는 동안 사용자가 UI에서 수행하는 데이터를 수정합니다.
예를 들어 직원 그룹을 관리하는 애플리케이션을 작성하는 경우 다음 클래스를 사용하여 데이터 모델을 정의할 수 있습니다.
using System;
using Foundation;
using AppKit;
namespace MacDatabinding
{
[Register("PersonModel")]
public class PersonModel : NSObject
{
#region Private Variables
private string _name = "";
private string _occupation = "";
private bool _isManager = false;
private NSMutableArray _people = new NSMutableArray();
#endregion
#region Computed Properties
[Export("Name")]
public string Name {
get { return _name; }
set {
WillChangeValue ("Name");
_name = value;
DidChangeValue ("Name");
}
}
[Export("Occupation")]
public string Occupation {
get { return _occupation; }
set {
WillChangeValue ("Occupation");
_occupation = value;
DidChangeValue ("Occupation");
}
}
[Export("isManager")]
public bool isManager {
get { return _isManager; }
set {
WillChangeValue ("isManager");
WillChangeValue ("Icon");
_isManager = value;
DidChangeValue ("isManager");
DidChangeValue ("Icon");
}
}
[Export("isEmployee")]
public bool isEmployee {
get { return (NumberOfEmployees == 0); }
}
[Export("Icon")]
public NSImage Icon {
get {
if (isManager) {
return NSImage.ImageNamed ("group.png");
} else {
return NSImage.ImageNamed ("user.png");
}
}
}
[Export("personModelArray")]
public NSArray People {
get { return _people; }
}
[Export("NumberOfEmployees")]
public nint NumberOfEmployees {
get { return (nint)_people.Count; }
}
#endregion
#region Constructors
public PersonModel ()
{
}
public PersonModel (string name, string occupation)
{
// Initialize
this.Name = name;
this.Occupation = occupation;
}
public PersonModel (string name, string occupation, bool manager)
{
// Initialize
this.Name = name;
this.Occupation = occupation;
this.isManager = manager;
}
#endregion
#region Array Controller Methods
[Export("addObject:")]
public void AddPerson(PersonModel person) {
WillChangeValue ("personModelArray");
isManager = true;
_people.Add (person);
DidChangeValue ("personModelArray");
}
[Export("insertObject:inPersonModelArrayAtIndex:")]
public void InsertPerson(PersonModel person, nint index) {
WillChangeValue ("personModelArray");
_people.Insert (person, index);
DidChangeValue ("personModelArray");
}
[Export("removeObjectFromPersonModelArrayAtIndex:")]
public void RemovePerson(nint index) {
WillChangeValue ("personModelArray");
_people.RemoveObject (index);
DidChangeValue ("personModelArray");
}
[Export("setPersonModelArray:")]
public void SetPeople(NSMutableArray array) {
WillChangeValue ("personModelArray");
_people = array;
DidChangeValue ("personModelArray");
}
#endregion
}
}
이 클래스의 대부분의 기능은 위의 키-값 코딩 섹션에 설명되어 있습니다. 그러나 이 클래스가 배열 컨트롤러 및 트리 컨트롤러의 데이터 모델 역할을 할 수 있도록 몇 가지 특정 요소와 추가된 사항을 살펴보겠습니다(나중에 데이터 바인딩 트리 뷰, 개요 뷰 및 컬렉션 뷰에 사용 예정).
첫째, 직원이 관리자 NSArray
일 수 있기 때문에( 특히 NSMutableArray
값을 수정할 수 있도록) 관리되는 직원을 연결할 수 있도록 했습니다.
private NSMutableArray _people = new NSMutableArray();
...
[Export("personModelArray")]
public NSArray People {
get { return _people; }
}
여기서 유의해야 할 두 가지 사항은 다음과 같습니다.
- 테이블 뷰, 개요 뷰 및 컬렉션과 같은 AppKit 컨트롤에 대한 Data Bind에 대한 요구 사항이므로 표준 C# 배열 또는 컬렉션 대신 사용
NSMutableArray
했습니다. - 데이터 바인딩을 위해 직원 배열을 캐스팅
NSArray
하여 직원 배열을 노출하고 해당 C# 형식의 이름을People
{class_name}Array 형식으로 데이터 바인딩이 예상personModelArray
하는 이름으로 변경했습니다(첫 번째 문자는 소문자로 설정됨).
다음으로 배열 컨트롤러 및 트리 컨트롤러를 지원하기 위해 몇 가지 특수 이름 public 메서드를 추가해야 합니다.
[Export("addObject:")]
public void AddPerson(PersonModel person) {
WillChangeValue ("personModelArray");
isManager = true;
_people.Add (person);
DidChangeValue ("personModelArray");
}
[Export("insertObject:inPersonModelArrayAtIndex:")]
public void InsertPerson(PersonModel person, nint index) {
WillChangeValue ("personModelArray");
_people.Insert (person, index);
DidChangeValue ("personModelArray");
}
[Export("removeObjectFromPersonModelArrayAtIndex:")]
public void RemovePerson(nint index) {
WillChangeValue ("personModelArray");
_people.RemoveObject (index);
DidChangeValue ("personModelArray");
}
[Export("setPersonModelArray:")]
public void SetPeople(NSMutableArray array) {
WillChangeValue ("personModelArray");
_people = array;
DidChangeValue ("personModelArray");
}
이를 통해 컨트롤러는 표시되는 데이터를 요청하고 수정할 수 있습니다. 위에서 설명한 NSArray
것과 마찬가지로 이러한 명명 규칙에는 매우 구체적인 명명 규칙이 있습니다(일반적인 C# 명명 규칙과는 다릅니다).
addObject:
- 배열에 개체를 추가합니다.insertObject:in{class_name}ArrayAtIndex:
- 클래스의 이름은 어디에{class_name}
있습니다. 이 메서드는 지정된 인덱스의 배열에 개체를 삽입합니다.removeObjectFrom{class_name}ArrayAtIndex:
- 클래스의 이름은 어디에{class_name}
있습니다. 이 메서드는 지정된 인덱스에서 배열의 개체를 제거합니다.set{class_name}Array:
- 클래스의 이름은 어디에{class_name}
있습니다. 이 메서드를 사용하면 기존 캐리를 새 캐리로 바꿀 수 있습니다.
이러한 메서드 내에서 배열의 변경 내용과 DidChangeValue
KVO 규정 준수를 WillChangeValue
위한 메시지를 래핑했습니다.
마지막으로 속성이 Icon
속성의 isManager
값을 사용하므로 isManager
KVO 중 데이터 바인딩된 UI 요소에 Icon
속성 변경 내용이 반영되지 않을 수 있습니다.
[Export("Icon")]
public NSImage Icon {
get {
if (isManager) {
return NSImage.ImageNamed ("group.png");
} else {
return NSImage.ImageNamed ("user.png");
}
}
}
이를 해결하기 위해 다음 코드를 사용합니다.
[Export("isManager")]
public bool isManager {
get { return _isManager; }
set {
WillChangeValue ("isManager");
WillChangeValue ("Icon");
_isManager = value;
DidChangeValue ("isManager");
DidChangeValue ("Icon");
}
}
접근자는 자체 키 외에도 키 isManager
에 WillChangeValue
대한 Icon
메시지와 DidChangeValue
메시지를 전송하므로 변경 내용도 볼 수 있습니다.
이 문서의 나머지 부분 전체에서 PersonModel
데이터 모델을 사용합니다.
단순 데이터 바인딩
데이터 모델이 정의되어 있으므로 Xcode의 인터페이스 작성기에서 데이터 바인딩의 간단한 예제를 살펴보겠습니다. 예를 들어 위에서 정의한 것을 편집하는 데 사용할 수 있는 양식을 Xamarin.Mac 애플리케이션에 PersonModel
추가해 보겠습니다. 몇 가지 텍스트 필드와 확인란을 추가하여 모델의 속성을 표시하고 편집합니다.
먼저 Interface Builder의 Main.storyboard 파일에 새 뷰 컨트롤러를 추가하고 해당 클래스SimpleViewController
의 이름을 지정하겠습니다.
다음으로, Mac용 Visual Studio 돌아가서 SimpleViewController.cs 파일(프로젝트에 자동으로 추가됨)을 편집하고 양식에 PersonModel
데이터를 바인딩할 인스턴스를 노출합니다. 다음 코드를 추가합니다.
private PersonModel _person = new PersonModel();
...
[Export("Person")]
public PersonModel Person {
get {return _person; }
set {
WillChangeValue ("Person");
_person = value;
DidChangeValue ("Person");
}
}
다음으로 보기가 로드되면 인스턴스를 PersonModel
만들어 이 코드로 채웁니다.
public override void ViewDidLoad ()
{
base.AwakeFromNib ();
// Set a default person
var Craig = new PersonModel ("Craig Dunn", "Documentation Manager");
Craig.AddPerson (new PersonModel ("Amy Burns", "Technical Writer"));
Craig.AddPerson (new PersonModel ("Joel Martinez", "Web & Infrastructure"));
Craig.AddPerson (new PersonModel ("Kevin Mullins", "Technical Writer"));
Craig.AddPerson (new PersonModel ("Mark McLemore", "Technical Writer"));
Craig.AddPerson (new PersonModel ("Tom Opgenorth", "Technical Writer"));
Person = Craig;
}
이제 양식을 만들고 Main.storyboard 파일을 두 번 클릭하여 Interface Builder에서 편집할 수 있도록 열어야 합니다. 폼을 다음과 같이 레이아웃합니다.
키를 통해 Person
노출한 양식에 PersonModel
데이터를 바인딩하려면 다음을 수행합니다.
직원 이름 텍스트 필드를 선택하고 바인딩 검사로 전환합니다.
바인딩 상자를 선택하고 드롭다운에서 단순 보기 컨트롤러를 선택합니다. 다음으로 키 경로를 입력
self.Person.Name
합니다.직업 텍스트 필드를 선택하고 상자에 바인딩을 검사 드롭다운에서 단순 보기 컨트롤러를 선택합니다. 다음으로 키 경로를 입력
self.Person.Occupation
합니다.Employee is a Manager 확인란을 선택하고 바인딩 상자를 검사 드롭다운에서 간단한 보기 컨트롤러를 선택합니다. 다음으로 키 경로를 입력
self.Person.isManager
합니다.직원 수 관리 텍스트 필드를 선택하고 바인딩 상자를 검사 드롭다운에서 단순 보기 컨트롤러를 선택합니다. 다음으로 키 경로를 입력
self.Person.NumberOfEmployees
합니다.직원이 관리자가 아닌 경우 직원 수 관리 레이블 및 텍스트 필드를 숨기려고 합니다.
직원 관리 레이블 수를 선택하고 숨겨진 턴다운을 확장하고 바인딩 상자를 검사 드롭다운에서 단순 보기 컨트롤러를 선택합니다. 다음으로 키 경로를 입력
self.Person.isManager
합니다.값 변환기 드롭다운에서 선택합니다
NSNegateBoolean
.그러면 데이터 바인딩에 속성 값
isManager
이 있으면 레이블이 숨겨지false
게 됩니다.직원 관리 텍스트 필드 수에 대해 7단계와 8단계를 반복합니다.
변경 내용을 저장하고 Mac용 Visual Studio 돌아가 Xcode와 동기화합니다.
애플리케이션을 실행하면 속성의 값이 Person
양식에 자동으로 채워집니다.
사용자가 폼을 변경하면 뷰 컨트롤러의 Person
속성에 다시 기록됩니다. 예를 들어 직원 선택 취소는 관리자 가 인스턴스를 Person
PersonModel
업데이트하고 직원 수 관리 레이블 및 텍스트 필드는 데이터 바인딩을 통해 자동으로 숨겨집니다.
테이블 뷰 데이터 바인딩
이제 데이터 바인딩의 기본 사항을 살펴보았습니다. 이제 배열 컨트롤러 및 데이터 바인딩을 사용하여 테이블 뷰에 대한 보다 복잡한 데이터 바인딩 작업을 살펴보겠습니다. 테이블 뷰 작업에 대한 자세한 내용은 테이블 뷰 설명서를 참조하세요.
먼저 Interface Builder의 Main.storyboard 파일에 새 뷰 컨트롤러를 추가하고 해당 클래스TableViewController
의 이름을 지정하겠습니다.
다음으로, TableViewController.cs 파일(프로젝트에 자동으로 추가됨)을 편집하고 양식에 데이터를 바인딩할 클래스의 PersonModel
배열(NSArray
)을 공개하겠습니다. 다음 코드를 추가합니다.
private NSMutableArray _people = new NSMutableArray();
...
[Export("personModelArray")]
public NSArray People {
get { return _people; }
}
...
[Export("addObject:")]
public void AddPerson(PersonModel person) {
WillChangeValue ("personModelArray");
_people.Add (person);
DidChangeValue ("personModelArray");
}
[Export("insertObject:inPersonModelArrayAtIndex:")]
public void InsertPerson(PersonModel person, nint index) {
WillChangeValue ("personModelArray");
_people.Insert (person, index);
DidChangeValue ("personModelArray");
}
[Export("removeObjectFromPersonModelArrayAtIndex:")]
public void RemovePerson(nint index) {
WillChangeValue ("personModelArray");
_people.RemoveObject (index);
DidChangeValue ("personModelArray");
}
[Export("setPersonModelArray:")]
public void SetPeople(NSMutableArray array) {
WillChangeValue ("personModelArray");
_people = array;
DidChangeValue ("personModelArray");
}
데이터 모델 정의 섹션에서 위의 클래스에서 수행한 PersonModel
것처럼 배열 컨트롤러가 컬렉션PersonModels
에서 데이터를 읽고 쓸 수 있도록 특별히 명명된 공용 메서드 4개를 공개했습니다.
다음으로 뷰가 로드되면 다음 코드로 배열을 채워야 합니다.
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
// Build list of employees
AddPerson (new PersonModel ("Craig Dunn", "Documentation Manager", true));
AddPerson (new PersonModel ("Amy Burns", "Technical Writer"));
AddPerson (new PersonModel ("Joel Martinez", "Web & Infrastructure"));
AddPerson (new PersonModel ("Kevin Mullins", "Technical Writer"));
AddPerson (new PersonModel ("Mark McLemore", "Technical Writer"));
AddPerson (new PersonModel ("Tom Opgenorth", "Technical Writer"));
AddPerson (new PersonModel ("Larry O'Brien", "API Documentation Manager", true));
AddPerson (new PersonModel ("Mike Norman", "API Documenter"));
}
이제 테이블 뷰를 만들고 Main.storyboard 파일을 두 번 클릭하여 인터페이스 작성기에서 편집할 수 있도록 열어야 합니다. 다음과 같이 표시되도록 테이블을 레이아웃합니다.
테이블에 바인딩된 데이터를 제공하기 위해 배열 컨트롤러 를 추가해야 합니다. 다음을 수행합니다.
라이브러리 검사기에서 인터페이스 편집기로 배열 컨트롤러를 끕니다.
인터페이스 계층 구조에서 배열 컨트롤러를 선택하고 특성 검사자로 전환합니다.
수업 이름에 대해 입력
PersonModel
하고 더하기 단추를 클릭하고 세 개의 키를 추가합니다. 이름을 지정Occupation
하고isManager
다음을 수행합니다.Name
그러면 배열 컨트롤러가 배열을 관리하는 내용과 표시해야 하는 속성(키를 통해)을 알 수 있습니다.
바인딩 검사자로 전환하고 콘텐츠 배열 아래에서 바인딩 및 테이블 뷰 컨트롤러를 선택합니다. 다음의 모델 키 경로를 입력합니다
self.personModelArray
.이렇게 하면 배열 컨트롤러가 뷰 컨트롤러에 노출된 배열
PersonModels
과 연결됩니다.
이제 테이블 뷰를 배열 컨트롤러에 바인딩해야 합니다. 다음을 수행합니다.
테이블 뷰 및 바인딩 검사기를 선택합니다.
테이블 내용 턴다운 아래에서 바인딩 대상 및 배열 컨트롤러를 선택합니다. 컨트롤러 키 필드에 대해 입력
arrangedObjects
합니다.Employee 열 아래에서 테이블 뷰 셀을 선택합니다. 값 턴다운 아래의 바인딩 검사기에서 바인딩 대상 및 표 셀 뷰를 선택합니다. 모델 키 경로에 대해 입력
objectValue.Name
합니다.objectValue
는 배열 컨트롤러에서 관리되는 배열의 현재PersonModel
값입니다.직업 열에서 테이블 뷰 셀을 선택합니다. 값 턴다운 아래의 바인딩 검사기에서 바인딩 대상 및 표 셀 뷰를 선택합니다. 모델 키 경로에 대해 입력
objectValue.Occupation
합니다.변경 내용을 저장하고 Mac용 Visual Studio 돌아가 Xcode와 동기화합니다.
애플리케이션을 실행하면 테이블이 다음 배열 PersonModels
로 채워집니다.
개요 보기 데이터 바인딩
개요 뷰에 대한 데이터 바인딩은 테이블 뷰에 대한 바인딩과 매우 유사합니다. 주요 차이점은 배열 컨트롤러 대신 트리 컨트롤러를 사용하여 개요 보기에 바인딩된 데이터를 제공한다는 것입니다. 개요 보기 작업에 대한 자세한 내용은 개요 보기 설명서를 참조하세요.
먼저 Interface Builder의 Main.storyboard 파일에 새 뷰 컨트롤러를 추가하고 해당 클래스OutlineViewController
의 이름을 지정하겠습니다.
다음으로, OutlineViewController.cs 파일(프로젝트에 자동으로 추가됨)을 편집하고 양식에 데이터를 바인딩할 클래스의 PersonModel
배열(NSArray
)을 공개하겠습니다. 다음 코드를 추가합니다.
private NSMutableArray _people = new NSMutableArray();
...
[Export("personModelArray")]
public NSArray People {
get { return _people; }
}
...
[Export("addObject:")]
public void AddPerson(PersonModel person) {
WillChangeValue ("personModelArray");
_people.Add (person);
DidChangeValue ("personModelArray");
}
[Export("insertObject:inPersonModelArrayAtIndex:")]
public void InsertPerson(PersonModel person, nint index) {
WillChangeValue ("personModelArray");
_people.Insert (person, index);
DidChangeValue ("personModelArray");
}
[Export("removeObjectFromPersonModelArrayAtIndex:")]
public void RemovePerson(nint index) {
WillChangeValue ("personModelArray");
_people.RemoveObject (index);
DidChangeValue ("personModelArray");
}
[Export("setPersonModelArray:")]
public void SetPeople(NSMutableArray array) {
WillChangeValue ("personModelArray");
_people = array;
DidChangeValue ("personModelArray");
}
데이터 모델 정의 섹션에서 위의 클래스에서 수행한 PersonModel
것처럼 트리 컨트롤러가 컬렉션PersonModels
에서 데이터를 읽고 쓸 수 있도록 특별히 명명된 네 가지 공용 메서드를 공개했습니다.
다음으로 뷰가 로드되면 다음 코드로 배열을 채워야 합니다.
public override void AwakeFromNib ()
{
base.AwakeFromNib ();
// Build list of employees
var Craig = new PersonModel ("Craig Dunn", "Documentation Manager");
Craig.AddPerson (new PersonModel ("Amy Burns", "Technical Writer"));
Craig.AddPerson (new PersonModel ("Joel Martinez", "Web & Infrastructure"));
Craig.AddPerson (new PersonModel ("Kevin Mullins", "Technical Writer"));
Craig.AddPerson (new PersonModel ("Mark McLemore", "Technical Writer"));
Craig.AddPerson (new PersonModel ("Tom Opgenorth", "Technical Writer"));
AddPerson (Craig);
var Larry = new PersonModel ("Larry O'Brien", "API Documentation Manager");
Larry.AddPerson (new PersonModel ("Mike Norman", "API Documenter"));
AddPerson (Larry);
}
이제 개요 보기를 만들고 Main.storyboard 파일을 두 번 클릭하여 인터페이스 작성기에서 편집할 수 있도록 열어야 합니다. 다음과 같이 표시되도록 테이블을 레이아웃합니다.
개요에 바인딩된 데이터를 제공하기 위해 트리 컨트롤러 를 추가해야 합니다. 다음을 수행합니다.
라이브러리 검사기에서 인터페이스 편집기로 트리 컨트롤러를 끕니다.
인터페이스 계층 구조에서 트리 컨트롤러를 선택하고 특성 검사기로 전환합니다.
수업 이름에 대해 입력
PersonModel
하고 더하기 단추를 클릭하고 세 개의 키를 추가합니다. 이름을 지정Occupation
하고isManager
다음을 수행합니다.Name
이렇게 하면 트리 컨트롤러가 배열을 관리하는 내용과 표시해야 하는 속성(키를 통해)을 알려줍니다.
트리 컨트롤러 섹션에서 자식에 대해 입력
personModelArray
하고, 개수 아래에 입력NumberOfEmployees
하고, 리프 아래에 입력isEmployee
합니다.이렇게 하면 트리 컨트롤러에서 자식 노드를 찾을 수 있는 위치, 자식 노드의 수 및 현재 노드에 자식 노드가 있는지를 알 수 있습니다.
바인딩 검사자로 전환하고 콘텐츠 배열 아래에서 바인딩 및 파일의 소유자를 선택합니다. 다음의 모델 키 경로를 입력합니다
self.personModelArray
.이렇게 하면 트리 컨트롤러가 뷰 컨트롤러에 노출된 배열
PersonModels
과 연결됩니다.
이제 개요 뷰를 트리 컨트롤러에 바인딩해야 합니다. 다음을 수행합니다.
개요 보기를 선택하고 바인딩 검사기에서 다음을 선택합니다.
개요 보기 콘텐츠 턴다운 아래에서 바인딩 대상 및 트리 컨트롤러를 선택합니다. 컨트롤러 키 필드에 대해 입력
arrangedObjects
합니다.Employee 열 아래에서 테이블 뷰 셀을 선택합니다. 값 턴다운 아래의 바인딩 검사기에서 바인딩 대상 및 표 셀 뷰를 선택합니다. 모델 키 경로에 대해 입력
objectValue.Name
합니다.objectValue
는 트리 컨트롤러에서 관리되는 배열의 현재PersonModel
값입니다.직업 열에서 테이블 뷰 셀을 선택합니다. 값 턴다운 아래의 바인딩 검사기에서 바인딩 대상 및 표 셀 뷰를 선택합니다. 모델 키 경로에 대해 입력
objectValue.Occupation
합니다.변경 내용을 저장하고 Mac용 Visual Studio 돌아가 Xcode와 동기화합니다.
애플리케이션을 실행하면 개요가 다음 배열 PersonModels
로 채워집니다.
컬렉션 뷰 데이터 바인딩
컬렉션 뷰를 사용한 데이터 바인딩은 배열 컨트롤러가 컬렉션에 대한 데이터를 제공하는 데 사용되므로 테이블 뷰를 사용한 바인딩과 매우 비슷합니다. 컬렉션 보기에는 미리 설정된 표시 형식이 없으므로 사용자 상호 작용 피드백을 제공하고 사용자 선택을 추적하기 위해 더 많은 작업이 필요합니다.
Important
Xcode 7 및 macOS 10.11 이상의 문제로 인해 Storyboard(.storyboard) 파일 내에서 컬렉션 뷰를 사용할 수 없습니다. 따라서 .xib 파일을 계속 사용하여 Xamarin.Mac 앱에 대한 컬렉션 뷰를 정의해야 합니다. 자세한 내용은 컬렉션 뷰 설명서를 참조하세요.
네이티브 크래시 디버깅
데이터 바인딩에서 실수를 하면 관리되지 않는 코드에서 네이티브 크래시가 발생하고 Xamarin.Mac 애플리케이션이 오류와 함께 SIGABRT
완전히 실패할 수 있습니다.
일반적으로 데이터 바인딩 중에 네이티브 크래시가 발생하는 주요 원인은 다음과 같습니다.
- 데이터 모델은 .의
NSObject
하위 클래스 또는NSObject
상속되지 않습니다. - 특성을 사용하는
[Export("key-name")]
데 Objective-C 속성을 노출하지 않았습니다. - 접근자의 값
WillChangeValue
과 메서드 호출에 대한 변경 내용을 래핑하지 않았습니다(특성과DidChangeValue
동일한 키를Export
지정). - 인터페이스 작성기에서 바인딩 검사기에서 잘못되었거나 잘못 입력된 키가 있습니다.
크래시 디코딩
데이터 바인딩을 찾아서 수정하는 방법을 보여 줄 수 있도록 데이터 바인딩에서 네이티브 크래시가 발생해 보겠습니다. 인터페이스 작성기에서 컬렉션 뷰 예제에서 첫 번째 레이블의 바인딩을 다음으로 Name
Title
변경해 보겠습니다.
변경 사항을 저장하고 Mac용 Visual Studio 다시 전환하여 Xcode와 동기화하고 애플리케이션을 실행해 보겠습니다. 컬렉션 뷰가 표시되면 키와 함께 속성을 노출하지 않으므로 애플리케이션이 일시적으로 오류(Mac용 Visual Studio 애플리케이션 출력에 표시됨)PersonModel
와 SIGABRT
충돌Title
합니다.
애플리케이션 출력에서 오류 맨 위로 스크롤하면 문제를 해결하는 키를 확인할 수 있습니다.
이 줄은 바인딩하는 개체에 키가 Title
존재하지 않는다는 것을 나타냅니다. Interface Builder에서 바인딩을 Name
다시 변경하고 저장, 동기화, 다시 빌드 및 실행하면 애플리케이션이 문제 없이 예상대로 실행됩니다.
요약
이 문서에서는 Xamarin.Mac 애플리케이션에서 데이터 바인딩 및 키-값 코딩 작업을 자세히 살펴보았습니다. 먼저 KVC(키-값 코딩) 및 KVO(키-값 관찰)를 사용하여 C# 클래스 Objective-C 를 노출하는 방법을 살펴보았습니다. 다음으로, KVO 규격 클래스를 사용하고 Xcode의 인터페이스 작성기에서 UI 요소에 데이터 바인딩하는 방법을 보여 줍니다. 마지막으로 배열 컨트롤러 및 트리 컨트롤러를 사용하는 복잡한 데이터 바인딩을 보여 줍니다.