'Swift'에 해당되는 글 61건

  1. 2021.02.18 채팅 앱 구조의 이해와 테이블 뷰 활용
  2. 2021.02.17 로그인 화면 동적 변환 구조
  3. 2021.02.16 팝업 레이아웃
  4. 2021.02.16 Switch
  5. 2021.02.15 커스텀 레이아웃을 스토리 보드와 연동
  6. 2021.02.15 Graph
  7. 2021.02.13 Floating Button
  8. 2021.02.13 table view
  9. 2021.02.13 보안 키보드 만들기
  10. 2021.02.06 StackView

시뮬레이터에 텍스트 필드를 눌러도 키보드 자판이 뜨지 않을 경우

시뮬레이터 실행 > 상단 위에 I/O 클릭

Keyboard 클릭 > Toggle Software Keyboard 클릭

 

 

cocoaTouch Class 파일 생성 시에 나오는 Also create XIB file은 컨트롤러 같은 경우는 스토리 보드 안에서 작업하기 때문에 컨트롤러가 아닌 경우에는 XIB를 같이 생성

 

 

Stretching

- 상황에 따라 전체 크기가 변함

- 1은 늘어나는게 끝까지라고 보면 됨(시작부터 끝까지 전체 다 늘어남 / 0부터 1 사이 값을 넣으면 됨)

기본 설정

 

가운데를 기준으로 한 픽셀만 잡아서 늘림

