프로그래밍/iOS
[UIKit] TableViewCell에서 AutoLayout 동적으로 추가 및 삭제하기(AutoLayout programmatically Swift)
병인
2022. 12. 25. 14:11
프로젝트를 하던 도중 TableViewCell에 AutoLayout을 동적으로 추가를 할 일이 생겼다.
하단은 프로필에 상태메세지가 없을 경우 사용자 이름을 centerYAnchor로 주는 코드이다.
if(self.dataSource[indexPath.section][indexPath.row].statusMsg == nil) {
cell.name.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
} else {
cell.name.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
cell.statusMessage.text = self.dataSource[indexPath.section][indexPath.row].statusMsg
}
여기서 TableViewCell의 Reuse 부분에서 문제가 생겼다.
나는 당연히 isActive = true / false 하면 해당 제약조건이 없어질 줄 알았으나... 하단의 이미지를 보고 맨탈이 붕괴되었다.
우선 기초적인 Reuse하면서 초기화 하는 부분을 빼먹었다.
override func prepareForReuse() {
image.image = nil
name.text = nil
statusMessage.text = nil
}
하지만 제약 조건은 돌아오지 않았다.
해당 부분에 대해 검색을 해보니 하단의 코드는 새로운 제약조건을 추가하고 Active만 false 처리 되는 코드인 것이다.
if(self.dataSource[indexPath.section][indexPath.row].statusMsg == nil) {
cell.name.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
} else {
cell.name.centerYAnchor.constraint(equalTo: self.centerYAnchor).isActive = true
cell.statusMessage.text = self.dataSource[indexPath.section][indexPath.row].statusMsg
}
따라서 programmatically 하게 한답시고 Cell을 재사용 할 때마다 신규 제약 조건을 매우 많이 추가해주고 있는 것이다.
이 부분을 해결하기 위해 Cell에 제약조건을 변수로 두고 해당 변수의 active를 활성 / 비활성화 해주어 해결했다.
class tableViewCell : UITableViewCell {
var nameCenterYAnchorConstraint : NSLayoutConstraint?
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
nameCenterYAnchorConstraint = name.centerYAnchor.constraint(equalTo: self.centerYAnchor)
setLayout()
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: tableViewCell.identifier, for: indexPath) as! tableViewCell
if(self.dataSource[indexPath.section][indexPath.row].statusMsg == nil) {
cell.nameCenterYAnchorConstraint?.isActive = true
} else {
cell.nameCenterYAnchorConstraint?.isActive = false
cell.statusMessage.text = self.dataSource[indexPath.section][indexPath.row].statusMsg
}
}
다른 제약 조건들은 생성할 때 init에서 1번만 호출되므로 문제가 없다.
동적으로 제약 조건을 추가할 때는 변수 사용을 적극 권장한다.