TextField 제한 - Team-HGD/SniffMEET GitHub Wiki

텍스트 필드 여러개인 경우

textField가 여러개인 경우, delegate 메서드에서 특정 텍스트필드에만 내용을 적용시키기 위해서는 guard문을 이용해 textField를 특정시켜줘야 할 필요가 있었다.

내가 구현할때는 age, name 두개의 텍스트 필드가 존재했고, 나이부분에만 메서드 연결이 필요했다.

이때, 1번 방식처럼 작성을 했더니 제대로 동작하지 않았다. 2번 처럼 작성하니 잘 동작하는 모습을 볼 수 있었는데 1번과 같은 경우에는 text를 ageTextField의 text로 할당했을뿐 textFiled가 어떤 종류의 텍스트필드인지를 제대로 지정해주지 않았기 때문이었다.

사소한 차이지만 큰 차이였다.

// 1번
guard let text = ageTextField.text else { return true }

// 2번
guard textField == ageTextField, let text = textField.text else { return true }

숫자만 제한

기존에는 나이 입력 textField를 터치했을때, 숫자 키보드가 올라오도록 구현해 숫자를 입력해주도록 유도했다.

하지만 환경상 숫자 키보드가 올라오지 않고 일반 키보드가 올라오는 경우(시뮬레이터 등)를 고려해 아예 입력 시점에 숫자만 입력될 수 있도록 제한을 걸어주었다.

let allowedCharacters = CharacterSet.decimalDigits
let inputCharacters = CharacterSet(charactersIn: string)
let filteredInputCharacters = allowedCharacters.isSuperset(of: inputCharacters)

위 방식을 이용해 글자에 숫자만 입력되도록 제한할 수 있었다.

글자수 제한

한글 문제

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool

위의 delegate 함수를 이용해 textField에 글자수 제한을 주었을때 문제가 발생했다.

예를들어 글자수를 4글자로 제한했을때 마지막 글자에 “과”와 같은 문자를 입력하면 “고”까지만 입력이 되었다.

이는 한글의 경우에 발생하는 문제였는데, 영어와 달리 한글은 유니코드 값으로 계산할 경우 count값이 [자음 + 모음] 형태를 기준으로 카운트되기 때문에 [자음 + 모음 + 자음] 혹은 [자음 + 모음 + 모음] 등의 경우에서 count 값이 예상과 달라져 발생하는 것이었다.

  1. NotificationCenter 이용 NotificationCenter 통해서 텍스트 변경을 감지하고 텍스트 변경 시점마다 텍스트 길이를 확인하고 초과를 판단한다. 이 방식을 이용하면 위에서 말한 textField 함수 사용 없이 구현 가능했는데, 단점은 초과 입력 된 부분이 마지막 글자로 대치된다는 점이었다.
  2. 직접 조건 설정 직접 조건을 설정해주는 방식이 있길래 시도해보았는데, 자음 + 모음 + 모음의 경우는 조건이 걸려있지 않아 if separatedCharactersCount == 2 && !string.isConsonant { return true } 조건을 추가해 시도해봤다. 그 결과, 글자수 제한에 도달했을때 마지막 글자로 “과”, “당”, “닮” 등이 잘 입력되었다. 하지만 지우는 과정에서 지워진 글자가 앞의 글자에서 다시 표시되는 문제가 발생했다.
guard let text = textField.text else { return true }
let maxLength = 8
let newText = text + string

if newText.count <= maxLength {
	return true
}

let lastWordOfOldText = String(text[text.index(before: text.endIndex)])
let separatedCharacters = lastWordOfOldText.decomposedStringWithCanonicalMapping.unicodeScalars.map{ String($0) }
let separatedCharactersCount = separatedCharacters.count
if separatedCharactersCount == 1 && !string.isConsonant {
	return true
}

if separatedCharactersCount == 2 && string.isConsonant {
	return true
}

if separatedCharactersCount == 2 && !string.isConsonant {
	return true
}

if separatedCharactersCount == 3 && string.isConsonant {
	return true
}

return false

글자수를 정확히 8글자로 제한하는 대신, 널널하게 제한 조건을 지정하고 (텍스트 더미 입력 방지를 위해) 글자수가 1 ~ 8글자인 경우에만 다음으로 넘어가는 버튼을 활성화시키도록 구현했다. 추가로, 8글자까지만 입력 가능하다는 경고 라벨도 넣어주었다.

사용자 경험을 헤치지 않기 위해 고려한 방식이었다.

Ref.

https://zartt.tistory.com/36