Todolist (.cont)
추가하기 View 완성
- 어제 사실 추가힉 View를 만들어 놓긴 했지만, 실질적으로 기능이 구현이 되어 있는건 아니었다.
- 일단 어제 제일 큰 문제는 같은
Storyboard
에다가 두개의 다른 viewController
를 생성해서 문제가 발생했다.
- 이유는 잘 모르겠으나, 두개의
ViewController
사이가, segue
로 하든, delegate
로 하든 데이터가 전송도 안되고 받는것도 안됐다.
- 결국 새로 Storyboard를 만들어서 했다.
- 이렇게 하니깐 바로 된다... 너무 허무했지만, 뭐라도 배웠다는 것에 감사한다.
- 그리고 어제는
Textview
에 placeholder
가 없었는데, 오늘은 새로 추가 했다.
textView delegate
를 활용해서 Textview
가 수정중인지 아닌지을 확인해서 알 맞는 Action을 추가 했다. (아래 코드)
extension DetailsViewController : UITextViewDelegate {
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.text == textViewPlaceHolder{
textView.text = nil
textView.textColor = .black
textView.textContainerInset = UIEdgeInsets(top: 20, left: 20, bottom: 0, right: 20)
}
}
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
textView.text = textViewPlaceHolder
textView.textColor = .lightGray
textView.textContainerInset = UIEdgeInsets(top: (textView.bounds.height - textView.contentSize.height) / 2 - 10, left: 0, bottom: 0, right: 0)
}
}
}
memoTextView.delegate = self
- 그리고 중간에 요소들을 감싸고 있는 테두리가 있는데, 저건 야매(?)로 만들었다. 원래는 따로
View
를 사용해서 해당 요소들을 안에 넣어서 관리를 해야할텐데. 이미 만들어 놓아서 다시 바꾸고 너무 시간이 올릴꺼 같아서 SubView
를 활용했다.
- 사실
Subview
를 사용을 해도 되는건지 잘 모르겠다. Subview
란 현재 View
에 말그대로 Subview
를 추가해서, 그 위에 올리는거다.
- 그래서 나는
view
하나를 생성해서, contraints
를 원하는 사이즈에 맞게끔 설정한 다음에, backgroundColor
를 .clear
로 설정을 했는데, 처음에는 버튼들이 안 눌렸다. 상식적으로 생각해봐도 그위에 쌓는거니깐 안된다는걸 알았다. 그래서 찾아보니 SubView
를 뒤에 위치할 수 있었다.
- 그리고 Subview를 사용할때 주의 해야할 문제는,
subview
를 추가 한다음에 contraints
를 설정해줘야 한다.
let backgroundView = UIView(frame: self.view.bounds)
backgroundView.backgroundColor = .clear
backgroundView.layer.cornerRadius = 20
backgroundView.layer.borderWidth = 5
backgroundView.layer.borderColor = UIColor.black.cgColor
self.view.addSubview(backgroundView)
backgroundView.translatesAutoresizingMaskIntoConstraints = false
backgroundView.topAnchor.constraint(equalTo: titleTextField.bottomAnchor, constant: 5).isActive = true
backgroundView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 10).isActive = true
backgroundView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10).isActive = true
backgroundView.bottomAnchor.constraint(equalTo: memoTextView.topAnchor,constant: -5).isActive = true
self.view.sendSubviewToBack(backgroundView)
Tag Collection View 추가
- 아이폰 미리알림 앱을 보니깐 태그들을 정리 해놓을수가 있었다. 그래서 나도 그걸 따라서 만들어보자는 생각을 Tag 기능을 추가로 구현하게 되었다.
- 처음에는 따로
View
를 만들어서 Collection View
를 띄워서, 사용자가 선택하는 방식으로 진행하려고 했는데, 솔직히 자신이 없었고, hierichy
가 너무 깊어지는거 같아서, 사용자 측면에서 안좋을 꺼 같아서 다른 방식으로 표현을 하기로 했다.
- 태그
Label
오른쪽에 CollectionView를 만들어서 태그를 보여주는 방식으로 하고, 추가할때는 Alert Controller
를 사용하자는 방식으로 진행했다.
- 기존
Todo
구조체에다가 Tag
배열을 만들고, 해당 배열에 tag 들을 문자열로 저장해서, 해당 배열을 돌면서 CollectionView를 구현했다.
- CollectionView를 할때 제일 문제는 역시나 Cell 사이즈 조정인거 같다.
- 처음에는 엄청 삽질을 했는데, 인터넷에서 찾아보니 글자크기에 따라서 cell 사이즈를 조정해주는 걸 구현한 분이 있어서 해당 코드를 따와서 내 코드에 맞게끔 구현했다.
- 방법은
NSAttributedString
를 사용해서 해당 길이를 폰트에 맞게 구한 다음에, 해당 길이를 이용해서 cell 사이즈를 유동적으로 바꾸는 것이다.
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
var tag : String
if currentTodo != nil {
tag = (self.currentTodo?.tag[indexPath.row])!
}else{
tag = self.newTodo.tag[indexPath.row]
}
let attributes = [NSAttributedString.Key.font: UIFont(name: font, size: 14)]
let tagSize = (tag as NSString).size(withAttributes: attributes as [NSAttributedString.Key: Any])
return CGSize(width: tagSize.width + 20, height: 30)
}
- 그리고 태그를 클릭시에 삭제하는 것도 구현을 했다.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if isEnabled {
if currentTodo != nil {
currentTodo?.tag.remove(at: indexPath.row)
}else{
newTodo.tag.remove(at: indexPath.row)
}
self.tagCollectionView.reloadData()
}
}
- 코드를보면 계속 isEnabled, currentTodo 이걸 확인하는데, 이건 바로 아래 부분에서 설명하겠다.
상세페이지 보기
- 각각의
Todo
의 정보가 있는데, 메인 페이지에선 실질적으로 확인할 수 가 없다. 따라서 상세페이지 보기를 만들려고 했는데, 또 새로 View
를 만들기엔 아까워서, 추가하기 View
를 활용해서 상세페이지 보기 View
를 만들었다.
CurrentTodo : Todo?
를 이용해서, 만약에 Todo
를 클릭해서 해당 View
를 로드를 하면, CurrentTodo
에다가 해당 Todo
를 저장한다, 만약에 그냥 추가하기 버튼으로 해당 view를 로드를 했다면, nil
상태가 된다.
- 즉 쉽게 말하면
CurrentTodo
를 활용해서 현재 사용자가 보고 있는 View
가 추가를 위함인지, 아니면 기존에 있는 Todo
를 보기 위함인지 판단하기 위해서다.
- 그리고 상세페이지에서는 모든 수정이 불가능하게끔,
isEnable : Bool
를 이용해서, 모든 요소들의 상태를 제어한다. 만약 상세페이지에서 변경하기 버튼을 누르면, isEnable.toggle()
을 호출하고, viewDidLoad()
를 다시 호출한다.
- 즉 하나의
View
로, 상세페이지, Todo
변경, 새로운 Todo
추가까지 사용한것이다.
- 위에
Navigation Title
도 변경해서 헷갈리지 않도록 구현했다.
- 또한 사용자가 수정하는 페이지라는것을 알수 있도록
TextView
의 Allignment
도 수정할때는 변경된다.
추가하기 버튼 변경
- 기존에는 우측상단에 추가하기 버튼이 있었는데, 너무 안이뻐서 다양한 어플들을 찾아봤다. 미리 알림 같은 경우에는
Tab Bar
즉 화면 하단에 있는 거를 활용해서 추가하기 버튼을 만들고, 또 다른데에서는 그냥 우상단에 Navigation Bar Item
을 활용해서도 했지만, 이쁘다는 생각이 안들어서 SubView를 해봤으니깐 또 해보자는 생각으로 TableView
위에다가 버튼을 만들기로 했다.
- 이것도 마찬가지로
Button
을 먼저 생성하고, customize 한다음에, subView에 추가를 하고, Contraint를 설정해줬다.
let button = UIButton(type: .system)
button.setImage(UIImage(systemName: "plus"), for: .normal)
button.contentVerticalAlignment = .fill
button.contentHorizontalAlignment = .fill
button.backgroundColor = .black
button.tintColor = .white
button.layer.cornerRadius = 40
button.layer.borderColor = UIColor.black.cgColor
button.layer.borderWidth = 5
button.layer.masksToBounds = true
view.addSubview(button)
button.translatesAutoresizingMaskIntoConstraints = false
button.trailingAnchor.constraint(equalTo: MyTableView.trailingAnchor, constant: -30).isActive = true
button.bottomAnchor.constraint(equalTo: MyTableView.bottomAnchor, constant: -50).isActive = true
button.widthAnchor.constraint(equalToConstant: 80).isActive = true
button.heightAnchor.constraint(equalToConstant: 80).isActive = true
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
TimePicker locale 설정
- TimePicker 에서 Date를 print해보면 실제 시간이 다르게 나온다. 그건 우리나라 시간이 아니라, 그 이유는 시간 기준이 UTC로 기본설정이 되어 있기 때문이다.
- 그래서 수정을 했는데, 뭔가 또 꼬인것 같다.. 이건 내일로 미루자..!
이후 계획!
- 각 태그, 혹은 시간 별로 section을 나눠서 보여주기? (카테고리)
- cell이 펼쳐질수 있으면 조금 더 좋아보일꺼 같다..
- 피드백을 받아보고! 수정할껀 수정하자.
오.. 뷰컨트롤러를 추가하고 계시군요! 오늘도 많이 배우고 갑니다 ㅎ