3월 26일 TIL (TodoList)

이승원·2024년 3월 26일
1

TIL

목록 보기
51/75
post-thumbnail

Todolist (.cont)

  • 오늘은 Todolist을 어느정도 끝을 낸거 같다... (사실 끝이 없음)
  • Tag Class로 변경
  • Tag 수정 페이지 구현
  • 상세페이지/수정페이지 로직 수정
  • 키보드 화면 가림 문제 해결

Tag Class 로 변경

  • Tag는 원래 구조체로 선언을 했었는데, CoreData에서는 구조체를 지원하지 않는 다는것을 보고 Class로 변환했다. 크게 달라진 부분은 없고, Mutating 만 지워주고, 값 전달이 아닌 참조전달이라서, 혹시나 문제가 생길부분들을 수정했다.

Tag 수정 페이지 구현

  • Tag 색깔을 구현해야 하고, 뭔가 기능적으로 많이 필요할꺼 같아서, 정말 많이 고민을 했다. 어떤 방식으로 해야 사용자 입장에서 편할지. 근데 아쉽게도 내가 이전까지는 이런 앱을 사용해본적이 없어서 정말 많은 앱을 다운받아서 테스트를 해보고, 참고 했다.
  • 일단 Tag 색깔을 변하는거 많긴하지만, 대부분 색깔이 지정되어 있는 경우가 많았다. 그렇게 하는데는 다 이유가 있다. 관리하기 쉬우니깐?!, 그치만 이왕하는거 사용자가 원하는 색깔로 할 수 있게끔 설정하고 싶었다.
  • 그리고 원래는 전체태그를 태그 수정페이지에서 같이 보여주면서, 사용자가 쉽게 클릭만으로 현재 투두에서 사용하는 방식으로 진행하려고 했으나, 어떻게 하든 난 leftAlignment CollectionVIew가 작동이 안됐다. 정확히 말하자면 왼쪽 정렬은 잘됐지만, 한 row에 최대 길이가 있는데, 각각 cell을 넣고, 만약에 남는 공간에 다음 cell이 안들어가면 자연스럽게 다음 row에다가 넣어야하는데, 인터넷을 보고 똑같이 코드를 짜도, 내 Collectionview는 이상하게 옆으로 삐져나왔다(?)
  • 참고했던 LeftAlignedCollectionViewFlowLayout는 아래와 같다.
class LeftAlignedCollectionViewFlowLayout: UICollectionViewFlowLayout {
    
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let attributes = super.layoutAttributesForElements(in: rect)

        var leftMargin = sectionInset.left
        var maxY: CGFloat = -1.0
        attributes?.forEach { layoutAttribute in
            if layoutAttribute.frame.origin.y >= maxY {
                leftMargin = sectionInset.left
            }

            layoutAttribute.frame.origin.x = leftMargin

            leftMargin += layoutAttribute.frame.width + minimumInteritemSpacing
            maxY = max(layoutAttribute.frame.maxY, maxY)
        }
        // 아래 줄을 추가안하시면 네모네모(?)하고 이상한 Cell을 목격할수있습니다.
        self.estimatedItemSize = UICollectionViewFlowLayout.automaticSize // 해당 줄만 추가했습니다.
        return attributes
    }
}

...
overide func viewDidLoad(){
	super.viewDidLoad()
    tagCollecitonView.delegate = self
    let layout = LeftAlignedCollectionViewFlowLayout()
    layout.minimumLineSpacing = 5
    layout.minimumInteritemSpacing = 1
    layout.sectionInset.top = 10
    layout.sectionInset.left = 5
    layout.sectionInset.right = 6
    tagCollectionView.collectionViewLayout = layout
}
  • 이렇게 만들면 대충 이쁘게 나온다. 그치만 태그가 특정 순서로 되어 있다던가, 길이가 길어진다던가하면 결국 문제가 생긴다..
  • 그래서 결국 전체 태그를 보여주는거는 없애고, 현재 사용중인 태그만 보여주는 방향으로 가기로 했다.
  • 큰 Label 하나를 만들어서 사용자가 현재 편집중인 태그를 보여주고, TextField의 변화의 따라서, label도 자동으로 바뀌는 방식으로 채택했다. 이방법은 TextField addTarget을 통해서 했다.
