Programming/Swift

[Swift] Table Controller

Aosta 2021. 7. 25. 16:02

Table View Controller Object 는 Android 의 Listview 와 유사한 기능이다.

 

1. Main.storyboard 와 project에 있는 ViewController 를 지워준다.

2. Table View Controller Object 를 storyboard 에 추가해준다.

3. Embed In > Navigation bar 하고 initial 해준다.

4. 이어지는 ViewController 들을 만들어주고 View 를 구성한다.

5. TableViewController 와 다른 ViewController 를 연결해준다.

  • TableViewController 에서 Tv list View와 리스트 Detail 을 담당하는 ViewController 를 연결시켜준다.
  • Table View Cell 와 Detail 로 가는 Segue 에 identifier 를 준다.

6. Table View 와 연결된 ViewController 에서도 사용이 가능한 변수를 만들어 준다.

  • '처음 뜨는 화면' 에서 변수를 지정해준다.
  • 이 변수들은 Project 전체에서 사용이 가능한 변수이다.
  • 관리를 class 가 아니라 project 차원에서 한다.
import UIKit

// 변수 선언을 Class 정의 전에 한다.

var items = ["책 구매", "철수와 약속", "스터디 준비하기"]
var itemsImageFile = ["cart.png", "clock.png", "pencil.png"]


class TableViewController: UITableViewController {

 

7. Table view data source

  • numberOfSections

numberOfSections return 의 차이

  • tableview : cellForRowAt ( 셀에 들어가는 내용 // withIdentifier 에 꼭 cell identifier 를 넣어줘야한다 !! )
        override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath)
            
            cell.textLabel?.text = items[indexPath.row]
            cell.imageView?.image = UIImage(named: itemsImageFile[indexPath.row])
            
            return cell
        }​
  • tableview : canEditRowAt ( Edit 버튼으로 수정이 가능한지 여부 )

canEditRowAt 의 차이

  • tableview : moveRowAt ( 기존에 있는 위치를 삭제하고 원하는 곳에 새로 넣는다는 개념이다 )
    // Override to support rearranging the table view.
    override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
            
        // 이동할 item 의 위치
        let itemToMove = items[fromIndexPath.row]
        let itemImageToMove = itemsImageFile[fromIndexPath.row]
            
        // 이동할 item 을 삭제
        items.remove(at: fromIndexPath.row)
        itemsImageFile.remove(at: fromIndexPath.row)
            
        // 이동 위치를 찾고 빼내서 그쪽으로 이동한
        items.insert(itemToMove, at: to.row)
        itemsImageFile.insert(itemImageToMove, at: to.row)
    }​

8. Navigation Setting

  • target 에서 값을 받을 전역변수를 만들어둔다.
    // target 의 전역변수
    var receiveItem = ""
    
    // target 의 전역변수와 prepare 로 받아온 값을 일치시켜주는 func
    func receiveItems(_ item: String) {
        // TableViewController 는 이 함수를 실행 시킬 것임
        receiveItem = item
    }​
  • Table View Controller 의 Navigation 에서 segue 를 찾아 값을 지정해준다.
    // MARK: - Navigation
    
    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
        if segue.identifier == "sgDetail"{
            let cell = sender as! UITableViewCell
            let indexPath = self.tvListView.indexPath(for: cell)
            // 이상황이면 indexPath가 몇번째 자리인지 알고 있다.
            
            let detailView = segue.destination as! DetailViewController
            // DetailViewController 에 있는 함수에 값을 넣어준다
            detailView.receiveItems(items[indexPath!.row])
    	}
            
    }​

 

[ AddViewController ]

import UIKit

class AddViewController: UIViewController {

    @IBOutlet weak var tfAddItem: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
            
    @IBAction func btnAddItem(_ sender: UIButton) {
        // TableViewController 에 있는 배열에 값 넣어주기
        items.append(tfAddItem.text!)
        itemsImageFile.append("clock.png")
        navigationController?.popViewController(animated: true)
        
    }
    
} // AddViewController

 

