본문 바로가기
IT/프로그래밍 노트

027 Table view , Delegate Pattern

by 33.0 2025. 3. 15.
728x90

 

iOS 버전 별 사용자 비율 

xcode - General - MinimumDeployments - 개발하는 앱의 최소 소프트웨어 버전을 설정하는 메뉴다. 

 

https://developer.apple.com/support/app-store/

 

App Store - Support - Apple Developer

App Store The App Store makes it simple for users to discover, purchase, and download apps for iPhone, iPad, Mac, Apple TV, and Apple Watch. Enroll in the Apple Developer Program to distribute your apps worldwide on the App Store.

developer.apple.com

OS별 사용 비율이 나와 있다. 

 

2025년 1월 21일 기준으로 ios 버전 사용 비율이다. 

 

Table view 

사용할 메뉴가 수직방향의 목록으로 표시되어 있는 방식의 화면을 이야기한다.  

수평 스크롤은 컬렉션 뷰를 사용하면 된다. 테이블 뷰와 구현방식이 비슷하다.

용어

Cell

테이블 뷰에 표시되는 하나의 항목 

Table View Section / Section

Cell들이 모여서 그룹을 만드는 것을 섹션이라고 한다. 

Cell Accessory / Accessory 

셀 안에 앵글브라켓이 있는건 터치했을 때 새로운 화면이 표시된다는 뜻이다. 

앵글 브라켓을 악세사리라고 한다. 

 

스토리 보드에서 테이블 뷰 추가, 코드 연결

 

Command Shift L - Table view 추가 , 전체화면으로 확장 , 핀버튼에서 제약 추가

-- 이때 추가했던 Table view는 껍데기라고 한다. 

 

다시 Command Shift L - Table view Cell 추가 

-- 셀을 추가할 수 있다. 

Cell 선택 - atribute inspector -

style 을 통해서 Custom, Basic, Right Detail, Left Detail, Subtitle 등 선택할 수 있다. 

identifier - cell 이라고 입력, identifier는 대소문자를 구분하기 때문에 정확하게 입력해야한다. 

나중에 디자인을 가져와서 데이터를 채운 다음 리턴해야하는데 디자인을 가져올 때 사용하는 이름이 identifier다. 나중에 크래쉬가 발생할 수 있으니 이 값은 꼭 잘 확인해야한다. 

이 다음 View Controller 와 Prototype Cells를 연결시켜줘야한다. 

사이드 메뉴에서 Table View 클릭, 스토리 보드에서 우클릭 컨넥션 패널에서 outlets - datasource 에서 오른쪽 동그라미 잡고 view controller에 드래그 혹은 Scene Dock 씬 독에 있는 첫번째 아이콘으로 드레그 

목록을 표시할 때 스토리보드에서 해야할 기본적인 작업은 여기까지다 

 

여기서 추가된 Prototype cells은 설계도이다. cell하나가 아니다. 

이렇게 간단하게 연결되어 있는 클래스로 이동할 수 있다. 

 

 

import UIKit

class ViewController: UIViewController, UITableViewDataSource { 
//여기서 ViewController는 UIViewController클래스를 상속받고 있다. 얼핏보면 다중상속같지만 
//UITableViewDataSource는 프로토콜이다. 
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }


}

 

UIViewController - 화면을 구현할 때 필요한 기본적인 기능이 구현되어 있는 클래스 이다.  

클래스 의 이름 콜론다음에 이름이 오면 클래스 혹은 프로토콜 , 두번째 이후로 오는 이름은 무조건 프로토콜이다.  

이렇게 기존 클래스에 프로토콜을 추가하면 에러메시지가 발생한다. conform을 작성하라는 것이다. 

conform - 프로토콜이 요구하는 멤버를 구현하는 것 , 우리나라 말로는  따르다. 채택한다. 채용한다. (프로토콜을 따른다.)

 

class ViewController: UIViewController, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 100
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = "\(indexPath.row)"
        return cell
    }
    

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }


}

fix를 누르면 func tableview 메서드가 두개 뜬다. 이렇게 작성해주면 된다. 

 

Delegate Pattern 델리게이트 패턴 

Delegate Patten

한 객체가 처리못하는 기능을 다른 객체가 처리해주는 것. (= 위임한다)

 

Delegator 위임자 : 작업을 위임하는 객체  (부탁하는 객체)

Delegate 대리자 : 실제 작업을 수행하는 객체  (부탁받는 객체)

 

다른 객체로 부터 위임받은 객체를 Delegate Object , Delegate 라고 한다. 

델리게이트 패턴으로 구현하는 대표적인 예가 테이블 뷰이다. 

과정 

위임자의 dataSource , delegate 속성에  대리자를 저장하면 된다. 

dataSource 속성 :  데이터 베이스나 서버에 접근하여 정보를 알아내는 객체  

delegate 속성 : 이벤트를 대신 처리하는 객체 , 항목을 선택하거나 삭제했을때 이벤트가 발생했다는 것만 알려줌 

 

델리게이트한테 이벤트가 발생했다고 알려주고 (메서드를 호출)

 

델리게이트가 이벤트를 처리한다. (메서드 구현) 

 

Protocol 프로토콜

델리게이트가 메서드를 구현하는 것은 반드시 지정된 형식으로 구현해야한다. 

이러한 메서드는 프로토콜로 선언되어 있으니 그 프로토콜에 선언되어 있는대로 메서드를 구현해야한다. 

 

Protocol 프로토콜 : 위임자가 대리자에게 전달할 메서드를 정의한 규약 

 

문제가 생기는 경우 

1. 델리게이트 객체가 없는 경우 -  크래쉬 발생 

