본문 바로가기

iOS/iOS개발

[iOS]텍스트 입력, Delegate

텍스트 필트에서의 입력과 Delegate

 

 

텍스트 필드의 속성 Placeholder

  • 위치 : Attribute Inspector > Placeholder
  • Placeholder : P텍스트 필드에 아무것도 입력하지 않았을 때 나오는 값

 

 

텍스트 필드에 아무것도 입력하지 않았을 때

 

키보드 스타일 설정

  • Keyboard Type : Number Pad로 설정하면 숫자로 된 키보드가 나오게 된다

 

 

 

텍스트 필드 변경처리

 

조건

회씨를 입력하면 섭씨로 변경처리되도록 설정

-> 컨트롤 레이어모델 레이어에서 처리한다.

 

컨트롤레이어 ConversionViewController.swift 생성

// import Foundation
import UIKit

class ConversionViewControlller : UIViewController {
    
}

 

ViewController >   indentifier Inspector > Class를 ConversionViewController로 선택

 

 

ConversionViewControlle.swift수정

// import Foundation
import UIKit

class ConversionViewControlller : UIViewController {
    
    @IBOutlet var celsiusLabel: UILabel!
    
    @IBAction func fahrenheitEditingChanged(textField: UITextField){
        celsiusLabel.text = textField.text
    }
}

 

ConversionViewController선택 > ceisiusLabel을 드래그하여 Label "100"에 드롭

 

 

IBAction 연결

 

텍스트 필드 선택 > Connection Inpector >  Sent Events의 Editing Changed를 ConversionViewController에 Dreg and Drop > fahrenheitEditingChanged 선택

 

 

텍스트필드 선택 후 Connection Inpector

 

Sent Events의 Editing Changed
fahrenheitEditingChanged 선택

 

 

-ConversionViewController.swift 수정

// import Foundation
import UIKit

class ConversionViewControlller : UIViewController {
    
    @IBOutlet var celsiusLabel: UILabel!
    
    @IBAction func fahrenheitEditingChanged(textField: UITextField){
        
        if let text = textField.text, !text.isEmpty{
            celsiusLabel.text = textField.text
        }
        else{
            celsiusLabel.text = "???"
        }
    }
}

 

 

-실행화면

 

텍스트를 입력했을때
텍스트 입력이 없을때

 

 

키보드 숨기기

 

UITextField의 두 함수

  • becomeFirstResponder : 키보드를 나타나게 한다. UITextField를 선택하면 자동 호출된다.
  • resignFirstResponder : 키보드를 사라지게 한다.

컨트롤들을 포함하고 있는 View를 클릭하면 키보드가 사라지도록 설정한다.

 

ConvertionViewController.swift 코드 수정

// import Foundation
import UIKit

class ConversionViewControlller : UIViewController {
    
    @IBOutlet var celsiusLabel: UILabel!
    @IBOutlet var textField: UITextField!
    
    @IBAction func fahrenheitEditingChanged(textField: UITextField){
        
        if let text = textField.text, !text.isEmpty{
            let fahrenheitValue = Double(text)
            let celsiusValue = (fahrenheitValue! - 32.0) * (5.0 / 9.0)
            celsiusLabel.text = String(celsiusValue)
        }
        else{
            celsiusLabel.text = "???"
        }
    }
    
    @IBAction func dismissKeyboard(sender: AnyObject){
        textField.resignFirstResponder()
    }
    
}

 

변수 fatrenheitValue 데이터 타입: Double

 

 

Tap Gesture Recognizer을 ViewController밑에 Drop > Tap Gesture Recognizer을 ViewController의 dismissKeyboard와 연결

 

 

온도 변환 구하기

 

 

ConvertionViewController.swift 코드 수정

// import Foundation
import UIKit

class ConversionViewControlller : UIViewController {
    
    @IBOutlet var celsiusLabel: UILabel!
    @IBOutlet var textField: UITextField!
    
    @IBAction func fahrenheitEditingChanged(textField: UITextField){
        
        if let text = textField.text, !text.isEmpty{
            let fahrenheitValue = Double(text)
            let celsiusValue = (fahrenheitValue! - 32.0) * (5.0 / 9.0)
            celsiusLabel.text = String(celsiusValue)
        }
        else{
            celsiusLabel.text = "???"
        }
    }
    
    @IBAction func dismissKeyboard(sender: AnyObject){
        textField.resignFirstResponder()
    }
    
}

변수 fatrenheitValue 데이터 타입 

 

 

숫자 포맷 지정자

 

ConvertionViewController.swift 코드 수정

// import Foundation
import UIKit

class ConversionViewControlller : UIViewController {
    
    @IBOutlet var celsiusLabel: UILabel!
    @IBOutlet var textField: UITextField!
    
    
    @IBAction func dismissKeyboard(sender: AnyObject){
        textField.resignFirstResponder()
    }
    
