개발을 잘하고 싶은 주니어?

테이블 뷰 공부하기 - 1 (인터페이스 빌더로 구현하기) 본문

개발/iOS

테이블 뷰 공부하기 - 1 (인터페이스 빌더로 구현하기)

데쿠! 2021. 10. 12. 23:10
반응형

이번에는 테이블 뷰에 대한 공부를 해보겠습니다.

우선 인터페이스 빌더로 테이블 뷰를 생성해서 다른 뷰로 데이터를 넘겨주는 것을 해보겠습니다.

다음 2번에서는 코드로 이것들을 다시 구현하는 것을 해볼 예정입니다.

 

Segue 

테이블 뷰의 셀을 클릭했을 때 셀의 데이터가 다른 뷰로 넘어가도록 하기 위해서는 segue라는 개념을 알아야 합니다.

애플 문서에서 보면 UIStoryboardSegue 클래스는 두 개의 뷰 컨트롤러 사이에 시각적인 전환을 수행하고 준비하는 오브젝트라고 되어 있습니다. 쉽게 말하자면 현재 뷰컨에서 다른 뷰컨으로 넘어가는 것을 준비하고 수행하는 오브젝트라는 것입니다.

Segue 오브젝트는 다음으로 넘어갈 뷰컨에 대한 정보가 포함되어 있습니다. segue가 수행되기 전에 (다음 뷰컨으로 넘어가기 전에) 스토리보드 런타임에서 현재 뷰컨의 메서드인 prepare(for: sender:)가 호출되고 이 메서드에서 다음 뷰컨으로 데이터를 줄 수 있습니다.

segue 오브젝트는 직접 만들 필요는 없고 두 뷰컨 사이에 segue를 수행해야 하는 경우에 스토리보드 런타임에서 생성합니다.

직접 호출할 수도 있는데 이 경우에는 현재 뷰컨의 메서드인 performSegue(withIdentifier:sender:) 메서드를 호출하면 됩니다. 

위와 같은 화면처럼 테이블 뷰의 셀을 클릭하면 새로운 뷰가 모달로 띄워지고 클릭한 셀의 정보가 새로운 뷰에 나타나도록 해보겠습니다.

1. 테이블 뷰에 셀을 추가하고 셀에 원하는 레이블을 놔줍니다. 또한 원하는 모습으로 오토레이아웃을 적용해줍니다.

2. 첫번 째 뷰의 뷰컨을 클릭하고 Ctrl+마우스 드래그 앤 드랍으로 두 번째 뷰에 놔줍니다. 그러고 나서 뜨는 팝업창에서 Present Modally를 클릭해줍니다.

Present Modally : Navigation 뷰컨 스택에 두 번째 뷰가 추가되지 않고 그냥 아래에서 위로 뷰가 올라오면서 보여지기만 한다. 
Show : Navigation Contoller에서 Push/Pop 중에서 Push에 해당한다. Show를 클릭하면 두번 째 뷰가 뷰컨 스택에 쌓이게 되면서 화면에 보여진다.

3. 그렇게 되면 첫 번째 뷰와 두 번째 뷰가 연결되었다고 스토리보드에서 시각적으로 표현됩니다.

 

 

두번째 뷰컨으로 데이터 보내기

위에서 보인 segue를 사용하기 위해서는 segue를 구별할 identifier가 필요합니다. (현재는 segue가 하나밖에 없지만 뷰컨이 많은 프로젝트의 경우에는 segue가 많이 생성될 수 있습니다.)

 

그러고 나서, 첫 번째 뷰컨 클래스에서 segue를 수행하는 것을 준비하는 메소드인 prepare를 오버라이딩하여 다음 뷰에 데이터를 보내줄 코드를 추가해줍니다.

* 첫번째 뷰컨 *

// 1
performSegue(withIdentifier: "showDetail", sender: indexPath.row)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // 2
    if let index = sender as? Int{
        // 3
        if segue.identifier == "showDetail"{
            // 4
            let vc = segue.destination as? DetailViewController
            vc?.name = nameList[index]
            vc?.age = ageList[index]
        }
    }
}

 

* 두 번째 뷰컨 *

class DetailViewController: UIViewController {
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var ageLabel: UILabel!
    var name: String?
    var age: Int?
    override func viewDidLoad() {
        super.viewDidLoad()
        updateUI()
    }
    func updateUI(){
        if let name = name, let age = age{
            nameLabel.text = name
            ageLabel.text = String(age)
        }
    }
}

1. performSegue(withIdentifier:sender:) 메서드는 segue를 수행하는 메서드입니다. 

이곳에서는 segue를 특정 identifier를 가진 segue를 초기화합니다. 원래는 자동으로 시작되긴 하는데 이렇게 직접 사용할 수도 있습니다. (스토리보드에서 segue를 설정하지 않았을 경우에 보통 사용합니다. 핸드폰을 흔드는 이벤트에 반응해서 수행할 커스텀한 액션 핸들러에서 부르는 경우에는 스토리보드에서 설정할 수 없으므로 이 메서드를 사용합니다. )

identifier : segue를 구별하는 string입니다. 인터페이스 빌더에서 지정할 수 있습니다.

sender : segue를 시작하기 위해 필요하다고 생각되는 object입니다. 이 object는 보통 정보를 주는 목적으로 사용됩니다.

(위에서는 어떤 셀이 클릭됐는지를 알려주는 indexPath가 sender로 보내진다)

2. sender로 보내진 index를 옵셔널 바인딩하고 

3. segue의 identifier를 확인합니다.

4. segue의 destination 정보를 가지고 해당 뷰컨의 name과 age를 원하는 데이터로 설정합니다.

두 번째 뷰컨에서 nameLable, ageLable의 text로 바로 설정하지 않고 name, age 변수를 따로 만들어서 설정한 이유?
prepare메서드는 두 번째 뷰컨이 메모리에 올라오기 전에 실행이 된다. nameLabel, ageLabel도 아직 메모리에 올라오지 않은 상태에서 바로 해당 레이블의 text프로퍼티를 설정해버리면 해당 레이블들은 nil인 상태이므로 크래시가 발생한다.

그래서 name, age에 데이터를 저장해놓고, 두번째 뷰컨이 메모리에 올라오고 나서 호출되는 viewDidLoad에서 해당 레이블의 text를 설정해줘야 한다.

 

이렇게 되면 완성! 이 됩니다.

 

반응형
Comments