self.tagTextField.addTarget(self, action: #selector(textFieldChanged), for: .editingChanged)

@objc func textFieldChanged(){
        if self.tagTextField.text?.first != "#"{
            self.currentTagLabel.text = "#" + (self.tagTextField.text ?? "")
        }else{
            self.currentTagLabel.text = self.tagTextField.text
        }
        
        if let _ = (self.currentTags.firstIndex{$0.tagName == self.currentTagLabel.text }){
            self.addButton.titleLabel?.text = "변경"
        }else{
            self.addButton.titleLabel?.text = "추가"
        }
    }
  • 아쉬운점은 .editingChanged 는 Touch Event로 인해 TextField가 변했을때만 textFieldChanged 함수를 호출한다. 즉 touch event가 아닌, 직접 값을 부여했을때는 해당 함수가 호출되지 않는다. 그래서 .ValueChanged 도 해봤지만, 얘는 또 이상하게 작동이 안됐다..

상세페이지/수정페이지 로직 수정

  • 이부분이 오늘한것중에서 제일 맘에 든다.
  • 원래는 당장 보여주기 위해서 구조체, 인스턴스 이런거 신경하나도 안쓰고, 그냥 글이면 [String], 이런식으로 만들다보니깐, 추가적인 변경을 하기가 엄청 까다로웠다.
  • 그치만 이제 Tag 색깔을 넣을려면 [String]이 아닌 [Tag]로 사용해야지만 가능했기에, 모든 코드를 다 돌아보면서, 정리할꺼 정리하고, 이제 제대로된 구조체와 인스턴스를 사용하게끔 변경했다.
  • 물론 아직도 조금 정리가 안된 부분이 있지만, 처음 구현했을때보다는 100배 나아졌다.

키보드 화면 가림 문제 해결

  • 시뮬레이터로만 작동하다보니 키보드를 전혀 고려하고 있지 않았다. 문득 생각이 들어서 해결해버리자 싶어서 바로 인터넷에서 방법을 찾아봤다.
  • ScrollView을 이용하는 방법도 있고, 단순히 View를 올리는 방법도 있고, Delegate를 이용하는 방법도 있었는데, 사실 다 써보고 Delegate가 제일 좋은거 같아서 Delegate를 사용했다.
  • 일단 ScrollView 같은 경우에는 이미 만들어 놓은 Storyboard를 변경해야해서, 정말 하기 싫었지만, Contraints 다시 하고 했는데, 안됐다. ScrollView는 추가적으로 공부를 해야될꺼 같다.
  • 단순히 View을 올리는 방법은 폰마다 다르기 떄문에, 시도해보니 역시나 안됐다.
  • 마지막 Delegate 방법이 제일 깔끔한것 같았다. (내 현재시점 기준)
func registerForKeyboardNotifications() {
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    @objc func keyboardWillShow(notification: NSNotification) {
        if memoTextView.isFirstResponder {
            if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
                let keyboardHeight = keyboardSize.height
                // Adjust your view accordingly, for example:
                let transform = CGAffineTransform(translationX: 0, y: -keyboardHeight)
                UIView.animate(withDuration: 0.3) {
                    self.view.transform = transform
                }
            }
        }
    }
    
    @objc func keyboardWillHide(notification: NSNotification) {
        UIView.animate(withDuration: 0.3) {
            self.view.transform = .identity
        }
    }
override func viewDidLoad() {
	super.viewDidLoad()
    registerForKeyboardNotifications()
}
  • 추가적으로 TextField에서 Enter키 눌르면 키보드 내리는 기능
extension DetailsViewController: UITextFieldDelegate {
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }
    
    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder() // TextField 비활성화
        return true
    }
}
override func viewDidLoad() {
	super.viewDidLoad()
	titleTextField.delegate = self
}
  • 다른데 터치할시 키보드 숨기는 기능
extension UIViewController {
    
    func hideKeyboardWhenTappedAround() {
        let tap = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    }
    
    @objc func dismissKeyboard() {
        view.endEditing(true)
    }

}
override func viewDidLoad() {
	super.viewDidLoad()
    self.hideKeyboardWhenTappedAround()
}

이후 계획!

  • Tag 별 화면 ( 해당 Tag를 갖고 있는 투두 보여주기 )
  • 가능하면 날짜 별 정렬 (CalandarView 사용)
  • 가능하면 정렬 기능
profile
개발자 (진)

2개의 댓글

comment-user-thumbnail
2024년 3월 26일

도움이 많이 되요 :)

답글 달기
comment-user-thumbnail
2024년 3월 27일

키보드가림문제가 Delegate를 사용해서 되는군요.. 오 새로운걸 배웠어요 Delegate이 역시 말씀하신대로 공부를 많이 해야하는 부분인가봐요

답글 달기