관리 메뉴

김종권의 iOS 앱 개발 알아가기

[iOS - swift] 7. 테이블 뷰 (table view) 본문

iOS 기본 (swift)

[iOS - swift] 7. 테이블 뷰 (table view)

jake-kim 2020. 4. 3. 22:15

1. 테이블 뷰가 나온 배경

 - 방대한 콘텐츠를 표현하기 위함

 - 테이블 뷰의 완성 =  테이블 뷰 + 섹션1(테이블 뷰 셀 + 콘텐츠 뷰) + 섹션2(테이블 뷰 셀 + 콘텐츠 뷰) + 섹션n(...)

2. 일반적인 테이블 뷰

 - 테이블 뷰 셀의 종류 : Basic, Right Detail, Left Detail, Subtitle, Custom

 

1) 테이블 뷰 생성 : UITableViewController

  - 통째로 테이블 뷰 생성 : 스토리보드에서 UITablewView 드래그엔 드롭


  cf)  UITableViewController가 아닌, UIViewController에서 테이블 뷰 생성 : (1) ~ (4)작업

        (delegate, datasource, table view 각 추가)

      (1) "Table View"드래그 앤 드롭 

      (2) "Table View Cell"드래그 앤 드롭, tableView 뷰를 UIViewController에 @IBOutlet변수로 생성(타입은 UITableView!, 이름은 tableView로 설정된 상태)

      (3) 클래스 부분에 프로토콜 두 개를 extension으로 추가 : UITableViewDataSource, UITableViewDelgate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int-> Int {
        return list.count
    }
    
    func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        let cell = tableView.dequeueReusableCell(withIdentifier: "myCell")
        cell.textLabel?.text = "\(indexPath.row)번째 데이터입니다"
        return cell
    }
}
 
extension ViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 120
    }
}
 
 
http://colorscripter.com/info#e" target="_blank" style="text-decoration:none;color:white">cs

    (4) 권한 부여 : self.tableView.dataSource = self, self.tableView.delegate = self (또는 스토리보드에서 Dock Bar의 뷰컨트롤러를 테이블 뷰에 드래그앤 드롭 -> dataSource와 Degeate연결)

1
2
self.tableView.dataSource = self
self.tableView.delegate = self
 

 

  * 테이블 뷰에서 데이터가 없는 줄들을 없애는 방법은 텅 빈 view를 table view cell 밑에 높으면 해결


2) table view cell을 선택하여 id기입 ( UITableViewController안에서 사용할 재사용 큐에서 셀을 참조하기 위함 )

 

attribute instpector

 

3) 테이블 뷰 셀의 종류

 - static Cells(정적인 방법) : 프로그래밍적으로 구현한 것이 아닌 스토리보드에서 직접 구성한 것

 - dynamic cells(동적인 방법) : 고정되지 않고 갱신되는 내용을 표현할 때 사용 (주로 사용)

     -> 데이터 바인딩 : 데이터 소스를 테이블 뷰의 각 행에 연결하는 과정

                                  데이터 전달에 유용하게 하기 위해서는 아래와 같은 데이터 소스를 생성

1
2
3
4
5
6
7
8
9
10
11
class MovieVO {
  var thumbnail: String// 영화 섬네일 이미지 주소
  var title: String// 영화 제목
  var description: String// 영화 설명
  var detail: String// 상세정보
  var opendate: String// 개봉일
  var rating: Double? // 평점
  
  // 영화 썸네일 이미지를 담을 UIImage 객체를 추가한다
  var thumbnailImage: UIImage?
}
 
 

 

※ 네트워크 데이터를 다룰 때는 딕셔너리 형태인 NSDictionary를 많이 사용

var list = [NSDictionary]

 

 - 데이터 준비

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// ListTableViewController 
 var dataset = [
        ("다크 나이트""영웅물에 철학에 음악까지 더해져 예술이 되다""2008-09-04"8.95, "darknight.jpg"),
        ("말할 수 없는 비밀""여기서 너꺼지 다섯 걸음""2015-05-07"9.19, "secret.jpg")
    ]
    
    lazy var list: [MovieVO] = {
        var datalist = [MovieVO]()
        for (title, desc, opendate, rating) in self.dataset {
            let mvo = MovieVO()
            mvo.title = title
            mvo.description = desc
            mvo.opendate = opendate
            mvo.rating = rating
DispatchQueue.main.async {
             mvo.thumbnail = thumbnail
}
            datalist.append(mvo)
        }
        return datalist
    }() // 소괄호의 의미 : 해당 클로저를 실행한다는 의미
    
 
    // 주의 비슷한 방법의 연산프로퍼티는 "="를 사용하지 않음, 끝에 "()"를 쓰지 않음
    var list : [MovieVO] {
        return [(MovieVO()), MovieVO()]
} // 클로저가 아니므로 소괄호 안쓰는 것
 

 * 데이터를 튜플 형태로 줌으로써 가져다 쓰기 용이

 