2. 델리게이트 객체가 있지만 메소드를 구현하지 않아 부탁을 못들어주는 경우 반드시 처리해야할 이벤트라면 필수메소드를 구현해야 하는데 필수메소드를 구현하지 않는 경우 - 크래쉬 발생. swift에서 컴파일 에러 발생

3. 이벤트 가 반드시 처리해야할 필요가 없는 경우, 부탁할 대상이 없으면 이벤트를 무시, 부탁할 대상은 있으나 메소드를 구현하지 않으면 이벤트 무시하고 끝난다. 메서드를 구현되어 있으면 해당 이벤트에서 호출해서 처리. 

 

코드 구현의 3가지 step 

checking the methods to implement 

레퍼런스를 보면서 델리게이트가 필요한지 확인, 

델리게이트가 필요하면 프로토콜 레퍼런스로 가서 어떤 메소드가 선언되어있고 어떤게 필수 메소드인지 확인 

 

connecting two objects

객체 연결 , 스토리보드나 코드에서 연결 

뷰 컨트롤러가 델리게이트 객체가 된다. 

 

implementing protocol methods 

델리게이트 객체로 가서 프로토콜 메서드 구현 

뷰 컨트롤러가 델리게이트 객체라면 뷰컨트롤러 클래스 안에서 구현하거나 

익스텐션으로 따로 분리해서 가독성을 높일 수 있음. 

 

prototype Cells 

- 새로운 셀을 만들때 사용하는 설계도 

table view는 이름으로 cell을 구분, re-use identifier 

 

테이블 뷰를 선택하고 

 

 

 

UItableViewDataSource 

프로토콜, 테이블 뷰에 데이터를 관리하고 셀을 제공하기 위해 객체가 채택하는 메서드.  

프로토콜에 대한 정보 검색하기 

https://developer.apple.com/documentation/uikit/uitableviewdatasource#topics

구글에서 프로토콜 이름을 검색해서 apple에서 확인할 수 있다. 

프로토콜 검색 -  Topics 란에 있는 'Required'라고 표시된 메서드는 필수 메서드이기 때문에 꼭 코드를 작성해야한다. 

해당 메서드 클릭하면 메서드의 이름, 언제 호출되는지 알 수 있다. 이런 부분은 파악하고 있어야한다. 

 

<UItableViewDataSource 의 필수메서드> 

 

첫번째 필수 메서드 - tableView(_: numberOfRowsInSection:)

UITableView, 즉 자기 자신을 파라미터로 받고 있고 numberOfRowsInSection을 받고 있다. 해당 이름을 클릭하면 

인스턴스 메소드임을 확인할 수 있다. 
데이터 소스에 지정된 섹션에 표시할 Row의 갯수를 리턴하라고 지시한다. 섹션이 여러개라면 두번째 파라미터에 적절한 값을 리턴하면 된다. 

테이블 뷰에 표시할 cell의 갯수를 리턴하면 된다. 

 

두번째 필수 메서드- tableView(_: cellForRowAt:)

첫번째 메서드를 통해서 테이블 뷰는 몇개를 표시해야 하는지 알게되었다. 

이제 테이블뷰는 어떤 데이터를 어떻게 표시해야하는지를 묻고 있는 것이다. 

테이블 뷰의 각 행(Row)에 표시할 셀(UITableViewCell)을 생성하고 반환하는 역할을 하는 메서드이다. 

이 메서드는 테이블 뷰의 각 행들이 화면에 표시될때마다 호출되는 메서드이다. 

table view - 셀을 요청하는 UITableView 객체 

indexPath - 셀의 위치를 나타내는 IndexPath객체

cell 도 index를 가지고 있다. cell index는 Rawindex라고 하기도 한다. 

section index - 0 부터 시작 Row index - 0부터 시작 

 

예) 스크린 타임 의 section index - 2 , row index - 0 

예) 손쉬운 사용의 section index - 1 , row index - 1

 

UITableViewCell 

셀을 만든다음 표시할 데이터를 채우고 완성된 셀을 리턴 해주는 타입 

 

실전 코드 분석 

class ViewController: UIViewController, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 100
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        // #1 
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        // #2
        cell.textLabel?.text = "\(indexPath.row)"
        // #3
        return cell
    }

 

#1. 셀을 만들때는 생성자를 사용하는게 아니라 Table view가 제공하는 메서드를 사용해서 만든다. 

dequeueReusableCell(withIdentifier: , for: )

테이블 뷰는 새로운 셀을 만들지 않고 재사용 큐(queue)를 확인, 사용할 수 있는 셀이 있는지 봄. 재사용 가능한 셀이 있다면, 없다면  새로운 걸 만들어 주고 파라미터로 identifier와 일치하는 셀을 만들어서 리턴해줌. 

-> 메모리 절약 효과 

cell에서 identifier에 저장한 값과 withIdentifier의 문자열을 비교하여 설계도에 맞게 Cell을 만드는 것이므로 오타 금지 

for: 에는 indexPath 라고 입력하면 됨. 

 

#2. 

Cell 의 Style - Basic 로 선택하면 셀에 자동으로 추가된 textLabel 이라는 이름으로 접근 가능, text 속성에 접근해서 원하는 문자열을 저장하면 Label에 표시된다. 

지금은 셀의 인덱스 즉 로우인덱스를 표시하고 있다. => "\(indexPath.row)"

만약 섹션 인덱스도 같이 표시하고 싶다면 

"\(indexPath.section) - \(indexPath.row)" 라고 수정하면 된다. 

 

 

#3. 

마지막으로 cell 을 리턴하면 된다. 

 

 

 

 

728x90