Xcode에서 remove reference한 파일 직접 삭제하는 방법

|

개인 공부 내용을 정리한 글입니다.
잘못된 내용이 있다면 편하게 댓글 남겨주세요!


문제 상황

실수로 xcode내 파일 중 하나를 삭제할 때 move to trash 를 하지 못하고 remove reference 를 클릭했다.
동일한 이름의 파일을 올리려고 하니 이미 해당 파일이 폴더 내에 있어서 삭제가 안된다고 한다.

“GoogleService-Info (1).plist” couldn’t be moved to “SupportingFiles” because an item with the same name already exists.

Xcode내에는 이미 내가 파일을 삭제했으니 파일은 보이지않고, 근데 이미 파일은 존재한다고 하는데 어떻게 해야할까?

해결 방법

나 같은 경우는 해당 파일이 Supporting files라는 폴더안에 있었다. 따라서..

  1. Supporting files 마우스커서 오른쪽 클릭
  2. Show in finder 클릭
  3. Supporting files 폴더를 들어가면 삭제되지 않은 파일들이 있음을 발견할 수 있다.

원하는 파일을 직접 삭제하면 더이상 해당 에러는 발생하지 않는다!

UILable의 자동 줄바꿈하는 방법?

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


UILable 자동 줄바꿈?

기본적으로 UILable을 사용하면 아래 사진처럼 자동 줄바꿈이 안된다.

틀이 정해져있는 텍스트라면 스토리보드에서 line의 수를 정해주면 되지만, 우리가 만약 채팅방을 만든다고 생각해보자.
채팅을 주고받을때 주고받는 텍스트의 길이는 유동적일 것이다.

이 유동적인 텍스트(데이터)에 대한 줄바꿈이 자동으로 되도록 하기 위해서는 아래처럼 진행하면 된다.

@IBOutlet weak var chatLbl: UILabel!

self.chatLbl.numberOfLines = 0

그러면 아래처럼 적용이 된다.

tableview 혹은 scrollview에서 화면 터치이벤트 받는 방법?

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


touchesbegan이 안된다!?

보통 키보드가 올라온 상태에서 화면을 누르면 키보드가 내려가게 하고 싶다면 touchesbegan으로 처리를 했을 것이다.

override func touchesbegan(_ touches: Set(UITouch), with event: UIEvent?) {
  // todo...
}

지금 내가 하고 있는 프로젝트는 테이블뷰로 이루어지고 있는데, 이 테이블뷰의 셀에 터치를 시도하게 되면 키보드가 내려가질 않는 현상이 발생한다.
이 touchesbegan이 먹히지 않는 이유는 찾아보니 생각보다 간단했다.

테이블뷰나 스크롤뷰 같은 경우는 일반적으로 스크롤을 하기위해 기본적인 1터치 가 발생한다.
그렇기 때문에 한번의 터치같은 경우는 그냥 무시가 되는 것 같다. 따라서 touchesbegan & touchedMoved 모두 호출이 되지 않는 것이다.

따라서 이러한 경우 직접 GestureRecognizer 를 추가하여 핸들러를 캐치하도록 만들어주어야 한다.

override func viewDidLoad() {
    super.viewDidLoad()

    // 핸들러 등록
    view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:))))
}

// 터치가 발생할때 핸들러 캐치
@objc func handleTap(sender: UITapGestureRecognizer) {
    if sender.state == .ended {
        view.endEditing(true) // todo...
    }
    sender.cancelsTouchesInView = false
}

이렇게 핸들러를 등록해주면 tableview 혹은 scrollview에서 터치이벤트를 작동할 수 있게된다.

채팅 textView(입력창, 전송버튼이 합쳐진 뷰)를 키보드와 붙여서 올리고 내리는 방법

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


내가 원하는 화면

내가 원하는 화면은 위와 같다.

현재 만들고 있는 창은 채팅방이고, 채팅을 입력하는 textView와 전송 버튼이 담겨진 uiView가 textView를 터치했을때 키보드와 함께 붙어서 올라가고 바깥을 터치할때 내려가도록 만들고 싶었다.

내가 한 코드

@IBOutlet weak var sendViewBottomMargin: NSLayoutConstraint!


func initNotification() {
    // 키보드 올라올 때
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(noti:)), name: UIResponder.keyboardWillShowNotification, object: nil)
    // 키보드 내려갈 때
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(noti:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}

// 키보드 올라오기
@objc func keyboardWillShow(noti: Notification) {
    let notiInfo = noti.userInfo!
    // 키보드 높이를 가져옴
    let keyboardFrame = notiInfo[UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
    let height = keyboardFrame.size.height - self.view.safeAreaInsets.bottom
    sendViewBottomMargin.constant = height

    // 애니메이션 효과를 키보드 애니메이션 시간과 동일하게
    let animationDuration = notiInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! TimeInterval
    UIView.animate(withDuration: animationDuration) {
        self.view.layoutIfNeeded()
    }
}

// 키보드 내려가기   
@objc func keyboardWillHide(noti: Notification) {
    let notiInfo = noti.userInfo!
    let animationDuration = notiInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! TimeInterval
    self.sendViewBottomMargin.constant = 0

    // 애니메이션 효과를 키보드 애니메이션 시간과 동일하게
    UIView.animate(withDuration: animationDuration) {
        self.view.layoutIfNeeded()
    }
}

위의 sendViewBottomMargin이 걸려있는 부분은 아래 사진과 같다.

string으로 넘어오는 date값 원하는대로 dateFormat 해보기 > iso8601DateFormatter사용하기

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


문제상황

  • 서버에서 보내주는 date값의 형식이 우선 스트링값으로 넘어오고 있다. > “2020-11-09T11:05:56.000Z”
  • 내가 원하는 것은 2020-11-09 딱 요부분! 그리고 dateFormat은 yyyy. MM. dd 이다.

Date extension을 통해 해결해보려 했으나 능력부족인지 뭔지 해결이 되질 않았다..
좋은 방법이 있다면 알려주세요!

1. 일단 되게 하는 방법

let date: String = "2020-11-09T11:05:56.000Z"
let arr = date.components(separatedBy: "T") // T를 기준으로 나눠줌
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy. MM. dd"
let newDate = dateFormatter.date(from: arr[0])  // 첫번째 배열값을 가져와 원하는 포맷으로 변경

self.dateLbl.text = dateFormatter.string(from: newDate!)

이 방법은 누가봐도 그냥 정말 딱 되게만 가능하게하는 방법이다.

2. 정석: iso8601DateFormatter 사용

let dateString: String = data.createDate
let iso8601DateFormatter = ISO8601DateFormatter()
iso8601DateFormatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] // option형태의 포맷
let date = iso8601DateFormatter.date(from: dateString)

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy. MM. dd"
self.dateLbl.text = dateFormatter.string(for: date!)

ios에서 시간 데이터를 관리하기 위해서는 Date라는 타입을 이용해 string을 date로 혹은 반대로 변환하기 위해 DateFormatter를 사용하는 것이 관습처럼 이루어졌는데, ios10부터는 iso8601DateFormatter 클래스 가 추가되어 iso8601 표준 포맷을 더 쉽게 다룰 수 있게 되었다고 한다.

특이한 점은 format형태가 문자열이 아닌 option 형태라는 것이다.

DateFormatter가 편한 부분도 있어서 계속해서 이를 사용해도 좋지만, 문자열로 format을 명시할 때 발생하는 실수를 줄일때는 위의 방법을 사용하는 것도 좋을 것 같다.