변경할때 주로 사용하는 설정

 

 

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextViewDelegate {
    
    // UITableViewDelegate와 DataSource 프로토콜을 사용하기 위해 꼭 구현해야 하는 함수
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return ChatDatas.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        // 2로 나눈 나머지 수가 짝수인 경우 이 코드를 실행
        if indexPath.row % 2 == 0 {
            
            // IndexPath가 있는걸 사용
            let myCell = tableView.dequeueReusableCell(withIdentifier: "myCell", for: indexPath) as! MyCell
            myCell.MyCellTextView.text = ChatDatas[indexPath.row]
            
            // 선택했을때 아무런 효과가 나타나지 않음
            myCell.selectionStyle = .none
            
            return myCell
            
        // 홀수인 경우 실행
        } else {
            let yourCell = tableView.dequeueReusableCell(withIdentifier: "yourCell", for: indexPath) as! YourCell
            yourCell.YourCellTextView.text = ChatDatas[indexPath.row]
            yourCell.selectionStyle = .none
            
            return yourCell
        }
    }
    
    var ChatDatas = [String]()
    

    @IBOutlet weak var chatTableView: UITableView! {
        didSet {
            
            // UITableViewDelegate와 UITableViewDataSource 프로토콜 사용
            // 스토리 보드에서 따로 할 수도 있음
            chatTableView.delegate = self
            chatTableView.dataSource = self
            
            // 구분 선 없애기
            chatTableView.separatorStyle = .none
        }
    }
    
    @IBOutlet weak var InputTextView: UITextView! {
        didSet {
            InputTextView.delegate = self
        }
    }
    
    @IBOutlet weak var InputViewBottomMargin: NSLayoutConstraint!
    @IBOutlet weak var InputTextViewHeight: NSLayoutConstraint!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        
        // 사용하려는 셀 등록
        chatTableView.register(UINib(nibName: "MyCell", bundle: nil), forCellReuseIdentifier: "myCell")
         
        chatTableView.register(UINib(nibName: "YourCell", bundle: nil), forCellReuseIdentifier: "yourCell")
        
        
        // 키보드 관련 옵저버 설정
        // 키보드 올라올 때
        NotificationCenter.default.addObserver(self, selector: #selector(KeyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
        
        // 키보드 내려올 때
        NotificationCenter.default.addObserver(self, selector: #selector(KeyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
    }

    @objc func KeyboardWillShow(noti: Notification) {
        
        // 텍스트 필드를 눌렀을때 키보드와 텍스트 필드를 같이 올라가게 함
        let notiInfo = noti.userInfo!
        let KeyboardFrame = notiInfo[UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
        
        // 아이폰 x는 기존 아이폰과 달리 safeArea 값만큼 키보다가 더 올라가서 그 값 만큼 빼줘야 함
        let height = KeyboardFrame.size.height - self.view.safeAreaInsets.bottom
        
        let animationDuration = notiInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! TimeInterval
                
        UIView.animate(withDuration: animationDuration) {
            self.InputViewBottomMargin.constant = height
            self.view.layoutIfNeeded()
        }
    }
    
    @objc func KeyboardWillHide(noti: Notification) {
        
        let notiInfo = noti.userInfo!
        let animationDuration = notiInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as!
            TimeInterval
        UIView.animate(withDuration: animationDuration) {
            self.InputViewBottomMargin.constant = 0
            self.view.layoutIfNeeded()
        }
    }

    // 전송 버튼
    @IBAction func SendString(_ sender: Any) {
        ChatDatas.append(InputTextView.text)
        
        // 텍스트 입력 후 전송 하면 입력했던 텍스트가 남아있지 않고 지워짐
        InputTextView.text = ""
        
        // 테이블 뷰 전체 갱신
        //chatTableView.reloadData()
        
        // 마지막 row로 설정 / section도 0부터 시작
        let lastInexPath = IndexPath(row: ChatDatas.count - 1, section: 0)
        
        // 테이블 뷰 마지막만 갱신
        chatTableView.insertRows(at: [lastInexPath], with: UITableView.RowAnimation.automatic)
        
        chatTableView.scrollToRow(at: lastInexPath, at: UITableView.ScrollPosition.bottom, animated: true)
        
        // 전송 버튼 누른 후 텍스트 뷰 크기를 40으로 돌려놓음
        InputTextViewHeight.constant = 40
    }
    
    // 텍스트 필드 크기 조절
    func textViewDidChange(_ textView: UITextView) {
        
        // 텍스트 크기에 맞춰서 텍스트 뷰 크기가 같이 커지고 작아짐
        if textView.contentSize.height <= 40 {
            InputTextViewHeight.constant = 40
        } else if textView.contentSize.height >= 100 {
            InputTextViewHeight.constant = 100
        } else {
            InputTextViewHeight.constant = textView.contentSize.height
        }
    }
}

'Swift' 카테고리의 다른 글

Table View  (0) 2021.03.03
버튼 관련 코드  (0) 2021.02.24
로그인 화면 동적 변환 구조  (0) 2021.02.17
팝업 레이아웃  (0) 2021.02.16
Switch  (0) 2021.02.16
Posted by khon98
,

텍스트 필드에 입력된 값은 숫자로 입력하거나 문자로 입력해도 string임

 

정규식 - regular expression

1. 이메일

let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"

 

2. ID

let idRegEx = "[A-Za-z0-9]{5,13}"

 

3. 비밀번호

let pwRegEx = "[A-Za-z0-9!_@$%^&+=]{8,20}"

 

4. 닉네임

let nickRegEx = "[가-힣A-Za-z0-9]{2,7}"

 

 

 

 

import UIKit

class ViewController: UIViewController {
    
    @IBOutlet weak var EmailTextField: UITextField!
    @IBOutlet weak var PasswordTextField: UITextField!
    @IBOutlet weak var EmailError: UILabel!
    @IBOutlet weak var PasswordError: UILabel!
    
    var EmailErrorHeight: NSLayoutConstraint!
    var PasswordErrorHeight: NSLayoutConstraint!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 텍스트 필드의 값을 입력하거나 삭제할때 editingChanged로 받을수 있음
        EmailTextField.addTarget(self, action: #selector(TextFieldEdited), for: .editingChanged)
        PasswordTextField.addTarget(self, action: #selector(TextFieldEdited), for: .editingChanged)
        
        EmailErrorHeight = EmailError.heightAnchor.constraint(equalToConstant: 0)
        PasswordErrorHeight = PasswordError.heightAnchor.constraint(equalToConstant: 0)
    }
    
    @objc func TextFieldEdited(textField: UITextField) {
        
        if textField == EmailTextField {
            print("이메일 텍스트 필드 \(textField.text!)")
            
            if isValidEmail(Email: textField.text) == true {
                
                // .isActive = true 를 해야 활성화가 됨
                // email 값 형식에 맞으면 높이 값을 0으로 설정
                EmailErrorHeight.isActive = true
                
            } else {
                
                // 아니면 비활성화
                EmailErrorHeight.isActive = false
            }
            
        } else if textField == PasswordTextField {
            print("비밀번호 텍스트 필드 \(textField.text!)")
            
            if isValidPassword(pw: textField.text) == true {
                PasswordErrorHeight.isActive = true
                
            } else {
                PasswordErrorHeight.isActive = false
            }
        }
        
        UIView.animate(withDuration: 0.1) {
            self.view.layoutIfNeeded()
        }
        
    }
    
    // 정규식 - regular expression
    // 옵셔널 스트링으로 입력을 받아서 Bool 타입으로 리턴
    func isValidEmail(Email: String?) -> Bool {
            guard Email != nil else { return false }

            let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}"
            let pred = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
            return pred.evaluate(with: Email)
        }

    func isValidPassword(pw: String?) -> Bool {
        
        // 입력한 비밀번호가 8자 이하면 false
        if let hasPassword = pw {
            if hasPassword.count < 8 {
                return false
            }
        }
        
        return true
    }
}

'Swift' 카테고리의 다른 글

버튼 관련 코드  (0) 2021.02.24
채팅 앱 구조의 이해와 테이블 뷰 활용  (0) 2021.02.18
팝업 레이아웃  (0) 2021.02.16
Switch  (0) 2021.02.16
커스텀 레이아웃을 스토리 보드와 연동  (0) 2021.02.15
Posted by khon98
,

팝업 레이아웃

Swift 2021. 2. 16. 22:03

작업할 때 슈퍼 뷰 밖으로 나가게 되는 콘텐츠들은 선택이 안됨

버튼 같은 경우 해당하는 뷰를 조금만 벗어나도 그 뷰 안에 있는 부분만 눌림

작업하는 뷰 말고 메인 뷰로 아예 빼서 작업하는 뷰와 정렬해서 작업해야 함

 

 

viewController.swift

import UIKit

class ViewController: UIViewController {

    // main story board 버튼과 연결
    @IBAction func showPopup(_ sender: Any) {
        let storyBoard = UIStoryboard.init(name: "PopupViewController", bundle: nil)
        
        let popupVC = storyBoard.instantiateViewController(withIdentifier: "PopupVC")
        
        popupVC.modalPresentationStyle = .overCurrentContext
        
        self.present(popupVC, animated: true, completion: nil)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}

 

 

 

cocoaTouch Class 파일

import UIKit

class PopupViewController: UIViewController {

    @IBAction func PopupClose(_ sender: Any) {
        self.dismiss(animated: true, completion: nil)
    }
    
    @IBAction func DoneAction(_ sender: Any) {
        print("Done")
    }
}

'Swift' 카테고리의 다른 글

채팅 앱 구조의 이해와 테이블 뷰 활용  (0) 2021.02.18
로그인 화면 동적 변환 구조  (0) 2021.02.17
Switch  (0) 2021.02.16
커스텀 레이아웃을 스토리 보드와 연동  (0) 2021.02.15
Graph  (0) 2021.02.15
Posted by khon98
,

Switch

Swift 2021. 2. 16. 20:43
import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var BtnCenterX: NSLayoutConstraint!
    @IBOutlet weak var switchBtn: UIButton!
    @IBOutlet weak var switchBg: UIView!
    
        override func viewDidLoad() {
        super.viewDidLoad()
            
            // 원으로 만들고 싶으면 해당 크기의 반 만큼 입력하면 됨
            switchBtn.layer.cornerRadius = 25
            switchBg.layer.cornerRadius = 25
    }

    @IBAction func selectedBtn(_ sender: Any) {
        
        // 버튼 이동
        if BtnCenterX.constant == 75 {
            BtnCenterX.constant = -75
            
            // 버튼이 이동할때 배경 색 변경
            switchBg.backgroundColor = UIColor.lightGray
        } else {
            BtnCenterX.constant = 75
            switchBg.backgroundColor = UIColor.gray
        }
        
        UIView.animate(withDuration: 0.5) {
            self.view.layoutIfNeeded()
        }
    }
}

'Swift' 카테고리의 다른 글

로그인 화면 동적 변환 구조  (0) 2021.02.17
팝업 레이아웃  (0) 2021.02.16
커스텀 레이아웃을 스토리 보드와 연동  (0) 2021.02.15
Graph  (0) 2021.02.15
Floating Button  (0) 2021.02.13
Posted by khon98
,
import UIKit

@IBDesignable
class DiagonalCustomImageView: UIImageView {
    
    // 숫자라고 Int 타입만 쓰면 안됨 타입을 확인 해야 함
    @IBInspectable var innerHeight: CGFloat = 150
    
    func makePath() -> UIBezierPath {
        let path = UIBezierPath()
        
        // 선 긋는 좌표 지정
        // path의 시작점은 move / cgpoint는 해당하는 좌표
        path.move(to: CGPoint.zero)
        
        // 그리기, 이미지 뷰의 끝으로 이동 y는 움질일 필요가 없으므로 0
        path.addLine(to: CGPoint.init(x: self.bounds.width, y: 0))
        
        // x축은 유지한 상태로 이미지 뷰의 높이 만큼 y축 이동
        path.addLine(to: CGPoint.init(x: self.bounds.width, y: self.bounds.height))
        
        // y에서 -50만큼 이동 후 왼쪽으로 끝까지 이동
        path.addLine(to: CGPoint.init(x: 0, y: self.bounds.height - innerHeight))
        path.close()
        
        return path
    }
    
    func pathToLayer() -> CAShapeLayer {
        let shapeLayer = CAShapeLayer()
        shapeLayer.path = makePath().cgPath
        
        return shapeLayer
    }
    
    func makeMask() {
        self.layer.mask = pathToLayer()
    }
    
    // 해당하는 오브젝트가 그려질때
    override func layoutSubviews() {
        makeMask()
    }

}

'Swift' 카테고리의 다른 글

팝업 레이아웃  (0) 2021.02.16
Switch  (0) 2021.02.16
Graph  (0) 2021.02.15
Floating Button  (0) 2021.02.13
table view  (0) 2021.02.13
Posted by khon98
,

Graph

Swift 2021. 2. 15. 22:29

deactivate

- constraints 설정을 다 비활성화 시킴

 

activate

- deactivate와 반대

 

비활성화와 활성화를 시키지 않으면 값이 중첩되기 때문에 오류 발생

 

 

import UIKit

// multiplier 값 변경하기 위한 조건
extension NSLayoutConstraint {
    func changeMultiplier(value: CGFloat) -> NSLayoutConstraint {
        
        // 처음에 있는 constraint 값 비활성화
        NSLayoutConstraint.deactivate([self])
        
        // constraints 새로 만들기
        let newConstraints = NSLayoutConstraint.init(item: self.firstItem, attribute: self.firstAttribute, relatedBy: self.relation, toItem: self.secondItem, attribute: self.secondAttribute, multiplier: value, constant: self.constant)
        
        newConstraints.priority = self.priority
        newConstraints.shouldBeArchived = self.shouldBeArchived
        newConstraints.identifier = self.identifier
        
        // 새로 만든 constraint로 활성화
        NSLayoutConstraint.activate([newConstraints])
        
        // 활성화된 constraint return
        return newConstraints
    }
}


class ViewController: UIViewController {

    @IBOutlet weak var graph1Height: NSLayoutConstraint!
    @IBOutlet weak var graph2Height: NSLayoutConstraint!
    @IBOutlet weak var graph3Height: NSLayoutConstraint!
    @IBOutlet weak var graph4Height: NSLayoutConstraint!
    @IBOutlet weak var graph5Height: NSLayoutConstraint!
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func style1(_ sender: Any) {

        // animation 추가
        UIView.animate(withDuration: 0.5) {
            
            // 클로저 안에는 self가 있어야 함
            self.graph1Height = self.graph1Height.changeMultiplier(value: 0.5)
            self.graph2Height = self.graph2Height.changeMultiplier(value: 0.8)
            self.graph3Height = self.graph3Height.changeMultiplier(value: 0.1)
            self.graph4Height = self.graph4Height.changeMultiplier(value: 0.9)
            self.graph5Height = self.graph5Height.changeMultiplier(value: 0.2)
            
            // 화면 갱신
            self.view.layoutIfNeeded()
        }
    }
    
    
    @IBAction func style2(_ sender: Any) {
        
        graph1Height = graph1Height.changeMultiplier(value: 0.1)
        graph2Height = graph2Height.changeMultiplier(value: 0.6)
        graph3Height = graph3Height.changeMultiplier(value: 0.8)
        graph4Height = graph4Height.changeMultiplier(value: 0.3)
        graph5Height = graph5Height.changeMultiplier(value: 0.5)
        
        UIView.animate(withDuration: 0.5) {
            self.view.layoutIfNeeded()
        }
    }
}

'Swift' 카테고리의 다른 글

Switch  (0) 2021.02.16
커스텀 레이아웃을 스토리 보드와 연동  (0) 2021.02.15
Floating Button  (0) 2021.02.13
table view  (0) 2021.02.13
보안 키보드 만들기  (0) 2021.02.13
Posted by khon98
,

Floating Button

Swift 2021. 2. 13. 21:15

새로운 파일 생성 시 subclass of에 UIView인지 Controller인지 확인

self 객체는 앞에 self를 입력해줘야 함

 

Up Casting

- 여러 가지 타입을 포괄하는 타입

 

Down Casting

- 여러 가지 포괄하는 타입의 하위 타입 중에 하나를 선택하는 개념

 

viewDidLoad

- view controller가 실행하면서 같이 실행되는 func

- 화면이 그려지기 전에 오브젝트들이 생성되면서 실행되는 부분

 

viewDidAppear

- 디바이스가 실행되고 보이는 시점

 

Duration

- 초를 의미(1은 1초, 0.3은 0.3초)

 

Damping

- 흔들림 애니메이션

 

delay

- Duration과 비슷한 개념,  delay 할 필요가 없으면 0

 

usingSpringWithDamping

- 0에 가까울수록 흔들림이 커짐(0 ~ 1 사이에 값을 넣음 / 0.3이나 0.8 같은 소수, 1 이상 갑은 흔들림 없음)

 

layoutIfNeeded

- layoutIfNeeded가 없으면 화면 갱신이 안됨

- Duration에 입력한 숫자만큼 분할해서 갱신(Duration에 1을 넣으면 1초의 시간에 맞춰서 움직임이 표현)

 

 

ViewController.swift

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "ShowPopup" {
            
            // 다운 캐스팅
            let FloatingVC = segue.destination as! FloatingButtonListViewController
            
            // 해당하는 화면이 투명하게 나오게 하기
            FloatingVC.modalPresentationStyle = .overCurrentContext
        }
    }
}

 

 

