이러한 보안 키보드를 만들고, 세자리 마다 콤마(,)를 찍게 할 것이다. 이 방법은 내가 앞서 만들었던 계산기 만들때에도 굉장히 유용하게 쓰일 것 같다.
일단 왼쪽에 보면 CustomKeyboard.swift
와 CustomKeyboard.swift
파일이 있다. 이 두 파일을 만들어줘야하는데, CustomKeyboard.swift
파일은 캡처화면 처럼 Cocoa Touch Class파일을 생성하면 된다.
이 때, 상속받는 클래스가 UIViewController
가 아니라 UIView
이어야 한다.
그리고CustomKeyboard.xib
파일은 아래 User Interface 항복에서 View 파일을 생성해주면 된다.
여기서 View와 Storyboard의 차이점은 간단하게 Storyboard 파일은 Controller만 연결할 수 있고 View는 UI종류는 다 연결이 가능하다. 파일을 생성후 CustomKeyboard.swift
클래스를 파일 인스펙터에서 연결해 주어야 한다.
여기서 보면, 오른쪽 아래에 View 항목에 User Interaction Enabled
체크 항목이 있는데 이것을 체크해제해주면 버튼을 눌러도 아무런 반응이 일어나지 않는다. 이 사진 처럼 보안키보드 공백을 버튼으로 만든다면 저걸 해제해주면 되고, 아예 View를 삽입해버리면 이 과정은 생략해도 된다. 개인적으로는 버튼 액션보단 그냥 View가 더 깔끔하지 않을까 생각한다.
레이아웃은 간단하게 버튼 11개를 만들고 가로를 하나의 스택뷰로 묶은다음에 총 4개의 스택뷰를 다시 하나의 큰 스택뷰로 묶고 Constraints를 설정해주고 Distribution을 Fill equally로 설정하면 이렇게 나온다.
1~9까지 버튼들 함수 하나하나 생성하지말고 함수하나에 모든 버튼을 다 연결하면 된다. 이걸 몰라서 나는 계산기 만들 때 뻘짓을 했다.
(캡쳐가 너무 귀찮아서 사진 설명이 불친절한건 양해 부탁드립니다. 그냥 복습겸 쓰는거라..)
먼저 CustomKeyboard.swift
파일의 코드를 살펴보겠다.
>>> CustomKeyboard.swift
import UIKit
// delegate - 기능이나 값을 위임해줌.
protocol CustomKeyBoardDelegate {
func KeyboardTapped(str: String)
}
class CustomKeyboard: UIView {
var delegate: CustomKeyBoardDelegate? // 계속 남아있어 메모리 누수가 일어날 수 있으므로 optional로 선언.
@IBAction func buttonTapped(_ sender: UIButton) {
delegate?.KeyboardTapped(str: sender.titleLabel!.text!)
}
}
여기서 가장 중요한건 protocol
, delegate
인데, 버튼이 눌릴 때 그 버튼의 텍스트 값을 ViewController.swift
에 전달해줘야하므로 설정한다고 보면 된다.
그리고 ViewController.swift
파일
>>> ViewController.swift
import UIKit
// 클래스에 protocol을 사용해준다고 선언을 해야함.
class ViewController: UIViewController, CustomKeyBoardDelegate {
@IBOutlet weak var firstTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
// 커스텀 키보드 설정 방법.
//firstTextField.inputView = "커스텀키보드뷰"
let loadNib = Bundle.main.loadNibNamed("CustomKeyboard", owner: nil, options: nil) // xib 파일 정보를 불러온 것.
let myKeyboardView = loadNib?.first as! CustomKeyboard
myKeyboardView.delegate = self //이 선언문이 중요함.
firstTextField.inputView = myKeyboardView
}
func KeyboardTapped(str: String) {
// 키보드 눌렀을 때 호출 됨.
let oldNumber = Int(firstTextField.text!)
var newNumber = Int(str)
if str == "00" && oldNumber != nil{
newNumber = oldNumber! * 100
}
else if str == "000" && oldNumber != nil{
newNumber = oldNumber! * 1000
}
else if oldNumber != nil{
newNumber = newNumber! + oldNumber! * 10
}
if let hasNumber = newNumber {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal // 숫자를 세자리마다 쉼표로 찍어줌.
if let formatted = numberFormatter.string(from: NSNumber(value: hasNumber)){ // if let은 optional을 벗겨준다.
firstTextField.text = String(describing: formatted)
}
}
}
}
먼저, class에 protocol을 사용하기 위해 CustomKeyBoardDelegate
를 선언한다.
그리고 여기서
let myKeyboardView = loadNib?.first as! CustomKeyboard
myKeyboardView.delegate = self //이 선언문이 중요함.
firstTextField.inputView = myKeyboardView
loadnib는 .xib파일을 불러온다고 생각하면 되고, 클래스에서 CustomKeyboardDelegate
를 선언해주었으니 .delegate = self 다.
그리고 inputView가 키보드 모양이므로 그걸 내 커스텀 키보드로 바꿔주는 것. 이 구문이 상당히 어려우니까 복습을 좀 하고 찾아봐야겠다.
그리고 쉼표를 찍어주는 numberFromatter
사용법은
if let hasNumber = newNumber {
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal // 숫자를 세자리마다 쉼표로 찍어줌.
if let formatted = numberFormatter.string(from: NSNumber(value: hasNumber)){ // if let은 optional을 벗겨준다.
firstTextField.text = String(describing: formatted)
}
}
구글링을 해도 이거와 큰 차이가 없다. if let은 optional 변수를 자동으로 unwrap 해주는 것은 처음 알았다. 나머지는 변수 장난들. 그리고 쉼표를 찍어주는 것은 String
형식으로 반환되는 것을 꼭 참고해야 할 것 같다.
꼭 혼자 다시 만들어보기!