4) UITableViewController에 준비한 데이터 정보 입력

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
extension ViewController: UITableViewDataSource, UITableViewDelegate {
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let row = list[indexPath.row]
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell"as! PersonCell
        
        cell.name.text = row.name
        cell.age.text= row.age
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int-> Int {
        return list.count
    }
}
 
 
extension ViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 120
    }
}
 
 
 
 
* PersonCell과 같은 커스텀은 따로 swift파일을 만들어서, UITableViewCell을 상속 받은 곳에 IBOutlet으로 정의한 것
1
2
3
4
5
6
7
8
9
10
11
12
13
class MovieCell: UITableViewCell {
 
  @IBOutlet var title: UILabel! // 영화제목
  
  @IBOutlet var desc: UILabel! // 영화 설명
  
  @IBOutlet var opendate: UILabel! // 개봉일
  
  @IBOutlet var rating: UILabel! // 평점
 
  @IBOutlet var thumbnail: UIImageView! // 섬네일 이미지
}
 
 

3. custom cell 

1) 커스텀 테이블 뷰 (custom cell)

 - 스토리보드에 있는 table view cell에 id값을 부여한 후, 적절히 뷰들을 배치

 - 새로운 MovieCell.swift추가하여(UITableViewCell 구현) 여기에 @IBOutlet변수 생성

 - 이 클래스를 스토리보드에서의 table view cell클래스 이름으로 연결

 - 나머지 작업은 동일 단, 재사용 큐 사용시 다운캐스팅이 필요

1
let cell = tableView.dequeueReusableCell(performSegue(withIdentifier: "myCell"as! MovieCell
 

2) cell에 관한 속성

(1) table view cell의 공간을 동적으로 변경

 - numberOfLines : 행 수 제한을 제거(1줄로 나와서 글이 잘리는 경우를 방지)

    cell.textLabel?.numberOfLines = 0

 

(2) 정한 text label안에 모든 내용 담기 (...이라는 잘린 표시 없이 다 넣는 방법)

 - cell.myTitle?.adjustsFontSizeToFitWidth = true

 

(3) table View에 이밖에 동적으로 데이터를 추가하는 경우에 (list.append되면), tableView메서드를 다시 불러야함

  -> self.tableView.reloadData() 사용

 

 

(4) tableView에 헤더 넣기 

  self.tableView.tableHeaderView = UIView객체 대입

 (단, headerView.addSubview에 이미지를 넣고 싶을 때, UIImage가 아니라 UIImgeView로 넣어야함)

1
2
3
4
5
6
7
8
9
10
11
12
  override func viewDidLoad() {
    // 테이블 뷰의 헤더 역할을 할 뷰를 정의한다.
    let headerView = UIView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: 70))
    headerView.backgroundColor = UIColor.brown
    
    // 테이블 뷰의 헤더 뷰로 지정한다.
    self.tableView.tableHeaderView = headerView
 
    // ( 하략 )
    
    headerView.addSubview(self.myLabel)
   }
 
 

 

*번외) 스토리보드가 아닌, 프로그래밍적으로 tableCell생성하는 방법

  '??' 연산자를 이용해서 nil체크 여부와 자동캐스팅 동시에 실행 (가장 좋은 방법)

1
2
3
4
5
6
7
8
9
10
   override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let id = "menu"
        let cell = tableView.dequeueReusableCell(withIdentifier: id) ?? UITableViewCell(style: .default, reuseIdentifier: id)
        
        cell.textLabel?.text = self.titles[indexPath.row]
        cell.imageView?.image = self.icons[indexPath.row]
        
        return cell
    }
 
 
 

 

 * UITableViewCell에서의 style 

.default
.subtitle
.value1
.value2

 

* 코드 출처 : 꼼꼼한 재은씨의 스위프트 : 기본편

 

* programmatically 테이블 뷰 사용하기 : ios-development.tistory.com/71

 

[iOS - UI Custom] 12. table view (programmatically)

(위와 같이 데이터가 없는 곳에도 줄 간격이 생기므로, 이것을 제거하려면 다음 코드를 추가) self.tableView.separatorStyle = .none * table view를 custom 한다는 것 <=> UITableViewCell을 상속받아서 custom..

ios-development.tistory.com

 

Comments