cocoa touch class

import UIKit

class FloatingButtonListViewController: UIViewController {

    @IBOutlet weak var btn1CenterY: NSLayoutConstraint!
    @IBOutlet weak var btn2CenterY: NSLayoutConstraint!
    @IBOutlet weak var btn3CenterY: NSLayoutConstraint!
    
    // 처음 실행되는 부분
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // constant 값 초기화
        btn1CenterY.constant = 0
        btn2CenterY.constant = 0
        btn3CenterY.constant = 0

    }
    
    
    // 디바이스를 실행해서 화면이 보이는 시점
    override func viewDidAppear(_ animated: Bool) {
        // super는 규칙이라고 생각하면 됨
        super.viewDidAppear(animated)
        
        // withDuration 버튼이 올라오는 시간 0에 가까울수록 빨리 올라감
        UIView.animate(withDuration: 1, delay: 0, usingSpringWithDamping: 0.5, initialSpringVelocity: 0.5, options: .curveEaseOut) {
            
            self.btn1CenterY.constant = 80
            self.btn2CenterY.constant = 160
            self.btn3CenterY.constant = 240
            
            // 화면 갱신,layoutIfNeeded를 꼭 해야 갱신 됨
            self.view.layoutIfNeeded()
            
            // 애니메이션이 끝나는 시점
        } completion: { (completion) in
        }
    }

    
    @IBAction func DismissFloating(_ sender: Any) {
        
        // withDuration 버튼이 내려가는 시간 0에 가까울수록 빨리 내려감
        UIView.animate(withDuration: 0.6, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 0.5, options: .curveEaseOut) {
            
            self.btn1CenterY.constant = 0
            self.btn2CenterY.constant = 0
            self.btn3CenterY.constant = 0
            
            self.view.layoutIfNeeded()
            
        } completion: { (completion) in
            
            // animation 효과를 사용안하면 animated에 false입력
            // completion은 옵셔널이라 사용 안할경우 nil입력 가능
            self.dismiss(animated: false, completion: nil)
            
        }

    }
    
    @IBAction func Food3Action(_ sender: Any) {
        print("food3 selected")
    }
    
    @IBAction func Food2Action(_ sender: Any) {
        print("food2 selected")
    }
    
    @IBAction func Food1Action(_ sender: Any) {
        print("food1 selected")
    }
}

 