    // 1
    @IBAction func fahrenheitEditingChanged(textField: UITextField){
        
        if let text = textField.text, let value = Double(text){
            fahrenheitVlaue = value
        }
        else{
            fahrenheitVlaue = nil
        }
    }
    
    // 3
    func updateCelsiusLabel(){
        if let value = celsiusValue{
            //celsiusLabel.text = "\(value)"'
            //celsiusLabel.text = String.init(format: "%.2f", value)
            celsiusLabel.text = numberFormatter.string(from: NSDecimalNumber(decimal: Decimal(value)))
        }
        else {
            celsiusLabel.text = "???"
        }
    }
    
    // 4
    var celsiusValue: Double? {
        if let value = fahrenheitVlaue{
            return (value - 32) * (5/9)
        }
        else {
            return nil
        }
    }
    
    // 2
    var fahrenheitVlaue: Double?{
        didSet{
            updateCelsiusLabel()
        }
    }
    
    let numberFormatter: NumberFormatter = {
        let nf = NumberFormatter()
        nf.numberStyle = .decimal
        nf.minimumIntegerDigits = 0
        nf.maximumIntegerDigits = 1 // 소수점 뒤로 최대 1개까지
        return nf
    }()   
}

 

실행화면

 

 

Delegation

  • callback의 객체지향적 방식이다.
  • 하나의 delegation은 여러 개의 callback함수를 내포한다.
  • 델리게이션은 필요한 시점에 메서드를 호출해주는 역할을 하며 이벤트가 발생할 때마다 델리게이션 내의 함수를 호출한다.
  • 클래스 간 상호작용을 전달하는 간단한 접근 방식이며 클래스의 책임을 분리할 수 있다.

 

Delegate 패턴

 위임자를 갖고 있는 객체가 다른 객체에게 자신의 일을 위임(Delegate)하는 형태의 디자인 패턴이다.

 

https://velog.io/@zooneon/Delegate-%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C

 

[iOS] Delegate 패턴이란 무엇일까?

유명하고 자주 사용되는 Delegate 패턴에 대해 알아봅시다.

velog.io

 

 

 

Protocol ( = 자바에서는 interface )

  • 특정 역할을 수행하기 위한 메서드, 프로퍼티, 기타 요구사항 등의 청사진을 정의하는 것.
  • 구조체, 클래스, 열거형은 프로토콜을 채택하여 특정 기능을 수행하기 위한 프로토콜의 요구사항을 구현한다. 
  • Swift는 프로토콜 지향 언어(Protocol-Oriented-Language)이다.

 

Protocol과 Interface의 차이점

Interface

  • 프로퍼티의 기본값을 설정할 수 있다
  • 인터페이스의 모든 메서드를 구현해야 한다.

Protocol

  • 프로퍼티의 기본값을 설정하지 않는다. 프로토콜은 기능을 정의하고 제시할 뿐 스스로 기능을 구현하지 않는다.
    var age: Int = 20 // 프로토콜은 기본 값 설정 불가능 -> 오류!
  • optional 키워드를 사용하여 선택적으로 메서드를 구현할 수 있다.
protocol Person { 
  var A: Int
  func B(s: String)
  // optional 키워드를 사용.
  optional func C(status: Boolean) -> Boolean
}

class youngPerson: Person {
  var A: Int = 14
  
  func B(s: String) {
  	print(s)
  }
}

 

정리

  • Protocol : 정의만 할 뿐 초기값 설정이 불가능하고, optional 키워드를 통해 선택적으로 구현이 가능하다.
  • Interface : 초기값 설정이 가능하고, 선택적으로 구현하는 것이 불가능하다.

 

 

알파벳 문자 허용하지 않기

 

UITextFieldDelegate프로토콜 추가

