TableView 만들기 (Swift + Storyboard)

다수의 Xib가 합쳐진 것이 스토리보드(Storyboard)이므로 Objetive-C 와 완전히 동일하다. Objective-C에서와 같이 테이블 뷰를 만들고 뷰 컨트롤러에 추가한다.

 

var dataTblDong = [String]()
var dataTblTppg = [String]()
@IBOutlet weak var mDongTable: UITableView!
@IBOutlet weak var mTypeTable: UITableView!

 

중요한 것은 바뀐 코드 형식이다. 테이블 2개를 만드는 실무 코드를 살펴보자.

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if tableView == self.mDongTable {
        return self.dataTblDong.count
    } else if tableView == self.mTypeTable {
        return self.dataTblTppg.count
    }
    return 1
}

데이터를 담을 전역 변수, 혹은 멤버 변수로 빼고 해당 변수의 개수로 리스트 항목(table rows)개수를 반환한다.

 

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = UITableViewCell()

셀은 코드 내부에서 정의 할 수 있다.


UITableViewCell

UITableViewCell 클래스 원형은 다음과 같다.

open class UITableViewCell : UIView, NSCoding, UIGestureRecognizerDelegate {
.
.
.

    // These properties will always return nil when a non-nil `contentConfiguration` is set.
    @available(iOS, introduced: 3.0, deprecated: 100000, message: "Use UIListContentConfiguration instead, this property will be deprecated in a future release.")
    open var imageView: UIImageView? { get } // default is nil.  image view will be created if necessary.

    @available(iOS, introduced: 3.0, deprecated: 100000, message: "Use UIListContentConfiguration instead, this property will be deprecated in a future release.")
    open var textLabel: UILabel? { get } // default is nil.  label will be created if necessary.

    @available(iOS, introduced: 3.0, deprecated: 100000, message: "Use UIListContentConfiguration instead, this property will be deprecated in a future release.")
    open var detailTextLabel: UILabel? { get } // default is nil.  label will be created if necessary (and the current style supports a detail label).
.
.
.

기본적으로 이미지뷰, 텍스트라벨, 세부 텍스트라벨을 가지고 있다. 이에, 따로 추가 없이 텍스트를 지정할 수 있다.

 

    let obj = self.dataTblDong[indexPath.row]
     cell.textLabel?.text = obj

 

텍스트를 지정하고 셀(cell) 을 리턴(return)하면 바로 텍스트를 볼 수 있다. 셀에 다양하게 속성 적용도 가능하다. 

    cell.backgroundColor = .white
    cell.textLabel?.textColor = .darkGray
    cell.selectedBackgroundView?.backgroundColor = .red
    cell.selectedBackgroundView?.tintColor = .blue
    if cell.description != nil { }

 

TIP! : 보다 자세한 내용은 UITableViewCell에서 cmd+option+0 키를 눌러 해당 함수에 대한 빠른 도움(Quick Help)을 보는 것이다. 가장 아래 Open in Developer documentation 링크를 따라가면 Xcode 에서 바로 사용법을 확인할 수 있다.

 

테이블이 2개인 경우 if 문으로 cell 을 세팅한다.

