🧑💻 오늘까지 진행한 요구사항
[ ContactsViewController.swift ]
// CoreData 데이터 수정하기
func updateData(currentName: String, updateName: String, currentPhoneNumber: String, updatePhoneNumber: String, currentImgaeUrl: String, updateImageUrl: String) {
// 수정할 데이터를 찾기 위한 fetch request 생성
let fetchRequest = Contacts.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "name == %@", currentName) // 예시: 이름이 "Adam"인 데이터 수정
do {
// fetch request 실행
let result = try self.container.viewContext.fetch(fetchRequest)
// 결과 처리
for data in result as [NSManagedObject] {
// 데이터 수정
data.setValue(updateName, forKey: Contacts.Key.name)
data.setValue(updatePhoneNumber, forKey: Contacts.Key.phoneNumber)
data.setValue(updateImageUrl, forKey: Contacts.Key.imageUrl)
// 변경 사항 저장
try self.container.viewContext.save()
print("데이터 수정 완료")
}
} catch {
print("데이터 수정 실패")
}
}
// 저장된 데이터 선택 삭제
func deleteData(name: String) {
// 삭제할 데이터를 찾기 위한 fetch request 생성
let fetchRequest = Contacts.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "name == %@", name)
do {
// fetch request 실행
let result = try self.container.viewContext.fetch(fetchRequest)
// 결과 처리
for data in result as [NSManagedObject] {
// 삭제
// CRUD 의 D.
self.container.viewContext.delete(data)
print("삭제된 데이터: \(data)")
}
// 변경 사항 저장
try self.container.viewContext.save()
print("데이터 삭제 완료")
} catch {
print("데이터 삭제 실패: \(error)")
}
}
private func configureUI() {
view.backgroundColor = .white
// 등록할 때 로직
if isModify == false {
self.title = "연락처 추가"
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "등록", style: .plain, target: self, action: #selector(naviButtonTapped))
deleteButton.isHidden = true
// 수정할 때 로직
} else {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "수정", style: .plain, target: self, action: #selector(modifyButtonTapped))
// 옵셔널 값 처리
guard let modifyContact = modifyContact else { return }
self.title = modifyContact.name
nameTextField.text = modifyContact.name
phoneNumberTextField.text = modifyContact.phoneNumber
AF.request(modifyContact.imageUrl).responseData { response in
if let data = response.data, let image = UIImage(data: data) {
DispatchQueue.main.async {
self.circleImageView.image = image
}
}
}
deleteButton.isHidden = false
}
@objc private func modifyButtonTapped() {
print("수정 버튼 클릭")
guard let modifyContact = modifyContact else { return }
updateData(currentName: modifyContact.name, updateName: nameTextField.text ?? modifyContact.name, currentPhoneNumber: modifyContact.phoneNumber, updatePhoneNumber: phoneNumberTextField.text ?? modifyContact.phoneNumber, currentImgaeUrl: modifyContact.imageUrl, updateImageUrl: self.imageUrl.isEmpty ? modifyContact.imageUrl : self.imageUrl)
self.navigationController?.popViewController(animated: true)
}
@objc private func deleteButtonTapped() {
print("삭제 버튼 클릭")
guard let modifyContact = modifyContact else { return }
deleteData(name: modifyContact.name)
self.navigationController?.popViewController(animated: true)
}
✓ TIL
[ 테이블 뷰의 셀을 클릭했을 때 ViewController 넘어가는 방법 ]
UITableView 함수 중에 didSelectRowAt 함수를 이용하여 셀을 클릭하였을 때 처리를 하였다.
// 테이블 뷰 클릭 시 이벤트 처리
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let modifyVC = ContactsViewController()
modifyVC.isModify = true // 수정이면 isModify의 값을 true로 변경
// 정보를 넘겨주기 프로퍼티로 정보를 가지고 있어야 한다.
// 옵셔널로 가지고 있어야 한다. 수정이 될수도 있기 때문에 ex) 값이 있으면 수정, 없으면 추가
let contact = contactsTableData[indexPath.row]
modifyVC.modifyContact = contact
navigationController?.pushViewController(modifyVC, animated: true)
}
셀을 클릭했을 때 ContactsViewController에 정보를 넘겨주기 위해 ContactsViewController를 modifyVC에
인스턴스를 생성하고, ContactsViewController에 있는 isModify 변수의 값을 true로 설정한다.
isModify는 수정 상태인지 확인하는 변수이며 true는 수정, false는 추가로 처리된다.
다음은 contact 변수에 현재 클릭된 셀의 값인 indexPath.row를 이용하여
contactsTableData의 [해당 인덱스]값을 받아온다.
그다음 ContactsViewController에 있는 ContactsModel 구조체 형식의 modifyContact의 변수에
방금 받은 contact값을 보내준다. 이러면 ContactsViewController에서 선택한 셀의 데이터를 이용하여
처리를 할 수 있다.
마지막으로 navigationController의 pushViewController를 이용해서
ContactsViewController이 화면에 뜨게 push 해준다.
[ ContactsViewController에서의 처리 ]
var isModify = false // 수정 여부 확인
var modifyContact: ContactsModel? // ViewController 에서 데이터 전달
먼저 앞에서 설명한 isModify 변수와 modifyContact 변수이다.
해당 변수는 각각 수정 여부 확인과 ViewController에서 데이터를 받아오기 위한 역할을 한다.
private func configureUI() {
view.backgroundColor = .white
if isModify == false {
self.title = "연락처 추가"
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "등록", style: .plain, target: self, action: #selector(naviButtonTapped))
deleteButton.isHidden = true // 삭제 버튼을 안보이게 처리
} else {
self.navigationItem.rightBarButtonItem = UIBarButtonItem(title: "수정", style: .plain, target: self, action: #selector(modifyButtonTapped))
// 옵셔널 값 처리
guard let modifyContact = modifyContact else { return }
self.title = modifyContact.name
nameTextField.text = modifyContact.name
phoneNumberTextField.text = modifyContact.phoneNumber
AF.request(modifyContact.imageUrl).responseData { response in
if let data = response.data, let image = UIImage(data: data) {
DispatchQueue.main.async {
self.circleImageView.image = image
}
}
}
deleteButton.isHidden = false // 삭제 버튼을 보이게 처리
}
}
그다음 configureUI 함수 안에서 isModify의 값으로 연락처 등록 화면과 연락처 수정 화면으로 분기처리한다.
먼저 isModify의 값이 false일 때 (연락처 등록 화면) 네비게이션 바의 title의 텍스트 값을 "연락처 추가"라고 설정하고
네비게이션 바의 오른쪽 버튼의 text를 "등록", 버튼 클릭 이벤트를 naviButtonTapped 함수와 연결하였다.
그리고 삭제 버튼을 보이지 않게 처리하였다.
isModify가 false가 아닐 때 (연락처 수정 화면) 네비게이션 바의 오른쪽 버튼의 text를 "수정", 버튼 클릭 이벤트를 modifyButtonTapped 함수와 연결하였다.
그 다음 ViewController에서 받아온 modifyContact 데이터가 현재 옵셔널 값이기 때문에
guard let을 통해 옵셔널 바인딩 하고, 네비게이션 바의 title의 텍스트 값을 선택한 셀의 연락처 이름으로 설정하고,
nameTextField의 text 값과 phoneNumberTextField의 text 값을 각각 선택한 셀의 연락처 이름과 전화번호로
값을 넣어주었다.
circleImageView는 메인쓰레드에서 선택된 셀의 imageUrl을 받아서 이미지를 넣어주었다.
[ 데이터의 수정과 삭제 ]
// CoreData 데이터 수정하기
func updateData(currentName: String, updateName: String, currentPhoneNumber: String, updatePhoneNumber: String, currentImgaeUrl: String, updateImageUrl: String) {
// 수정할 데이터를 찾기 위한 fetch request 생성
let fetchRequest = Contacts.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "name == %@", currentName) // 예시: 이름이 "Adam"인 데이터 수정
do {
// fetch request 실행
let result = try self.container.viewContext.fetch(fetchRequest)
// 결과 처리
for data in result as [NSManagedObject] {
// 데이터 수정
data.setValue(updateName, forKey: Contacts.Key.name)
data.setValue(updatePhoneNumber, forKey: Contacts.Key.phoneNumber)
data.setValue(updateImageUrl, forKey: Contacts.Key.imageUrl)
// 변경 사항 저장
try self.container.viewContext.save()
print("데이터 수정 완료")
}
} catch {
print("데이터 수정 실패")
}
}
// 저장된 데이터 선택 삭제
func deleteData(name: String) {
// 삭제할 데이터를 찾기 위한 fetch request 생성
let fetchRequest = Contacts.fetchRequest()
fetchRequest.predicate = NSPredicate(format: "name == %@", name)
do {
// fetch request 실행
let result = try self.container.viewContext.fetch(fetchRequest)
// 결과 처리
for data in result as [NSManagedObject] {
// 삭제
// CRUD 의 D.
self.container.viewContext.delete(data)
print("삭제된 데이터: \(data)")
}
// 변경 사항 저장
try self.container.viewContext.save()
print("데이터 삭제 완료")
} catch {
print("데이터 삭제 실패: \(error)")
}
}
@objc private func modifyButtonTapped() {
print("수정 버튼 클릭")
guard let modifyContact = modifyContact else { return }
updateData(currentName: modifyContact.name, updateName: nameTextField.text ?? modifyContact.name, currentPhoneNumber: modifyContact.phoneNumber, updatePhoneNumber: phoneNumberTextField.text ?? modifyContact.phoneNumber, currentImgaeUrl: modifyContact.imageUrl, updateImageUrl: self.imageUrl.isEmpty ? modifyContact.imageUrl : self.imageUrl)
self.navigationController?.popViewController(animated: true)
}
@objc private func deleteButtonTapped() {
print("삭제 버튼 클릭")
guard let modifyContact = modifyContact else { return }
deleteData(name: modifyContact.name)
self.navigationController?.popViewController(animated: true)
}
updateData는 총 6개의 파라미터를 가지고 있는데
이는 각각 현재 이름, 바꿀 이름, 현재 전화번호, 바꿀 전화번호, 현재 이미지, 바꿀 이미지이다.
바꿀 이름과 번호가 비어있으면 ViewController에서 넘겨받은 데이터의 이름과 번호로 설정하였고,
바꿀 이미지가 비어있으면 마찬가지로 ViewController에서 넘겨 받은 데이터의 이미지로 설정하였다.
수정 버튼을 누르면 updateData 함수가 실행되고, 실행이 종료되면 navigationController의 popViewController을 통해
이전 뷰인 ViewController로 돌아가게 된다.
deleteData는 name 값을 가지고 해당 name이 CoreData에 있으면 삭제하는 함수이다.
삭제 버튼을 누르면 deleteData가 실행되고, 현재 누른 셀의 데이터가 사라진다.
마찬가지로 실행이 종료되면 navigationController의 popViewController을 통해
이전 뷰인 ViewController로 돌아가게 된다.
➕ 개인적으로 추가한 부분 (Delete Button)
나는 8단계까지 구현을 마치고 연락처를 삭제하는 버튼을 추가로 구현했다.
삭제 버튼은 연락처를 수정하는 화면에서만 나타나게 구현하였으며,
버튼을 누르면 해당 연락처가 삭제되고, 메인 화면으로 돌아가게 된다.
'스파르타 코딩 클럽 - iOS 스타터 6기 > 본 캠프' 카테고리의 다른 글
40. 스파르타 코딩 클럽 - 킥보드 대여 앱 만들기 (2) (0) | 2025.04.28 |
---|---|
39. 스파르타 코딩 클럽 - 킥보드 대여 앱 만들기 (1) (1) | 2025.04.25 |
37. 스파르타 코딩 클럽 - 포켓몬 연락처 앱 만들기 (4) (0) | 2025.04.22 |
36. 스파르타 코딩 클럽 - 포켓몬 연락처 앱 만들기 (3) (0) | 2025.04.21 |
35. 스파르타 코딩 클럽 - 포켓몬 연락처 앱 만들기 (2) (1) | 2025.04.18 |