<테이블 뷰 컨트롤러>
테이블 뷰가 루트 뷰로 정의되어 있다.
목록 형식의 데이터를 화면에 표현하는 데 사용된다.
화면 전체가 목록으로 이루어진 인터페이스를 구현할 때 사용하는 컨트롤러.
ex)iTunes앱의 재생목록
iOS환경설정(설정 정보 관리)
카테고리 선택 / 작성된 메모의 목록 보기
테이블 뷰 컨트롤러의 계층구조
1. 테이블뷰 컨트롤러
2. 테이블뷰
3. 테이블뷰 셀 (여려개의 행)
4. 콘텐츠 뷰
우리가 실제로 화면에서 보는 목록 각 행의 내용은 저마다의 콘텐츠가 콘텐츠뷰 내부에 적절히 배치된 결과물임.
섹션: 하나의 테이블 뷰 내에서 셀들을 그룹으로 묶을 수 있는 단위.
하나의 테이블 뷰 내에서도 섹션에 따라 다른 주제로 분류된 데이터를 보여줄 수 있다.
ex)음악목록 - 추천음악목록, 내가 최근에 들은 음악 목록, 최근 발매 음반 등.
정리--
하나의 테이블 뷰 컨트롤러 화면을 구성하는 단위
테이블 뷰 컨트롤러 -> 하나의 테이블 뷰 -> 여러개의 테이블 뷰 섹션 -> 여러개의 테이블 뷰 셀 -> 테이블 뷰 셀마다 하나씩의 콘텐츠 뷰
[ 프로토타입 셀 ]
:테이블 뷰의 셀을 원하는 대로 쉽게 디자인할 수 있도록 해주는 객체. 테이블 뷰를 설계하는 데 걸리는 시간과 노력을 대폭 줄여준다.
버튼이나 텍스트 레이블과 달리 직접 데이터를 표시하거나 화면에 공간을 차지하지는 않는다.
그저 테이블 뷰가 화면에 표현될 때 셀의 구성을 미리 보여주기 위한 가상 툴에 불과.
*프로토타입 셀 영역
사용자가 테이블 뷰의 구성을 쉽게 인지할 수 있도록 몇 개의 영역으로 나누어져 있으며 그에 맞는 역할 담당.
cell content: 셀에 표현될 콘텐츠 -> 작업 대부분이 이 영역에서 이루어짐. 가변적인 너비값. 기기에 따른 가로 길이 변화에도 신경써야함.
accessory view: 콘텐츠의 부가 정보 여부를 암시 ->너비가 고정적
cell content영역에는 -> image, text 영역으로 나뉨.
*표준 편집 인터페이스
콘텐츠 자체 편집이 필요한 경우 위해 코코아 터치 프레임워크에서는 프로토타입 셀에 다음 그림과 같은 표준 편집 인터페이스 제공.
editing control, cell content, reordering control
editing control : 초록색 플러스. 빨간색 마이너스
reordering control: 셀의 순서를 재배치 하는 컨트롤 제공.
[ 데이터 소스 ]
테이블 뷰를 이용하여 화면에 콘텐츠 표현하는 방법 2가지 - 정적 / 동적
정적인 방법: 테이블 뷰 셀 각각을 프로그래밍적으로 구성하지 않고, 스토리보드에서 직접 구성한 것.
(static cells)
반면, 고정되지 않고 매번 갱신되는 내용을 표현하려면 테이블 뷰 셀을 프로그래밍적으로 구성해주어야 한다. 이를 위해 데이터 소스 필요.
테이블 뷰의 각 행마다 대응할 수 있도록 배열형태이기만 하면 데이터 소스가 됨.
데이터 바인딩: 이렇게 만들어진 데이터 소스를 테이블 뷰 각 행에 연결하는 과정.
[데이터 소스 만들기]
Value Object 패턴
:데이터 저장을 전담하는 클래스를 별도로 분리하는 설계 방식. 줄여서 VO라고 한다.
일종의 식판이라고 할 수 있다. (밥그릇, 국그릇 등을 올려 놓는..)
식판 하나만 들고가면 자연스레 국, 밥, 반찬이 함께 이동하게 됨.
클래스 인스턴스 내부의 속성에 각각의 데이터들을 담은 다음, 전달할 때는 클래스 인스턴스 전체를 전달하기 때문에, 자연스레 클래스 내부의 변수에 저장된 값도 함께 전달된다.
*리팩토링
:코드의 결과나 성능에는 영향을 미치지 않고 단지 가독성과 유지보수의 편의를 위해 더 세련되고 구조화된 코드로 변경하는 것.
튜플 - 데이터를 단순 나열하고 묶을 때 편리
*lazy
1) 미리 생성해서 메모리 낭비할 필요 없을 때 사용. lazy키워드 붙여서 변수를 정의하면 참조되는 시점에 맞추어 초기화되므로 메모리 낭비를 줄일 수 있다.
2) lazy키워드를 붙이지 않은 프로퍼티는 다른 프로퍼티를 참조할 수 없다.
[테이블 뷰와 데이터 소스 연동]
:UITableViewDataSource라는 프로토콜에 의존하여 이루어진다.
테이블 뷰 컨트롤러는 이 프로토콜을 참고하여 지정된 메소드를 호출함으로써, 데이터소스와 테이블뷰를 연동한다.
원래대로라면 이 프로토콜을 상속받아야 하지만, 우리가 상속받고있는 UITavleViewController 클래스가 이미 해당 프로토콜을 상속 받고 있으므로 다시금 상속 받을 필요는 없다.
테이블 뷰에 데이터 소스를 연동할 때 필요한 내용 2가지
1)테이블이 몇 개의 행으로 구성되는가?
2)각 행의 내용은 어떻게 구성되는가?
이들 두가지 질문에 답하기 위한 메소드들이 UITableViewDataSource프로토콜에 정의되어 있다.
이들 메소드를 구현하여, 실제로 앱이 구동될 때 메소드가 호출되고 그 결과로 적절한 반환값을 받아갈 수 있도록 해주어야 함.
*데이터소스 연동을 위한 핵심 메소드
1)tableView(_:numberOfRowsInSection:)
테이블뷰가 생성해야할 행 개수 반환
우리가 사용하기 위한 것이 아니라, 시스템이 사용하기 위한 메소드.
현재 몇 개의 행이 구성되어 있는지를 우리에게 알려주는 역할 x, 몇 개의 행을 생성해야 할지 우리가 iOS시스템에게 알려주기 위해 작성하는 메소드.
테이블 뷰를 구성하는 델리게이트에서 읽어들이기 위한 용도.
이미 만들어진 테이블 뷰의 행 개수를 결과값으로 반환하는용도 x, 이 메소드에 의해 테이블뷰의 행 수가 결정되는 것임.
생성해야 할 행 수: 우리가 임의로 지정해주기보다는 데이터 소스의 크기를 동적으로 반환하는 방식으로 처리하는 것이 바람직.
override func tableView(_tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return 테이블 뷰의 목록 길이
}
iOS가 이 메소드 호출할 때 2개의 인자값 함께 전달: 1) 테이블 뷰 객체 정보 2) 섹션정보
2)tableView(_:cellForRowAt:)
JS의 콜백함수와 비슷. 우리가 알아서 적절한 시점에 호출하는 것이 아니라, 작성해 두면 시스템이 알아서 호출하는 식. 약간 지뢰느낌.
이 메소드는 각 행이 화면에 표현해야 할 내용을 구성하는 데에 사용된다.
하지만, 이 메소드가 반환하는 값은 전체 테이블 뷰의 목록이 아니라, 하나하나의 개별적인 테이블 셀 객체.
이는 화면에 표현해야 할 목록의 수만큼 이 메소드가 반복적으로 호출된다는 것을 의미.
메소드 내에서 테이블 뷰 셀 객체를 구성한 다음, 결과값으로 반환하면 시스템은 이 객체를 받아 테이블 뷰의 목록 각 행에 채워 넣는 방식.
우리가 작성한 데이터 소스는 이 메소드 내부에서 활용되어 특정 행의 콘텐츠를 구성하는 데에 사용된다.
iOS시스템은 테이블 뷰를 구성하기 위해 먼저 1)번 메소드를 호출하여 몇 개의 행을 생성해야 하는지를 반환 받고, 그 수만큼 2)번 메소드를 호출한다.
override func tableView(_tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return 테이블 뷰 셀 인스턴스
}
iOS가 이 메소드 호출할 때 2개의 인자값 함께 전달: 1) 구성할 테이블 뷰 객체에 대한 참조 2) 구성할 행에 대한 참조 정보
첫번째 매개변수를 통해 테이블 뷰가 특정되면, 두번째 매개변수인 indexPath를 통해 몇 번째 행을 구성하기 위한 호출인지를 구분할 수 있다.
*사용자의 액션 처리를 위한 핵심 메소드
데이터 소스를 연동하기 위한 용도는 아니지만, 일반적으로 테이블 뷰를 구성할 때 많이 사용되는 핵심메소드
= tableView(_:didSelectRowAt:)
이 메소드는 사용자가 목록 중에서 특정 행을 선택했을 때 호출된다.
보통 사용자가 선택한 내용에 맞는 액션을 처리하는 용도로 사용됨.
사용자가 행을 선택했을 때 딱히 처리해줄 액션 없이, 그저 화면에 목록을 표시하기만 하는 용도의 테이블 뷰라면 이 메소드를 구현할 필요는 없다.
반대로 사용자가 행을 선택했을 때 그에 맞게 화면을 이동한다던가 혹은 상세내용을 팝업으로 보여주는 등의 다양한 기능 구현하고 싶을 때 이 메소드를 구현해주어야 한다.
override func tableView(_tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
}
첫번째 인자값: 사용자가 터치한 테이블 뷰에 대한 참조값, 두번째 인자값: 인자값이 터치된 행에 대한 정보.
사용자가 어느 테이블 뷰의 몇 번째 행을 선택했는지 확인할 수 있으며, 새로운 화면으로 이동하는 코드를 작성하거나, 알림창, 혹은 기타 기능을 작성하는 과정을 구현도 가능.
요약 >>
1)tableView(_:numberOfRowsInSection:) = 메소드를 구현하고, 생성할 목록의 길이를 반환
2)tableView(_:cellForRowAt:) = 메소드를 구현하고, 셀 객체를 생성하여 콘텐츠를 구성한 다음 반환
3)tableView(_:didSelectRowAt:) = 메소드를 구현하고, 사용자가 셀을 선택했을 때 실행할 액션을 정의
textLabel : 위쪽의 title 레이블 대응하는 속성
detailTextLabel: 아래쪽의 subtitle레이블에 대응하는 속성
[커스텀 프로토타입 셀]
커스텀 타입으로 설정된 프로토타입 셀: textLabel 이나 detailTextLable과 같은 기본 속성 사용하여 셀 내부의 객체를 참조할 수 없다.
그 대신 스토리보드 상에서 객체에 태그값을 입력하고, 소스코드에서는 이 값을 이용하여 객체를 참조해야 함.
1) 태그 속성값을 이용 or
2) 아울렛 변수를 연결하여 참조하는 방법 (단, 프로토타입셀은 정적 객체로 화면에 존재하는 것이 아니라 단순히 설계와 초기원형으로만 존재하는 객체. 따라서, 아울렛 변수를 직접 뷰 컨트롤러에 드래그 하는 방식은 사용 불가)
[커스텀 클래스로 프로토타입 셀의 객체 제어하기]
프로토타입 셀 자체를 커스텀 클래스와 연결한 다음, 셀 위에 올려진 객체를 아울렛 변수로 연결해서 참조.
아울렛 변수를 뷰 컨트롤러에 직접 정의하면 셀 내부 객체들이 정적인 객체가 되므로 사용하는 데에 문제가 생긴다. 하지만, 프로토타입 셀을 연결한 커스텀 클래스에 아울렛 변수를 정의하면 이는 동적으로 사용할 수 있는 형태의 객체가 되기 때문에 아울렛 변수를 통해 객체를 관리할 수 있다.
출처: 꼼꼼한 재은씨의 swift 기본편 p485-
'iOS > iOS Swift 개발 일기' 카테고리의 다른 글
iOS swift 이미지 객체로 인한 메모리 점유가 걱정될 때 (0) | 2022.05.28 |
---|---|
iOS swift 코드 스니펫 (0) | 2022.05.28 |
iOS swift 델리게이트 패턴 (0) | 2022.05.26 |
ios swift 로컬 알림 -UserNotification framework (0) | 2022.05.25 |
ios swift 사용자에게 메시지를 전달하는 방법 (0) | 2022.05.24 |