'Swift' 카테고리의 다른 글

커스텀 레이아웃을 스토리 보드와 연동  (0) 2021.02.15
Graph  (0) 2021.02.15
table view  (0) 2021.02.13
보안 키보드 만들기  (0) 2021.02.13
StackView  (0) 2021.02.06
Posted by khon98
,

table view

Swift 2021. 2. 13. 14:27

오토 레이아웃으로 구성되어 있는 크기나 이런 부분이 테이블 뷰 셀을 만났을 때는 변형이 일어나 애니메이션 효과가 튀는 경우가 생김

 

오류 해결 방법

1. heightForRowAt에서 정확한 높이 지정으로 오류 해결

2. tableView.rerloadData()를 이용해 어느 정도 해결 가능

3. tableView.extimatedSelectionHeaderHeight = 0 / extimatedSelectionFooterHeight = 0으로 해결할 수도 있음

4. 애니메이션 효과를 없애는 방법

- 애니메이션 효과가 계속 없으면 안 되니까 reload가 끝나는 부분에 true로 바꿔줘야 함 안 그러면 모든 애니메이션 효과가 없어짐

UIView.setAnimationsEnabled(false)

 

 

import UIKit

// 클래스 생성
class ExpandCell: UITableViewCell {
    @IBOutlet weak var descriptionLabel: UILabel!
    
}

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
    struct ExpandDataModel {
        var description: String
        var isExpand: Bool
    }
    
    // .init()과 ()는 같음 / []는 array 표시
    var DataModels = [ExpandDataModel]()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let textArray = ["short text",
        "long long long long long long long text",
        "short text",
        "long long long long long long long text",
        "short text",
        "long long long long long long long text"]
        
        // 안쓰는건 _로 표시
        for (_,value) in textArray.enumerated() {
            DataModels.append(ExpandDataModel.init(description: value, isExpand: false))
        }
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return DataModels.count
    }
    
    // cellForRowAt - 셀을 구성하는 부분에 대한 개념
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        // 셀 선언
        let cell = tableView.dequeueReusableCell(withIdentifier: "expandCell_ID", for: indexPath) as! ExpandCell
        
        // 한 줄 한 줄 개념을 row로 보면 됨
        cell.descriptionLabel.text = DataModels[indexPath.row].description
        
        // expand가 true이면 확장
        // expand이면 전체 줄 출력
        if DataModels[indexPath.row].isExpand == true {
            cell.descriptionLabel.numberOfLines = 0 // 0은 텍스트를 모두 표현
        } else { // 확장 된 상태가 아니라면
            // expand가 아니라면 1줄만 출력
            cell.descriptionLabel.numberOfLines = 1
        }
        
        // 터치 했을때 나오는 효과를 없앰
        cell.selectionStyle = .none
        
        return cell
    }

    // 클릭했을때 사용되는 func / didSelectRowAt
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        
        // expand 값을 바꿈
        DataModels[indexPath.row].isExpand = !DataModels[indexPath.row].isExpand
        
        // 화면에 모든 애니메이션 효과를 없앰
        // reload가 끝나는 부분에서 true로 바꿔줘야 함
        UIView.setAnimationsEnabled(false)
        
        // table view 화면은 자동으로 갱신되지 않음
        tableView.reloadRows(at: [indexPath], with: .none)
        UIView.setAnimationsEnabled(true)
        
    }
}

