240502
지난 투두리스트 만들 때는 스토리보드로 만들었는데 이번에 코드만으로 만들어 봤다
UI 도 좀 바꿔서 함
화면 구성
Snapkit 사용
화면 상단 TextField 에 위치시키고 내용을 적고 키보드 상에서 Done을 누르면 리스트가 추가 됨
Userdefaults 로 데이터 저장
스와이프로 삭제
(이건 아직 안함!!)할 일 완료시 리스트 하나를 클릭하면 취소선, 텍스트 회색으로 바뀜
코드 짠 순서대로 기록해 볼까 한다
Struct 생성
struct Task : Codable {
let title: String // 타이틀. 할 일 내용
var done: Bool // 완료 여부
}
담을 빈 배열 생성
var toDoList = [Task]()
텍스트필드, 테이블뷰 생성
let textField = UITextField()
let tableView = UITableView()
오토레이아웃
func setupConstraints() { // addSubview, 오토레이아웃 등
view.addSubview(textField)
view.addSubview(tableView)
textField.snp.makeConstraints {
$0.top.equalTo(view.safeAreaLayoutGuide)
$0.leading.equalToSuperview().offset(24)
$0.trailing.equalToSuperview().offset(-24)
$0.height.equalTo(50)
}
tableView.snp.makeConstraints {
$0.top.equalTo(textField.snp.bottom).offset(20)
$0.leading.trailing.bottom.equalToSuperview()
}
}
속성 값 설정
func configureUI() { // UI 요소들의 속성을 대입(컬러, text 등)
view.backgroundColor = .systemBackground
textField.borderStyle = .roundedRect // 테두리 스타일
textField.layer.borderColor = UIColor.systemGray.cgColor
textField.layer.borderWidth = 2.0
textField.layer.cornerRadius = 5
textField.placeholder = "할 일이 뭔데"
textField.clearButtonMode = .always // 입력내용 한번에 지우는 x버튼(오른쪽)
textField.clearsOnBeginEditing = false // 편집 시 기존 텍스트필드값 제거?
textField.returnKeyType = .done
tableView.backgroundColor = .systemBackground
tableView.register(ToDoListTableViewCell.self, forCellReuseIdentifier: ToDoListTableViewCell.identifier)
}
화면 터치하면 키보드 내려감
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?){
self.view.endEditing(true)
}
view 전체적으로 테이블뷰가 깔려 있어서 키보드 부분 제외하고 나머지 아무곳이나 클릭해서 내려가지 않고
텍스트필드 밑에 약간 깔린 뷰쪽만 클릭이 먹는다
일단 이게 중요한게 아니어서 패스하지만 고쳐놔 봐야지
텍스트 필드에서 Done 을 하면 테이블뷰에 리스트가 추가
extension ViewController: UITextFieldDelegate {
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
print("textFieldShouldReturn: \(textField.text ?? "")")
textField.resignFirstResponder() // Done 누르면 키보드 내려감
guard let title = textField.text else { return false }
self.addToDoItem(title: title)
print("[toDoList] \([toDoList])")
textField.text = "" // 텍스트 필드 안에 텍스트 비움
tableView.reloadData()
return true
}
}
테이블 뷰에 추가하는건 따로 함수를 만들어서 넣었다
리스트에 추가 함수
func addToDoItem(title: String) {
self.toDoList.append(Task(title: title, done: false)) //리스트에 할 일 추가해줌
saveData()
print("리스트에 할 일 추가")
self.tableView.reloadData() //추가한 리스트를 보여줌
print("할 일 추가 후 reloadData")
}
완료 여부인 bool 값은 일단 다 false로 넣어줌
그리고 이걸 저장하는 함수도 따로 만들어 주었다
반드시 releadData 할 것!
UserDefaults 로 저장하는 함수
func saveData() {
let toDoList = self.toDoList.map { task in
["title": task.title, "done": task.done]
}
UserDefaults.standard.setValue(toDoList, forKey: "ToDoList")
}
map 을 사용해서 하나씩 배열에 저장 됨
데이터를 로드하는 함수
func loadData() {
print("loadData")
guard let toDoList = UserDefaults.standard.value(forKey: "ToDoList") as? [[String : Any]] else { return }
self.toDoList = toDoList.compactMap { todo -> Task? in
guard let title = todo["title"] as? String, let done = todo["done"] as? Bool else { return nil }
return Task(title: title, done: done)
}
}
데이터가 로드되는건 viewDidLoad 에서 진행 된다
override func viewDidLoad() {
super.viewDidLoad()
setupConstraints()
configureUI()
textField.delegate = self
tableView.delegate = self
tableView.dataSource = self
loadData()
}
위에서 작성한 오토레이아웃과 속성값 그리고 loadData를 넣어주고
테이블뷰와 텍스트 필드의 delegate,dataSource 도 대리자 위임하는거 잊지 말기!!
테이블뷰 delegate, datasource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
toDoList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: ToDoListTableViewCell.identifier, for: indexPath) as? ToDoListTableViewCell else { return ToDoListTableViewCell() }
let toDoList = toDoList[indexPath.row]
cell.title.text = toDoList.title
cell.selectionStyle = .none
return cell
}
배열에 들어온 수 만큼 셀을 뿌리고
셀의 텍스트는 입력한 텍스트가 들어 갑니다
그리고 매번 방법을 까먹어서 검색하는,, 기본값으로 셀을 선택하면 선택한 셀이 회색으로 되는데
cell.selectionStyle = .none
요걸로 그 설정을 꺼줍니다
스와이프로 해당 셀 삭제
func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return .delete
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
toDoList.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
saveData()
} else if editingStyle == .insert {
}
}
셀의 설정을 .delete 로 설정해 줍니다
삭제 될때 먼저 배열에 해당하는 값을 지워주고
테이블뷰에 해당하는 셀을 지워줍니다
그리고 saveData 로 데이터를 저장해 주면 끝
저번 투두리스트 만들 때 saveData 가 들어가는 순서에 따라 오류가 났었던 기억이 나는데
일단 지금은 오류가 안나므로 여기서 마무리 하겠슴다
완료시 텍스트 설정이 바뀌는 것도 하게 되면 추가해 둘게요!
'iOS Swift > Study' 카테고리의 다른 글
Swift 버튼 좌측에 이미지 넣기 시도하다가 포기하고 UIView 로 그린썰 푼다 (0) | 2024.05.04 |
---|---|
Swift 버튼에 시스템 이미지 크기 바꾸기 (0) | 2024.05.04 |
Swift TMDB api 네트워킹 연습 (1) | 2024.05.02 |
Swift Delegate 패턴 예제로 알아보기 (6) | 2024.04.30 |
Swift codebase UI 그리기 내 버튼 왜 클릭 안돼 (6) | 2024.04.30 |
댓글