https://github.com/jacobkosmart/diary-ios-practice
To study UITabBarController, UICollectionView, NotificationCenter
https://github.com/jacobkosmart/diary-ios-practice
notificationcenter uicollectionview uikit uitabbarcontroller uuid
Last synced: 3 months ago
JSON representation
To study UITabBarController, UICollectionView, NotificationCenter
- Host: GitHub
- URL: https://github.com/jacobkosmart/diary-ios-practice
- Owner: jacobkosmart
- Created: 2021-12-15T07:23:06.000Z (over 3 years ago)
- Default Branch: main
- Last Pushed: 2021-12-16T23:32:40.000Z (over 3 years ago)
- Last Synced: 2024-12-28T03:27:52.320Z (5 months ago)
- Topics: notificationcenter, uicollectionview, uikit, uitabbarcontroller, uuid
- Language: Swift
- Homepage: https://jacobko.info/ios/ios-06/
- Size: 30.3 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# diary-ios-practice
## 기능 상세
- 일기장 탭을 누르면 일기 리스트를 표시할 수 있습니다
- 즐겨찾기 탭을 누르면 즐겨찾기한 일기 리스트를 표시할 수 있습니다
- 일기를 등록, 수정, 삭제, 즐겨찾기 할 수 있습니다
## Check Point !

### UITabBarController
- 일기장의 tab과 즐겨찾기 tab을 선택하면 각각 다른 화면이 보이게 구현
### UICollectionView
- 일기 list 를 표시하기
### NotificationCenter
- 수정, 삭제 등 event notification observing 하는것을 전달하여 기능 구현
> Describing check point in details in Jacob's DevLog - https://jacobko.info/ios/ios-06/
## Error Check Point
### Delete error issue

