꾸준히 안타치기

Stepper 커스텀을 위한 속성추가 ???????????? 본문

iOS/기본편 | 실전편 -꼼꼼한재은씨

Stepper 커스텀을 위한 속성추가 ????????????

글자줍기 2022. 2. 5. 16:19
반응형

import UIKit
@IBDesignable // 스토리보드미리보기처리
// 액션이벤트를 처리하려면,UIControl를 서브클래싱해야한다.
public class CSStepper: UIControl {
   
    // 접근제한 범위 설정
    public var leftBtn = UIButton(type: .system) // 좌측 버튼
    public var rightBtn = UIButton(type: .system) // 우측 버튼
    public var centerLabel = UILabel() // 중앙 레이블
    
    //스테퍼의 현재값을 저장할 변수
    @IBInspectable // 인터페이스빌더에서도 사용할수있도록함
    public var value: Int = 0 {
        didSet { //프로퍼티의 값이 바뀌면 자동으로 호출된다.
            self.centerLabel.text = String(value)
            
            // 이 클래스를 사용하는 객체들에게 valueChanged이벤트 신호를 보내준다.
            //sendActions는 인자값으로 입력된 타입의이벤트를 발생시키는 메소드
            //스테퍼가 눌릴때 valueChanged 이벤트를 발생시킨다.
            self.sendActions(for: .valueChanged)
        }
    }
    
    // 스토리보드에서 호출할 초기화 메소드
    public required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        // 셋업메소드에 스테터 속성작성
        self.setup()
    }
    
    // 프로그래밍 방식으로 호출할 초기화 메소드
    public override init(frame: CGRect){
        super.init(frame: frame)
        self.setup()
    }
    
    //뷰의 크키가 변할때 호출되는 메소드
    override public func layoutSubviews() {
        super.layoutSubviews()
        
        // 버튼의 너비 = 뷰 높이
        let btnWidth = self.frame.height
        
        // 레이블의 너비 = 뷰 전체의 크기 - 양쪽 버튼 너비의 합
        let lblWidth = self.frame.width - (btnWidth * 2)
        
        self.leftBtn.frame = CGRect(x: 0, y: 0, width: btnWidth, height: btnWidth)
        self.centerLabel.frame = CGRect(x: btnWidth, y: 0, width: lblWidth, height: btnWidth)
        self.rightBtn.frame = CGRect(x: btnWidth + lblWidth, y: 0, width:btnWidth, height: btnWidth)
    }
    
    
    private func setup(){
        // 클래스 내부에서만 사용 private
        // 스테퍼의 기본 속성을 설정한다.
        
        let borderWidth: CGFloat = 0.5
        let borderColor = UIColor.blue.cgColor
        
        // 좌측 다운 버튼 속성 설정
        self.leftBtn.tag = -1 //태그값이 -1
//        self.leftBtn.setTitle("⬇", for: .normal)//버튼의 타이틀 수정
        self.leftBtn.setTitle(self.leftTitle, for: .normal)//버튼의 타이틀 수정
        self.leftBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)// 폰트
        self.leftBtn.layer.borderWidth = borderWidth //버튼테투리두께
        self.leftBtn.layer.borderColor = borderColor //버튼테두리색상
        
        // 우측 업 버튼 속성
        self.rightBtn.tag = 1  //태그값이 +1
//        self.rightBtn.setTitle("⬆", for: .normal)//버튼의 타이틀
        self.rightBtn.setTitle(self.rightTitle, for: .normal)//버튼의 타이틀 수정
        self.rightBtn.titleLabel?.font = UIFont.boldSystemFont(ofSize: 20)// 폰트
        self.rightBtn.layer.borderWidth = borderWidth //버튼테투리두께
        self.rightBtn.layer.borderColor = borderColor //버튼테두리색상
        
        // 중앙 레이블 속성 설정
        self.centerLabel.text = String(value) // 컨트롤의 현재값을 문자열로 변환하여 표시
        self.centerLabel.font = UIFont.systemFont(ofSize: 16) // 레이블의 폰트
        self.centerLabel.textAlignment = .center // 가운데 정렬
        //self.centerLabel.backgroundColor = .cyan
        self.centerLabel.backgroundColor = self.bgColor // 배경 색상 지정
        self.centerLabel.layer.borderWidth = borderWidth // 레이블의 테두리 두께
        self.centerLabel.layer.borderColor = borderColor // 레이블의 테두리 색상 - 파란색
        
        //영역별객체를 서브 뷰로 추가한다.
        self.addSubview(self.leftBtn)
        self.addSubview(self.rightBtn)
        self.addSubview(self.centerLabel)
        
        //버튼의 터치 이벤트와 valuechange메소드를 연결한다.
        self.leftBtn.addTarget(self, action: #selector(valueChange(_:)), for: .touchUpInside)
        self.rightBtn.addTarget(self, action: #selector(valueChange(_:)), for: .touchUpInside)
    }
    
   
    
    // value 속성의 값을 변경하는 메소드(호출하는 곳이 외부이므로 public)
    @objc public func valueChange(_ sender: UIButton){
        // 현재의 값에 +1 또는 -1한다
        let sum = self.value + (sender.tag * self.stepValue)
        
        // 더한 결과가 최대값보다 크면 값을 변경하지 않고 종료
        if sum > self.maximumValue {
            return
        }
        //더한 결과가 최소값보다 작으면 값을 변경하지 않고 종료
        if sum < self.minimumValue {
            return
        }
        // 현재의 value값에 +1 또는 -1 한다.
        self.value += (sender.tag * self.stepValue)
    }
    
    // 좌측 버튼의 타이틀 속성
    @IBInspectable // 인터페이스빌더에서도 사용할수있도록함
    public var leftTitle : String = "⬇" {
        didSet {
            self.leftBtn.setTitle(leftTitle, for: .normal)
        }
    }
    
    // 우측 버튼의 타이틀 속성
    @IBInspectable // 인터페이스빌더에서도 사용할수있도록함
    public var rightTitle: String = "⬆" {
        didSet {
            self.rightBtn.setTitle(rightTitle, for: .normal)
        }
    }
    
    // 센터 영역의 색상 / 값이 변경되었을때 프로퍼티옵저버를 통해 적용한다.
    @IBInspectable // 인터페이스빌더에서도 사용할수있도록함
    public var bgColor: UIColor = UIColor.cyan {
        didSet {
            self.centerLabel.backgroundColor = backgroundColor
        }
    }
    
    // 증감값 단위
    @IBInspectable // 인터페이스빌더에서도 사용할수있도록함
    public var stepValue: Int = 1
    
    // 최대값과 최소값
    @IBInspectable public var maximumValue: Int = 100
    @IBInspectable public var minimumValue: Int = -100
 
}

인터페이스 빌더에서도 사용할수 있도록, @IBInspectable을 작성해주면, 스토리보드에서 아래와 같이 생성됨

ViewController.swift

코드로 작성한 스텝퍼 값이 표기됨

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // CSStepper 객체 정의
        let stepper = CSStepper()
        stepper.frame = CGRect(x: 100, y: 100, width: 130, height: 30)
        
        //valueChange 이벤트가 발생하면 logging메소드가 호출되도록
        stepper.addTarget(self, action: #selector(logging(_:)), for: .valueChanged)
        self.view.addSubview(stepper)
    }
    
    @objc func logging(_ sender: CSStepper){
        NSLog("현재 스테퍼의 값은 \(sender.value)입니다.")
    }
}

 

반응형
Comments