Skip to content

Commit

Permalink
[FEAT][#7] 출석코드입력란 기능 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
tngusmiso committed Feb 11, 2023
1 parent 23bab8f commit 46106db
Show file tree
Hide file tree
Showing 4 changed files with 133 additions and 7 deletions.
14 changes: 14 additions & 0 deletions Extensions/Collection+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Collection+Extension.swift
// momoIOS
//
// Created by 임수현 on 2023/02/11.
//

import Foundation

extension Collection {
subscript (safe index: Index) -> Element? {
return indices.contains(index) ? self[index] : nil
}
}
40 changes: 40 additions & 0 deletions Extensions/String+Extension.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//
// String+Extension.swift
// momoIOS
//
// Created by 임수현 on 2023/02/11.
//

import Foundation

extension String {
subscript (safe index: Int) -> String? {
guard self.count > index else { return nil }
let index = self.index(self.startIndex, offsetBy: index)
return "\(self[index])"
}

subscript (range: Range<Int>) -> String? {
let fromIndex = self.index(self.startIndex, offsetBy: max(0, range.lowerBound))
let toIndex = self.index(self.startIndex, offsetBy: min(range.upperBound, self.count))
return String(self[fromIndex..<toIndex])
}

subscript(_ range: Range<Int>) -> String {
let fromIndex = self.index(self.startIndex, offsetBy: range.startIndex)
let toIndex = self.index(self.startIndex, offsetBy: range.endIndex)
return String(self[fromIndex..<toIndex])
}

func replaced(_ string: String, in range: NSRange) -> String? {
guard let range = Range(range, in: self) else { return nil }
return self.replacingCharacters(in: range, with: string)
}

var isBackspace: Bool {
if let char = self.cString(using: String.Encoding.utf8) {
return strcmp(char, "\\b") == -92
}
return false
}
}
8 changes: 8 additions & 0 deletions momoIOS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
3A75FC10298827BE00B36A46 /* MainAttendanceCodeCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3A75FC0F298827BE00B36A46 /* MainAttendanceCodeCell.swift */; };
3AA713C929884007006F922F /* MainAttendanceDoneCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA713C829884007006F922F /* MainAttendanceDoneCell.swift */; };
3AA713D1298946FF006F922F /* UIColor+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3AA713D0298946FF006F922F /* UIColor+Extension.swift */; };
3ABBF7362996B6C9004D4D0B /* String+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABBF7352996B6C9004D4D0B /* String+Extension.swift */; };
3ABBF73A2996B8C9004D4D0B /* Collection+Extension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ABBF7392996B8C9004D4D0B /* Collection+Extension.swift */; };
3ADF66102993F48A00577028 /* AttendanceDetailViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3ADF660F2993F48A00577028 /* AttendanceDetailViewController.swift */; };
BF0408632987B3AA00F1129B /* LoginController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF0408622987B3AA00F1129B /* LoginController.swift */; };
BF04086B2987E34800F1129B /* AuthCommonConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = BF04086A2987E34800F1129B /* AuthCommonConstants.swift */; };
Expand Down Expand Up @@ -45,6 +47,8 @@
3A75FC0F298827BE00B36A46 /* MainAttendanceCodeCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainAttendanceCodeCell.swift; sourceTree = "<group>"; };
3AA713C829884007006F922F /* MainAttendanceDoneCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainAttendanceDoneCell.swift; sourceTree = "<group>"; };
3AA713D0298946FF006F922F /* UIColor+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIColor+Extension.swift"; sourceTree = "<group>"; };
3ABBF7352996B6C9004D4D0B /* String+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extension.swift"; sourceTree = "<group>"; };
3ABBF7392996B8C9004D4D0B /* Collection+Extension.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Collection+Extension.swift"; sourceTree = "<group>"; };
3ADF660F2993F48A00577028 /* AttendanceDetailViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttendanceDetailViewController.swift; sourceTree = "<group>"; };
BF0408622987B3AA00F1129B /* LoginController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginController.swift; sourceTree = "<group>"; };
BF04086A2987E34800F1129B /* AuthCommonConstants.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthCommonConstants.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -174,6 +178,8 @@
children = (
E8207931298A163400B36FC9 /* UIView+Extension.swift */,
BFB8431E298CFF9200BA11EC /* UIStackView+Extension.swift */,
3ABBF7352996B6C9004D4D0B /* String+Extension.swift */,
3ABBF7392996B8C9004D4D0B /* Collection+Extension.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -332,6 +338,7 @@
BF6EC77F298D1B2E00F4B170 /* AttendanceResultCell.swift in Sources */,
BF04086B2987E34800F1129B /* AuthCommonConstants.swift in Sources */,
3A5AC31029898B330080323A /* UIButton+Extension.swift in Sources */,
3ABBF7362996B6C9004D4D0B /* String+Extension.swift in Sources */,
3ADF66102993F48A00577028 /* AttendanceDetailViewController.swift in Sources */,
E8207934298A22D000B36FC9 /* MainSessionInfoCell.swift in Sources */,
E8207932298A163400B36FC9 /* UIView+Extension.swift in Sources */,
Expand All @@ -342,6 +349,7 @@
3AA713D1298946FF006F922F /* UIColor+Extension.swift in Sources */,
3AA713C929884007006F922F /* MainAttendanceDoneCell.swift in Sources */,
E820792F298A138500B36FC9 /* MainSessionAbsentCell.swift in Sources */,
3ABBF73A2996B8C9004D4D0B /* Collection+Extension.swift in Sources */,
BF4310FA298C525900270DBF /* AttendanceHistoryCell.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ class AttendanceDetailViewController: UIViewController {
textField.textColor = .white
textField.font = .systemFont(ofSize: 32, weight: .medium)
textField.keyboardType = .numberPad
// textField.delegate = self
// textField.dataSource = self
textField.delegate = self
}

self.descriptionLabel.text = "운영진이 공지해준 출석체크 코드를 입력해주세요!"
Expand Down Expand Up @@ -139,8 +138,51 @@ class AttendanceDetailViewController: UIViewController {
make.height.equalTo(54)
}
}
}

// MARK: - UITextFieldDelegate
extension AttendanceDetailViewController: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
let currentText = textField.text ?? ""
let newText = range.lowerBound == 0 ? string : currentText.replaced(string, in: range) ?? ""

if newText.count == 0 {
textField.text = newText
self.prevTextField(textField)?.becomeFirstResponder()
} else {
self.fillTextField(textField, with: newText)
}
return false
}

// MARK: - TextField Values
private var isEditingCode: Bool {
for textField in self.codeTextFields where textField.isEditing == true {
return true
}
return false
}

private func textFieldIndex(of textField: UITextField) -> Int? {
for index in 0..<self.codeTextFields.count {
if textField == self.codeTextFields[index] {
return index
}
}
return nil
}

// MARK: - Actions
private func prevTextField(_ textField: UITextField) -> UITextField? {
guard let index = self.textFieldIndex(of: textField) else { return nil }
return self.codeTextFields[safe: index - 1]
}

private func nextTextField(_ textField: UITextField) -> UITextField? {
guard let index = self.textFieldIndex(of: textField) else { return nil }
return self.codeTextFields[safe: index + 1]
}

// MARK: - TextField Actions
@objc func keyboardWillShow(_ notification: NSNotification) {
if self.isEditingCode {
self.attendButton.moveWithKeyboard(
Expand All @@ -159,9 +201,31 @@ class AttendanceDetailViewController: UIViewController {
)
}

// MARK: - Logics
private var isEditingCode: Bool {
let textFileds = self.codeTextFields
return textFileds[0].isEditing || textFileds[1].isEditing || textFileds[2].isEditing || textFileds[3].isEditing
private func fillTextField(_ textField: UITextField, with string: String) {
let string = string.trimmingCharacters(in: CharacterSet(charactersIn: "0123456789.").inverted)
guard !string.isEmpty else { return }
textField.text = string[safe: 0]

guard let nextTextField = self.nextTextField(textField) else { return }
nextTextField.becomeFirstResponder()
if nextTextField.text?.isEmpty == false {
self.setCursor(of: nextTextField, at: 0)
}
self.fillTextField(nextTextField, with: string[1..<string.count])
}

private func clearTextField(after textField: UITextField) {
guard let index = self.textFieldIndex(of: textField) else { return }
let nextIndex: Int = index + 1
let totalCount = self.codeTextFields.count

for index in nextIndex..<totalCount {
self.codeTextFields[safe: index]?.text = ""
}
}

private func setCursor(of textField: UITextField, at position: Int) {
let position = textField.position(from: textField.beginningOfDocument, offset: position)!
textField.selectedTextRange = textField.textRange(from: position, to: position)
}
}

0 comments on commit 46106db

Please sign in to comment.