'Swift' 카테고리의 다른 글

Graph  (0) 2021.02.15
Floating Button  (0) 2021.02.13
보안 키보드 만들기  (0) 2021.02.13
StackView  (0) 2021.02.06
코드로 오브젝트 추가  (0) 2021.02.06
Posted by khon98
,

보안 키보드 만들기

Swift 2021. 2. 13. 01:26

file > new > file > Cocoa Touch Class > Subclass of: uiview

(xib파일은 view나 empty나 똑같음)

file > new > file > view > (이름은 연동해서 사용할 class 이름과 같이 사용하는 게 편함)

 

xib파일은 nib파일과 동일

 

컨트롤러가 아닌 걸 추가하고 싶은 경우에는 xib파일을 사용

컨트롤러는 스토리보드에 추가할 수 있지만 컨트롤러가 아닌 거는 추가를 할 수 없음

 

size를 freeform으로 하면 원하는 데로 크기를 조절할 수 있음

 

생성한 xib에 view class 이름을 Cocoa Tocuh Class에 입력한 이름으로 입력

 

 

Interaction에 User Interaction Enabled 체크를 해제하면 해당 버튼의 이벤트가 없어짐(눌러도 아무런 입력이 없음)

 

delegate

- 기능이나 값을 위임

- 오브젝트가 끊어지지 않고 남아있어서 메모리 누수가 생길 수도 있기 때문에 옵셔널로 선언

 

 