NotificationCenter 로 참조한 data 를 지울때 같은 diaryList 를 참조하기때문에 만약 home 화면의 diary list 에서 즐겨찾기가 되어 있고, 하나는 안되어 있는 상태에서 안되어 있는 것을 지울때 위와 같은 error message 가 표시 됩니다. 왜냐하면 즐겨찾기 에서도 같은 위치의 NotificationCenter 의 indexPath 를 찾기 때문에 즐겨찾기 페이지에는 1개 밖에 없기 때문에 해당이 되지 않게 됩니다 => `Error index out of range`
### Solving Problem
dairy date 를 추가할때 마다, 객체에 특정할 수 있는 고유의 key 값을 설정해서 저장하고, 수정,삭제 시 이 key 값을 참조하여 단순히 list 의 indexPath 로 삭제 하는것이 아니라 key 값을 참조해서 그 데이터를 삭제 해줘야 함 => (`uuid 값 추가`)
- struct 에 uuid String 값 추가
```swift
import Foundationstruct Diary {
var uuidString: String
var title: String
var contents: String
var date: Date
var isHeart: Bool
}
```- diary 가 add 될때 마다 uuid 값 추가하기, edit 모드일때 uuidString 값 참조하기
```swift
// in WriteDiaryViewController.swift// .edit 일 경우에만 NotificationCenter post event 발생
switch self.diaryEditorMode {
case .new:
let diary = Diary(
uuidString: UUID().uuidString,
title: title,
contents: contents,
date: date,
isHeart: false)
self.delegate?.didSelectReigster(diary: diary)case let .edit(indexPath, diary):
let diary = Diary(
uuidString: diary.uuidString,
title: title,
contents: contents,
date: date,
isHeart: diary.isHeart)
NotificationCenter.default.post(
name: NSNotification.Name("editDiary"),
object: diary,
userInfo: nil
)
// 더이상 userInfo 에 indexPath.row 값을 넘겨주지 않아도 됨 uuid 사용
// userInfo: ["indexPath.row" : indexPath.row])
}self.navigationController?.popViewController(animated: true)
}
```- 삭제가 일어날때, indexPath 대신 uuidString 이 전달되게 하기
```swift
// DiaryDetailViewController.swift@IBAction func tabDeleteBtn(_ sender: UIButton) {
// indexPath 대신 uuid 값을 불러오기
// guard let indexPath = self.indexPath else { return }
guard let uuidString = self.diary?.uuidString else { return }
// delegate 더이상 필요 없음 (NotificationCenter 로 대체)
// self.delegate?.didSelecteDelete(indexPath: indexPath)
NotificationCenter.default.post(
name: NSNotification.Name("deleteDiary"),
object: uuidString, // indexPath uuidString 이 전달되게 함
userInfo: nil)
self.navigationController?.popViewController(animated: true)
}// tabheartBtn action selector
@objc func tabHeartBtn() {
// 즐겨찾기 토글 기능 (on / off 기능)
guard let isHeart = self.diary?.isHeart else { return }
// 즐겨찾기 에서도 더이상 indexPath 대신 uuidString 사용
// guard let indexPath = self.indexPath else { return }if isHeart {
self.heartBtn?.image = UIImage(systemName: "heart")
} else {
self.heartBtn?.image = UIImage(systemName: "heart.fill")
}
self.diary?.isHeart = !isHeart
// delegate 으로 보낼경우 1:1 밖에 보낼 수 없기 때문에 NotificationCenter 을 이용해서 값을 보내야지 favorite 에서도 볼 수 있게 됨
// self.delegate?.didSelectHeart(indexPath: indexPath, isHeart: self.diary?.isHeart ?? false)
// Notification 에 isHeart 여부 보내기 logic
NotificationCenter.default.post(
name: NSNotification.Name("heartDiary"),
object: [
"diary" : self.diary,
"isHeart" : self.diary?.isHeart ?? false,
"uuidString": diary?.uuidString
],
userInfo: nil
)
}
```- UserDefaults 에 저장, 로드할때도 uuidString 추가
```swift
// in ViewController.swift// UserDefaults 에 diaryList 저장하기
private func saveDiaryList() {
let date = self.diaryList.map {
[
"uuidString": $0.uuidString,
"title": $0.title,
"contents": $0.contents,
"date": $0.date,
"isHeart": $0.isHeart,
]
}
let userDefaults = UserDefaults.standard
userDefaults.set(date, forKey: "diaryList")
}// UserDefaults 에 저장된 데이터 불러오기
private func loadDiaryList() {
let userDefaluts = UserDefaults.standard
// userDefaults 에서 저장된 데이터 불러올때는 any type 으로 return 되기 때문에 type casting 을 dictonary 형태로 형변환 해야함
guard let data = userDefaluts.object(forKey: "diaryList") as? [[String: Any]] else { return }
self.diaryList = data.compactMap{
guard let uuidString = $0["uuidString"] as? String else { return nil}
guard let title = $0["title"] as? String else { return nil}
guard let contents = $0["contents"] as? String else { return nil}
guard let date = $0["date"] as? Date else { return nil }
guard let isHeart = $0["isHeart"] as? Bool else { return nil }
return Diary(uuidString: uuidString,title: title, contents: contents, date: date, isHeart: isHeart)
}
```- 즐겨찾기 페이지에서도 uuidString 을 가져올 수 있게 추가
```swift
// in FavoriteViewController.swift// UserDefaults 에서 즐겨찾기 되어있는 diaryList 만 가져오기 logic
private func loadHeartDiaryList() {
let userDefaults = UserDefaults.standard
guard let data = userDefaults.object(forKey: "diaryList") as? [[String: Any]] else { return }
self.diaryList = data.compactMap {
guard let uuidString = $0["title"] as? String else { return nil }
guard let title = $0["title"] as? String else { return nil }
guard let contents = $0["contents"] as? String else { return nil }
guard let date = $0["date"] as? Date else { return nil }
guard let isHeart = $0["isHeart"] as? Bool else { return nil }
return Diary(uuidString: uuidString, title: title, contents: contents, date: date, isHeart: isHeart)
// fliter 함수를 사용해서 즐겨찾기 되어 있는 부분만 가져오고, 날짜가 최신순으로 오게끔 정렬하기
}.filter({
$0.isHeart == true
}).sorted(by: {
$0.date.compare($1.date) == .orderedDescending
})
}
```## reference
Jacob's DevLog - [https://jacobko.info/ios/ios-06/](https://jacobko.info/ios/ios-06/)
김종권의 iOS 앱 개발 알아가기 - [https://ios-development.tistory.com/103](https://ios-development.tistory.com/103)
fastcampus - [https://fastcampus.co.kr/dev_online_iosappfinal](https://fastcampus.co.kr/dev_online_iosappfinal)