Xamarin.iOS에서 데이터로 테이블 채우기
행을 UITableView
추가하려면 하위 클래스를 UITableViewSource
구현하고 테이블 뷰에서 자체 채우기 위해 호출하는 메서드를 재정의해야 합니다.
이 가이드에서는 다음을 다룹니다.
- UITableViewSource 서브클래싱
- 셀 재사용
- 인덱스 추가
- 머리글 및 바닥글 추가
서브클래싱 UITableViewSource
UITableViewSource
하위 클래스는 모든 UITableView
에 할당됩니다. 테이블 뷰는 원본 클래스를 쿼리하여 자체 렌더링 방법을 결정합니다(예: 필요한 행 수 및 기본값과 다른 경우 각 행의 높이). 가장 중요한 것은 원본이 데이터로 채워진 각 셀 뷰를 제공합니다.
테이블 표시 데이터를 만드는 데 필요한 필수 메서드는 두 가지뿐입니다.
- RowsInSection – 테이블이 표시해야 하는 총 데이터 행 수를 반환
nint
합니다. - GetCell – 메서드에
UITableViewCell
전달된 해당 행 인덱스 데이터로 채워진 값을 반환합니다.
BasicTable 샘플 파일 TableSource.cs 가능한 가장 간단한 구현이 있습니다 UITableViewSource
. 아래 코드 조각에서는 표에 표시할 문자열 배열을 허용하고 각 문자열을 포함하는 기본 셀 스타일을 반환한다는 것을 확인할 수 있습니다.
public class TableSource : UITableViewSource {
string[] TableItems;
string CellIdentifier = "TableCell";
public TableSource (string[] items)
{
TableItems = items;
}
public override nint RowsInSection (UITableView tableview, nint section)
{
return TableItems.Length;
}
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell (CellIdentifier);
string item = TableItems[indexPath.Row];
//if there are no cells to reuse, create a new one
if (cell == null)
{
cell = new UITableViewCell (UITableViewCellStyle.Default, CellIdentifier);
}
cell.TextLabel.Text = item;
return cell;
}
}
A는 UITableViewSource
간단한 문자열 배열(이 예제와 같이)에서 List <> 또는 기타 컬렉션에 이르기까지 모든 데이터 구조를 사용할 수 있습니다. 메서드의 UITableViewSource
구현은 기본 데이터 구조에서 테이블을 격리합니다.
이 하위 클래스를 사용하려면 문자열 배열을 만들어 원본을 생성한 다음 다음 인스턴스 UITableView
에 할당합니다.
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
table = new UITableView(View.Bounds); // defaults to Plain style
string[] tableItems = new string[] {"Vegetables","Fruits","Flower Buds","Legumes","Bulbs","Tubers"};
table.Source = new TableSource(tableItems);
Add (table);
}
결과 테이블은 다음과 같습니다.
대부분의 테이블을 통해 사용자는 행을 터치하여 이를 선택하고 다른 작업(예: 노래 재생, 연락처 호출 또는 다른 화면 표시)을 수행할 수 있습니다. 이를 위해 몇 가지 작업을 수행해야 합니다. 먼저 사용자가 메서드에 다음을 추가하여 행을 클릭할 때 메시지를 표시하는 AlertController를 RowSelected
만들어 보겠습니다.
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
UIAlertController okAlertController = UIAlertController.Create ("Row Selected", tableItems[indexPath.Row], UIAlertControllerStyle.Alert);
okAlertController.AddAction(UIAlertAction.Create("OK", UIAlertActionStyle.Default, null));
...
tableView.DeselectRow (indexPath, true);
}
다음으로 뷰 컨트롤러의 인스턴스를 만듭니다.
HomeScreen owner;
뷰 컨트롤러를 매개 변수로 사용하여 필드에 저장하는 생성자를 UITableViewSource 클래스에 추가합니다.
public TableSource (string[] items, HomeScreen owner)
{
...
this.owner = owner;
}
참조를 전달하기 위해 UITableViewSource 클래스가 만들어지는 ViewDidLoad 메서드를 this
수정합니다.
table.Source = new TableSource(tableItems, this);
마지막으로 메서드로 RowSelected
돌아가서 캐시된 필드를 호출 PresentViewController
합니다.
public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
{
...
owner.PresentViewController (okAlertController, true, null);
...
}
이제 사용자가 행을 터치할 수 있으며 경고가 표시됩니다.
셀 재사용
이 예제에는 6개의 항목만 있으므로 셀 재사용이 필요하지 않습니다. 그러나 수백 또는 수천 개의 행을 표시할 때 한 번에 몇 개만 화면에 맞을 때 수백 또는 수천 UITableViewCell
개의 개체를 만드는 것은 메모리 낭비입니다.
이 상황을 방지하기 위해 화면에서 셀이 사라지면 해당 보기가 재사용을 위해 큐에 배치됩니다. 사용자가 스크롤할 때 표는 표시할 새 보기를 요청하기 위해 호출 GetCell
합니다. 기존 셀(현재 표시되지 않음)을 다시 사용하기 위해 메서드를 호출 DequeueReusableCell
하기만 하면 됩니다. 다시 사용할 수 있는 셀이 반환되면 null이 반환되고 코드에서 새 셀 인스턴스를 만들어야 합니다.
이 예제의 코드 조각은 패턴을 보여 줍니다.
// request a recycled cell to save memory
UITableViewCell cell = tableView.DequeueReusableCell (cellIdentifier);
// if there are no cells to reuse, create a new one
if (cell == null)
cell = new UITableViewCell (UITableViewCellStyle.Default, cellIdentifier);
서로 cellIdentifier
다른 유형의 셀에 대해 별도의 큐를 효과적으로 만듭니다. 이 예제에서는 모든 셀이 동일하게 표시되므로 하드 코드된 식별자 하나만 사용됩니다. 다른 유형의 셀이 있는 경우 인스턴스화될 때와 재사용 큐에서 요청될 때 각각 다른 식별자 문자열이 있어야 합니다.
iOS 6 이상에서 셀 재사용
iOS 6은 컬렉션 뷰의 소개와 유사한 셀 재사용 패턴을 추가했습니다. 위에 표시된 기존 재사용 패턴은 이전 버전과의 호환성을 위해 계속 지원되지만 이 새 패턴은 셀에서 null 검사 대한 필요성을 제거하므로 바람직합니다.
새 패턴을 사용하면 애플리케이션이 컨트롤러의 생성자 중 하나 RegisterClassForCellReuse
또는 생성자를 호출하여 사용할 셀 클래스 또는 RegisterNibForCellReuse
xib를 등록합니다. 그런 다음 메서드에서 셀을 큐에서 GetCell
제거하는 경우 셀 클래스 또는 xib 및 인덱스 경로에 대해 등록한 식별자 전달을 호출 DequeueReusableCell
하기만 하면 됩니다.
예를 들어 다음 코드는 UITableViewController에 사용자 지정 셀 클래스를 등록합니다.
public class MyTableViewController : UITableViewController
{
static NSString MyCellId = new NSString ("MyCellId");
public MyTableViewController ()
{
TableView.RegisterClassForCellReuse (typeof(MyCell), MyCellId);
}
...
}
MyCell 클래스를 등록하면 아래와 같이 추가 null 검사 필요 없이 셀을 UITableViewSource
메서드에서 큐에서 GetCell
제거할 수 있습니다.
class MyTableSource : UITableViewSource
{
public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
{
// if cell is not available in reuse pool, iOS will create one automatically
// no need to do null check and create cell manually
var cell = (MyCell) tableView.DequeueReusableCell (MyCellId, indexPath);
// do whatever you need to with cell, such as assigning properties, etc.
return cell;
}
}
사용자 지정 셀 클래스와 함께 새 재사용 패턴을 사용하는 경우 아래 코드 조각에 표시된 것처럼 해당 생성자를 IntPtr
구현해야 합니다. 그렇지 않으면 Objective-C 셀 클래스의 인스턴스를 생성할 수 없습니다.
public class MyCell : UITableViewCell
{
public MyCell (IntPtr p):base(p)
{
}
...
}
이 문서에 연결된 BasicTable 샘플에서 위에서 설명한 항목의 예를 볼 수 있습니다 .
인덱스 추가
인덱스가 있으면 사용자가 원하는 기준으로 인덱싱할 수 있지만 일반적으로 사전순으로 정렬된 긴 목록을 스크롤할 수 있습니다. BasicTableIndex 샘플은 파일에서 훨씬 더 긴 항목 목록을 로드하여 인덱스를 보여 줍니다. 인덱스의 각 항목은 테이블의 '섹션'에 해당합니다.
'섹션'을 지원하려면 테이블 뒤의 데이터를 그룹화해야 하므로 BasicTableIndex 샘플은 각 항목의 첫 글자를 사전 키로 사용하여 문자열 배열에서 만듭니다 Dictionary<>
.
indexedTableItems = new Dictionary<string, List<string>>();
foreach (var t in items) {
if (indexedTableItems.ContainsKey (t[0].ToString ())) {
indexedTableItems[t[0].ToString ()].Add(t);
} else {
indexedTableItems.Add (t[0].ToString (), new List<string>() {t});
}
}
keys = indexedTableItems.Keys.ToArray ();
UITableViewSource
그런 다음 서브클래스를 사용 Dictionary<>
하려면 다음 메서드를 추가하거나 수정해야 합니다.
- NumberOfSections – 이 메서드는 선택 사항이며 기본적으로 테이블은 하나의 섹션을 가정합니다. 인덱스를 표시할 때 이 메서드는 인덱스의 항목 수를 반환해야 합니다(예: 인덱스에 영어 알파벳의 모든 문자가 포함된 경우 26).
- RowsInSection – 지정된 섹션의 행 수를 반환합니다.
- SectionIndexTitles – 인덱스를 표시하는 데 사용할 문자열 배열을 반환합니다. 샘플 코드는 문자 배열을 반환합니다.
샘플 파일 BasicTableIndex/TableSource.cs 업데이트된 메서드는 다음과 같습니다.
public override nint NumberOfSections (UITableView tableView)
{
return keys.Length;
}
public override nint RowsInSection (UITableView tableview, nint section)
{
return indexedTableItems[keys[section]].Count;
}
public override string[] SectionIndexTitles (UITableView tableView)
{
return keys;
}
인덱스는 일반적으로 일반 테이블 스타일에만 사용됩니다.
머리글 및 바닥글 추가
머리글 및 바닥글을 사용하여 테이블의 행을 시각적으로 그룹화할 수 있습니다. 필요한 데이터 구조는 인덱 Dictionary<>
스 추가와 매우 유사합니다. 이 예제에서는 알파벳을 사용하여 셀을 그룹화하는 대신 식물 유형별로 채소를 그룹화합니다.
출력은 다음과 같습니다.
머리글 및 바닥글을 표시하려면 하위 클래스에 UITableViewSource
다음 추가 메서드가 필요합니다.
- TitleForHeader – 머리글로 사용할 텍스트를 반환합니다.
- TitleForFooter – 바닥글로 사용할 텍스트를 반환합니다.
샘플 파일 BasicTableHeaderFooter/Code/TableSource.cs 업데이트된 메서드는 다음과 같습니다.
public override string TitleForHeader (UITableView tableView, nint section)
{
return keys[section];
}
public override string TitleForFooter (UITableView tableView, nint section)
{
return indexedTableItems[keys[section]].Count + " items";
}
에 대한 및 메서드 재정의를 사용하여 View 개체를 사용하여 머리글 및 GetViewForFooter
바닥글의 GetViewForHeader
모양을 추가로 사용자 지정할 수 있습니다UITableViewSource
.