if let - 옵셔널 타입을 벗겨냄

 

 

 

viewcontroller.swift

import UIKit

class ViewController: UIViewController, CustomKeyboardDelegate {
    
    @IBOutlet weak var FirstTextView: UITextField! // 첫번째 텍스트 이름
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 커스텀 키보드 설정 방법
        // owner / option 값이 있으면 self를 입력 하면 됨
        let loadNib = Bundle.main.loadNibNamed("CustomKeyboard", owner: nil, options: nil)
        
        // array와 같은 개념 first, 첫번째 인덱스 즉 0번째 인덱스에 있는 오브젝트를 가져오라는 뜻
        // as! 타입 캐스팅
        let myKeyboardView = loadNib?.first as! CustomKeyboard
        
        // 뷰 컨트롤러로 위임
        myKeyboardView.delegate = self
        FirstTextView.inputView = myKeyboardView
    }
    // 키보드 눌렀을때 호출
    func KeyboardTapped(str: String) {
        print(str)
        
        // 타입 변환
        // 기존에 입력한 숫자
        let oldNum = Int(FirstTextView.text!)
        
        // 새로 입력한 숫자
        var newNum = Int(str)
        
        if str == "00" && oldNum != nil {
            newNum = oldNum! * 100 // nil이기 때문에 ! 해도 됨
        }
        
        if str == "000" && oldNum != nil {
            newNum = oldNum! * 1000
        }
        
        if let hasNum = newNum {
            // 쉼표 만들기
            let numberFormatter = NumberFormatter()
            numberFormatter.numberStyle = .decimal
            
            if let formatted = numberFormatter.string(from: NSNumber(value: hasNum)) {
                FirstTextView.text = String(describing: formatted)
            }
        }
    }
}

 

 