class ConversionViewControlller : UIViewController, UITextViewDelegate, UITextFieldDelegate {

 

하단 코드 추가

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool{
        
        let decimalDigits = CharacterSet.decimalDigits
        for char in string.unicodeScalars{
            if !decimalDigits.contains(char){
                print("문자포함\n")
                return false;
            }
        }
        // '.' 사용불가
        let existingTextHasDecimalSeparator = textField.text?.range(of: ".")
        let replacementTextHasDecimalSeparator = string.range(of: ".")
        if existingTextHasDecimalSeparator != nil && replacementTextHasDecimalSeparator != nil{
            return false
        }
        else {
            return true
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        textField.delegate = self
    }

 

문자 입력 시 로그가 출력되는 것을 확인할 수 있다.

 

!decimalDigits.contains(char)

 

 

 

range(of:)

func range(of searchString: String) -> NSRange
  • 문자열 내에서 주어진 문자열이 처음 나타나는 범위를 찾아 반환한다.
  • 문자열의 특정 문자의 범위를 리턴해주는 메서드이다.
  • 반환값 : NSRange형태의 문자열의 위치와 길이를 반환한다.
  • options: 대소문자를 무시한다.
let str = "Hello, World!"
str.range(of: "World")
str.range(of: "world", options: [.caseInsensitive]) // 대소문자 무시

 

 

 

Range

  • [lowerBound, upperBound) 방식으로 표현
  • Swift에서의 Range는 표준 라이브러리이기 때문에 import하지 않아도 사용할 수 있다.
public struct Range<Bound: Comparable> {
  public let lowerBound: Bound
  public let upperBound: Bound
}

사용 예시

let range = 0..< countingUp.count
for i in range {
    let string = countingUp[i]
    //string
}

 

 

 

NSRange

  • Foundation에서 제공하는 구조체 타입
  • 연속적인 객체를 담고 있는 객체(String에서의 character들, Array에서의 원소들 등)에서 일정 부분을 표현하는 데 사용되는 구조체
  • 시작점인 location, Range의 길이인 length로 이루어져 있고 둘 다 Int 타입이다.
  • NSRange의 Range값은 [location, location + length) 방식으로 표현된다.
public struct _NSRange {
  public var location: Int
  public var length: Int
}

 

 

 

textField(_:shouldChangeCharactersIn:replacementString:) 

optional func textField(
    _ textField: UITextField,
    shouldChangeCharactersIn range: NSRange,
    replacementString string: String
) -> Bool
  • text가 변경할지에 대한 delegate요청 메서드
  • range: 변경되는 문자열에 관련된 NSRange 값, 이전 배열과 비교했을 때 현재 배열에서 변경된 원소의 개수
  • string: 대체 문자열
    • 문자를 하나 입력할 때 : 크기가 1인 문자열
    • 문자열 붙여 넣기를 수행할 때: 여러 개 문자열
    • 문자열을 삭제할 때: 빈 문자열

 

 

 


https://etst.tistory.com/74

 

[Swift 기초 문법] - IBAction과 IBOutlet이 뭘까

Swift 문법을 처음 공부하면서 여러 예제를 참고하다보니, 이전의 배웠던 java나 C# 등의 언어에서는 보지못했던 새로운 문법형식들이 등장해서 다소 낯설었습니다. 그래서 이런 문법들에 대해 찾

etst.tistory.com

 

https://velog.io/@youngking0914/iOSSwift-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C-vs-%EC%9D%B8%ED%84%B0%ED%8E%98%EC%9D%B4%EC%8A%A4-%EC%B0%A8%EC%9D%B4%EC%A0%90

 

[iOS][Swift] 프로토콜 vs 인터페이스 차이점

비슷해보이는 프로토콜과 인터페이스의 차이점입니다 !

velog.io

https://ios-development.tistory.com/688

 

[iOS - swift] textField(_:shouldChangeCharactersIn:replacementString:) newText 구하는 방법 (+ 문자열 처리, Range, NSRa

알아야 하는 기본 개념 Range NSRange 문자열 처리 메소드 .trimmingCharacters(In: .whitespacesAndNewlines), .replaceingCharacters(in:with:) Range half-open의 범위를 나타내고 있는 구조체 Range는 lowerB..

ios-development.tistory.com

https://soooprmx.com/swift-swift%EC%9D%98-%EB%AC%B8%EC%9E%90%EC%97%B4%EA%B3%BC-nsrange/

 

Swift의 문자열과 NSRange를 함께 사용하기 · Wireframe

Swift의 문자열 타입은 NSRange 타입과 호환되지 않지만, 기존의 코코아 프레임워크 내의 문자열 관련 처리 API들은 NSRange를 많이 사용한다. Swift 문자열을 이러한 API들과 사용하는 것은 매우 코드를

soooprmx.com

[Swift] String 고수가 될거야 (tistory.com)

 

[Swift] String 고수가 될거야

✔️ Apple 공식문서 참고 Apple Developer Documentation developer.apple.com Strings and Characters — The Swift Programming Language (Swift 5.5) Strings and Characters A string is a series of charact..

leeari95.tistory.com

https://jcsoohwancho.github.io/2019-11-17-NSRange%EC%99%80-Range/

 

NSRange와 Range

이번 포스트에서는 NSRange와 Swift에서 많이 쓰이는 Range에 대해서 알아보도록 하겠습니다. NSRange NSRange는 Foundation에서 제공하는 구조체 타입입니다. public struct _NSRange { public var location: Int public var l

jcsoohwancho.github.io

 

https://developer.apple.com/documentation/uikit/uitextfielddelegate/1619599-textfield

 

Apple Developer Documentation

 

developer.apple.com