[ 전체코드 ]

//
//  TableViewController.swift
//  Table
//
//  Created by 박재원 on 2021/07/22.
//

import UIKit

// 변수 선언을 Class 정의 전에 한다.
// 그 이유는 project 전체에서 사용할 수 있게 한다.
// 이 쪽은 class 가 아니라 project 가 관리하는 구역이다. * * * * * * * * * * * * * * * * * * *
// 그리고 '처음뜨는 화면' 에서 해줘야한다.

var items = ["책 구매", "철수와 약속", "스터디 준비하기"]
var itemsImageFile = ["cart.png", "clock.png", "pencil.png"]


class TableViewController: UITableViewController {

    // TableView와 꼭 연결해야한다!!
    @IBOutlet var tvListView: UITableView!
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false

        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        // self.navigationItem.rightBarButtonItem = self.editButtonItem
        
    
        // Edit버튼을 만들고 삭제 기능을 추가하기, 왼쪽으로 배치
        self.navigationItem.leftBarButtonItem = self.editButtonItem
   
    } // viewDidLoad
    
    
    // 위 : 화면 뜨기전에 동작     아래 : 화면 뜬 다음에 동작
    
    // 이 부분이 없으면 viewDidLoad 만 실행되고 있으면 여기까지 동작한다.
    // 화면이 뒤로 숨었다가 다시 나타날때 동작하는 함수이다! (Life Cycle)
    override func viewWillAppear(_ animated: Bool) {
        // 이 메소드로 아래에 있는 함수들 다시한번씩 실행시켜줌.
        tvListView.reloadData()
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return items.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath)
        
        cell.textLabel?.text = items[indexPath.row]
        cell.imageView?.image = UIImage(named: itemsImageFile[indexPath.row])
        
        return cell
    }

    
    // Override to support conditional editing of the table view.
    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        // Return false if you do not want the specified item to be editable.
        return true
    }
    

  
    // Override to support editing the table view.
    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            items.remove(at: indexPath.row)            // 선택한 'row'의 데이터 삭제
            itemsImageFile.remove(at: indexPath.row)   //

            // Delete the row from the data source
             tableView.deleteRows(at: [indexPath], with: .fade)  // Data를 지웠으면 화면에서도 지워주기
        } else if editingStyle == .insert {
            // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
        }    
    }
   
    // 삭제시 Delete 라고 나오는 것 '삭제'로 보이게 하기
    override func tableView(_ tableView: UITableView, titleForDeleteConfirmationButtonForRowAt indexPath: IndexPath) -> String? {
        return "삭제"

    }
    // 목록 순서 바꾸기
    // Override to support rearranging the table view.
    override func tableView(_ tableView: UITableView, moveRowAt fromIndexPath: IndexPath, to: IndexPath) {
        
        // 이동할 item 의 위치
        let itemToMove = items[fromIndexPath.row]
        let itemImageToMove = itemsImageFile[fromIndexPath.row]
        
        // 이동할 item 을 삭제
        items.remove(at: fromIndexPath.row)
        itemsImageFile.remove(at: fromIndexPath.row)
        
        // 이동 위치를 찾고 빼내서 그쪽으로 이동한
        items.insert(itemToMove, at: to.row)
        itemsImageFile.insert(itemImageToMove, at: to.row)
    }
        
        
    /*
    // Override to support conditional rearranging of the table view.
    override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
        // Return false if you do not want the item to be re-orderable.
        return true
    }
    */

    
    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destination.
        // Pass the selected object to the new view controller.
        if segue.identifier == "sgDetail"{
            let cell = sender as! UITableViewCell
            let indexPath = self.tvListView.indexPath(for: cell)
            // 이상황이면 indexPath가 몇번째 자리인지 알고 있다.
            
            let detailView = segue.destination as! DetailViewController
            // DetailViewController 에 있는 함수에 값을 넣어준다
            detailView.receiveItems(items[indexPath!.row])
        }
        
    }
    

    
}