cocoa touch class로 만든 파일

import UIKit

protocol CustomKeyboardDelegate {
    func KeyboardTapped(str: String)
}

class CustomKeyboard: UIView {
    
    // 프로토콜이 사용될수 있도록 연결
    var delegate: CustomKeyboardDelegate?

    @IBAction func BtnNum(_ sender: UIButton) {
        delegate?.KeyboardTapped(str: sender.titleLabel!.text!)
    }
}

'Swift' 카테고리의 다른 글

Floating Button  (0) 2021.02.13
table view  (0) 2021.02.13
StackView  (0) 2021.02.06
코드로 오브젝트 추가  (0) 2021.02.06
Button Inset  (0) 2021.02.05
Posted by khon98
,

StackView

Swift 2021. 2. 6. 11:30

StackView

- 오브젝트들을 정렬해서 나열하는 개념

- 복잡한 constraints 설정들을 간단하게 설정할 수 있음

- 그룹을 나눠서 작업하는걸 추천

'Swift' 카테고리의 다른 글

table view  (0) 2021.02.13
보안 키보드 만들기  (0) 2021.02.13
코드로 오브젝트 추가  (0) 2021.02.06
Button Inset  (0) 2021.02.05
스크롤 뷰  (0) 2021.02.05
Posted by khon98
,