    if tableView == self.mDongTable{
        let obj = self.dataTblDong[indexPath.row]
        cell.textLabel?.text = obj


UIButton

기본으로 제공되는 ImageView를 이용하지 않고 버튼을 삽입 하려면 이미지 사이즈 조절 extension이 필요하다. cell 내부 이미지 사이즈 조절을 위한 extension 이다.

 

extension UIImage {

    func imageResize (sizeChange:CGSize)-> UIImage{
        let hasAlpha = true
        let scale: CGFloat = 0.0 // Use scale factor of main screen

        UIGraphicsBeginImageContextWithOptions(sizeChange, !hasAlpha, scale)
        self.draw(in: CGRect(origin: CGPoint.zero, size: sizeChange))
        let scaledImage = UIGraphicsGetImageFromCurrentImageContext()
        return scaledImage!
    }
}

https://stackoverflow.com/questions/24709244/how-do-set-a-width-and-height-of-an-image-in-swift

 

UIImage에 붙는 extension 이므로 사용법은 간단하다.

let imgUnChecked = UIImage(named: "hjh_icon_checkbox_none")?.imageResize(sizeChange: CGSize.init(width: 30, height: 30))
let imgChecked = UIImage(named: "hjh_icon_checkbox_checked")?.imageResize(sizeChange: CGSize.init(width: 30, height: 30))



이를 활용하여 다음과 같이 이미지 세팅된 버튼을 삽입 해보자.

      let imgUnChecked = UIImage(named: "hjh_icon_checkbox_none")?.imageResize(sizeChange: CGSize.init(width: 30, height: 30))
        let imgChecked = UIImage(named: "hjh_icon_checkbox_checked")?.imageResize(sizeChange: CGSize.init(width: 30, height: 30))
        
        let btn = UIButton(frame: CGRect(x: 10, y: 10, width: 30, height: 30))
        btn.addTarget(self, action: #selector(customCellButtonTapped), for: .touchUpInside)
        
        btn.setImage(imgUnChecked, for: .normal)
        btn.setImage(imgChecked, for: .selected)
        btn.imageEdgeInsets = UIEdgeInsets(top: 1, left: 6, bottom: 5, right: 2)
        btn.tag = 0
        cell.contentView.addSubview(btn)

 

다른 테이블도 동일하게 적용 가능하다.

        
    } else if tableView == self.mTypeTable
    {
        let obj = self.dataTblTppg[indexPath.row]
        cell.textLabel?.text = obj
        let imgUnChecked = UIImage(named: "hjh_icon_checkbox_none")?.imageResize(sizeChange: CGSize.init(width: 30, height: 30))
        let imgChecked = UIImage(named: "hjh_icon_checkbox_checked")?.imageResize(sizeChange: CGSize.init(width: 30, height: 30))
        let btn = UIButton(frame: CGRect(x: 10, y: 10, width: 30, height: 30))
        btn.addTarget(self, action: #selector(customCellButtonTapped2), for: .touchUpInside)
        btn.imageView?.contentMode = .scaleAspectFit
        btn.setImage(imgUnChecked, for: .normal)
        btn.setImage(imgChecked, for: .selected)
        btn.frame = CGRect(x: 0, y: 0, width: 44, height: 44)
        btn.imageEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
        btn.tag = 0
        cell.contentView.addSubview(btn)
    }
    return cell
}

 

TIP! : 필자의 경험상 개발 초기에 UI 관련해서는 중복 코드를 놔두는 것이 좋다. 메소드 추출(Extract Method)을 이용하여 공통 부분을 리팩토링(Refactoring) 한 이후, 개발에서 세부적이고 개별적인 수정 사항에 대해 빠른 대응이 어려워진다. 왜냐면 추출된 공통 부분에서 또 공통 모듈이 추출되기 때문이다. 협업을 하다보면, 최종적으로 하나의 기능만 하는 모듈만 따로 분리되어 재 사용성을 높히는데 의견이 모아진다. 그러나 커스텀 UI와 관련된 부분은 UI Guide Line 이 없는 경우 공통 Method 로 빼는 것을 가장 마지막에 할 작업으로 넘기는 것이 좋다. 최종 코드에서 완벽히 공통된 코드를 D&D 와 메소드로 추출 기능 한 번이면 손쉽게 리팩토링이 가능하다. 그럼에도 불구하고 앱개발 경험이 별로 없이 아키텍트라고 하는 사람들이 앱 코드 수정은 하지 않고 코드 리뷰로 일반적이고 상식적이며 뻔히 알고 있는 이야기로 개발이 된 후, 다시 지속적인 변경된 요구사항 받을 때는 결국 상품과 끝 단의 개발자만 홀로 남게 된다. 재 사용성을 높히고자 했던 많은 작업 때문에 공통 코드의 공통 코드를 따라가며 연결된 파라미터를 다시 코드로 펼치는 작업을 하는 경우가 태반이었다. 매우 아랫단(low level)의 코드를 구현 할 때는 for문을 쓰는 것과 똑같은 코드를 펼치는 작업이 CPU 파이프라인을 타는 부분도 다를 경우가 있어서 reset이 되는 문제가 있었다. Application 단에서 그런 경우를 접하거나 어셈블리 코드로 코드의 형평성을 따질 필요는 없지만 요구 사항에 기민하게 대응하는 것이라면 오히려 경험 많은 개발자의 말을 따르는 편이 좋다. 앱 개발을 안다고 해서 API가 내려 간 그 하부단 운영체제 시스템콜의 시퀀스를 모두 고려할 것이 아니라면 말이다. 요약하자면, 코드 리팩토링은 가장 마지막에 하는 것이 맞다. 시장에서도 완전히 안정화 된 상태. 관련 라이브러리나 실행 시스템의 메이저 버전업은 예상되지 않는 상태. 인수인계 직전 등 내 손에서 코드가 떠나기 전인 마지막을 말한다.

 

'Swift & Python 실무 > {APP} SOCANNER APP' 카테고리의 다른 글

iOS용 openCV 라이브러리 나왔으면 좋겠다.  (0) 2021.05.20
POD  (0) 2021.05.20
UINavigationBar  (0) 2021.05.18
오늘자 troubleshooting  (0) 2020.04.08
namedtuple  (0) 2020.04.08

+ Recent posts