[새싹 iOS] 2주차_코드

임승섭·2023년 7월 29일
1

새싹 iOS

목록 보기
5/45
post-thumbnail

isHidden, TextView

//
//  PlayListViewController.swift
//  sesac2
//
//  Created by 임승섭 on 2023/07/24.
//

import UIKit

class PlayListViewController: UIViewController {

    
    @IBOutlet var firstImageView: UIImageView!
    @IBOutlet var secondImageView: UIImageView!
    @IBOutlet var thirdImageView:UIImageView!
    
    @IBOutlet var firstLabel: UILabel!
    @IBOutlet var secondLabel: UILabel!
    @IBOutlet var thirdLabel: UILabel!
    
    @IBOutlet var firstButton: UIButton!
    @IBOutlet var secondButton: UIButton!
    @IBOutlet var thirdButton: UIButton!
    
    // 아래에 띄워줄 가사
    let lyrics = ["가사1", "가사2", "가사3"]
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    
    // 여러 버튼을 하나의 액션에 묶었다
    // 서로 다른 버튼인 걸 어떻게 알 수 있을까?
    // 지난 시간 : sender의 title로 구분
    // 만약 title까지 다 같다면..? -> tag 기능
    // 인스펙터 창에 View 내려가서 Tag 찾아라
    @IBAction func playButtonTapped(_ sender: UIButton) {
        
        // tag 확인 가능
        print(sender.tag)
        print(lyrics[sender.tag - 1])
    }
    
    
    // 바탕을 탭 하면 이미지뷰가 사라지도록
    // 스택뷰기 때문에 공간을 차지하지 않고, 알아서 레이아웃이 이쁘게 적용됨
    @IBAction func backgroundTapGesture(_ sender: UITapGestureRecognizer) {
        
        // 1. 처음에 바뀌고 끝
//        firstImageView.isHidden = true
        
        // 2. 왔다갔다 하게
//        if firstImageView.isHidden == true {
//            firstImageView.isHidden = false
//        } else {
//            firstImageView.isHidden = true
//        }
        
        // 2 - 2.
//        firstImageView.isHidden = !firstImageView.isHidden
        
        // 2 - 3.
//        firstImageView.isHidden.toggle();
        
        // 2 - 4.
        firstImageView.isHidden = (firstImageView.isHidden)  ? false : true
        
    }
}

KingFisher, Segment Control

//
//  TestViewController.swift
//  sesac2
//
//  Created by 임승섭 on 2023/07/24.
//

import UIKit
import Kingfisher

enum Actor: Int {
    case man
    case woman
}

class TestViewController: UIViewController {

    
    @IBOutlet var segmentControl: UISegmentedControl!
    @IBOutlet var userTextField: UITextField!
    
    @IBOutlet var acterImageView: UIImageView!
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 만약에 얘가 100MB면...
        let url = URL(string: "https://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAyMjA4MTFfMTc2%2FMDAxNjYwMjAzNzMxNDU3.gBMVn-m1sGuKaK0Wy9zRkhY0HQcpMlLGIZQaIDzIv7Ug.imlhMCq-qFQFaCaOD9J5Ei_ZTsGX_N7jLdrzad1w5V4g.JPEG.sinseoyeon_8423%2F%253F%258B%25A4%253F%259A%25B4%25EB%25A1%259C%25EB%2593%259C%253F%258C%258C%253F%259D%25BC_20220811_073101.jpg&type=a340")
        acterImageView.kf.setImage(with: url)
        
    }
    
    
    @IBAction func segmentValueChanged(_ sender: UISegmentedControl) {
        
        if (sender.selectedSegmentIndex ==  Actor.man.rawValue) {
            view.backgroundColor = .red
            
            acterImageView.kf.setImage(with: URL(string: "http://search.pstatic.net/common/?src=http%3A%2F%2Fblogfiles.naver.net%2FMjAyMjA4MTFfMTc2%2FMDAxNjYwMjAzNzMxNDU3.gBMVn-m1sGuKaK0Wy9zRkhY0HQcpMlLGIZQaIDzIv7Ug.imlhMCq-qFQFaCaOD9J5Ei_ZTsGX_N7jLdrzad1w5V4g.JPEG.sinseoyeon_8423%2F%253F%258B%25A4%253F%259A%25B4%25EB%25A1%259C%25EB%2593%259C%253F%258C%258C%253F%259D%25BC_20220811_073101.jpg&type=a340"))
        } else if (sender.selectedSegmentIndex == Actor.woman.rawValue) {
            view.backgroundColor = .green
            
            acterImageView.kf.setImage(with: URL(string: "http://i.namu.wiki/i/R0AhIJhNi8fkU2Al72pglkrT8QenAaCJd1as-d_iY6MC8nub1iI5VzIqzJlLa-1uzZm--TkB-KHFiT-P-t7bEg.webp"))
        } else {
            acterImageView.kf.setImage(with: URL(string: "https://i.namu.wiki/i/KHZxgx6dilwr4Z7uu6wSPoVlf5aIb6rq6qIOBV2LYBYdN9cWFaLlvkggojNNTD6mrwtGxS_lTPh4Woge2hzuZQ.webp"))
        }
    }
    
    
    
    // 다른 화면에서 TransitionViewController로 돌아올 때 (unwind)
    // 액션 연결하지 않고, 직접 작성
    @IBAction func unwindToHome(_ segue: UIStoryboardSegue) {
        
    }
}

Custom Cell

//
//  CustomTableViewController.swift
//  0727sesac
//
//  Created by 임승섭 on 2023/07/28.
//

// 7/28 수업

import UIKit


class CustomTableViewController: UITableViewController {
    
    let todo = ToDoInformation()

    override func viewDidLoad() {
        super.viewDidLoad()

        // 3. 셀 높이 통일
        tableView.rowHeight = 80
    }
    
    // 1. 셀 개수
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return todo.list.count
    }
    
    
    // 2. 셀 데이터 및 디자인
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        // 타입 캐스팅
        // as 전 : UITableViewCell
        // as 써주면 : CustomTableViewCell
        let cell = tableView.dequeueReusableCell(withIdentifier: CustomTableViewCell.identifier)! as! CustomTableViewCell
        // CustomTableViewCell.identifier -> static let (타입 프로퍼티)로 사용
        
        
        
        // 어제 : cell.textLabel?.text
        // 주의 : label outlet을 tableviewcontroller에 연결하지 않는다
        // 그럼 어떻게 구현할거냐 -> UITableViewCell같은 애들 하나 더 만든다
        
        let row = todo.list[indexPath.row]
        
        // CustomTableViewCell에 만들어둔 함수
        cell.configureCell(row)
        
        
        return cell
    }
    
    
    // 셀 선택 시
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("select", indexPath)
    }

}

LED Board

  • View isHidden, Tap Gesture
//
//  LEDBoardViewController.swift
//  0724hw
//
//  Created by 임승섭 on 2023/07/24.
//

import UIKit

class LEDBoardViewController: UIViewController {

    // outlet
    @IBOutlet var mainLabel: UILabel!
    @IBOutlet var sendButton: UIButton!
    @IBOutlet var textColorButton: UIButton!
    @IBOutlet var mainTextField: UITextField!
    @IBOutlet var upperView: UIView!
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 디자인
        designMainLabel(mainLabel)
        designButton(sendButton, name: "보내기")
        designButton(textColorButton, name: "Aa")
        
        upperView.layer.cornerRadius = 10
        upperView.backgroundColor = .white
        
        // 텍스트필드의 테두리를 없애기 위한 작업 -> 오래걸림
        // borderStyle을 .none으로 해준다는 거 기억하기
        mainTextField.borderStyle = .none
        mainTextField.textColor = .red
    }
    
    
    /* 초기 디자인함수 */
    // 레이블
    func designMainLabel(_ sender: UILabel) {
        sender.text = "Hello Swift"
        sender.textColor = .red
        sender.textAlignment = .center
        sender.font = UIFont.boldSystemFont(ofSize: 40)
        sender.numberOfLines = 0
    }
    
    // 버튼
    func designButton(_ sender: UIButton, name: String) {
        
        sender.layer.cornerRadius = 10
        sender.layer.borderColor = UIColor.black.cgColor
        sender.layer.borderWidth = 1
        
        switch(name) {
        case "보내기":
            sender.tintColor = .black
        case "Aa":
            sender.tintColor = .red
        default:
            break;
        }
    }
    
    
    
    /* 기능 함수 */
    // 보내기 버튼 - 키보드 내려가기, 레이블 띄워주기
    @IBAction func sendButtonTapped(_ sender: UIButton) {
        // 키보드 내려가기
        view.endEditing(true)
        
        // 레이블 띄워주기
        mainLabel.text = mainTextField.text
    }
    
    // 리턴키 - 키보드 내려가기, 레이블 띄워주기
    @IBAction func keyboardReturnTapped(_ sender: UITextField) {    // Did End On Exit
        // 키보드 내려가기 (자동 구현)
        // view.endEditing(true)
        
        // 레이블 띄워주기
        mainLabel.text = mainTextField.text
    }
    
    
    // 배경 선택 시 - 키보드 내려가기 or 상단 뷰 토글
    @IBAction func backgroundTapGesture(_ sender: UITapGestureRecognizer) {
        // 키보드 올라와 있는 상태 -> 키보드 내리기
        // 키보드 내려가 있는 상태 -> 상단 뷰 토글
        
        // 현재 키보드가 올라와있는지에 대한 변수가 필요하다 -> isEditing
        if (mainTextField.isEditing) {
            view.endEditing(true)
        }
        else {
            upperView.isHidden.toggle()
        }
        
    }
    
    
    // 텍스트 컬러 버튼 누르면 색깔 랜덤으로 변경 -> textfield, 버튼, 레이블
    @IBAction func colorButtonTapped(_ sender: UIButton) {
        
        // drand48() : [0.0, 1.0) 사이의 값을 반환
        let rRed = CGFloat(drand48())
        let rGreen = CGFloat(drand48())
        let rBlue = CGFloat(drand48())
        
        let setColor = UIColor(red: rRed, green: rGreen, blue: rBlue, alpha: 1.0)
        
        mainTextField.textColor = setColor
        textColorButton.tintColor = setColor
        mainLabel.textColor = setColor
    }
}

Newly Coined Word Search

//
//  NewlyCoinedWord2ViewController.swift
//  0724hw
//
//  Created by 임승섭 on 2023/07/24.
//

import UIKit

class NewlyCoinedWord2ViewController: UIViewController {
    
    var wordDict = [
        "뉴진스" : "새 청바지",
        "알잘딱깔센" : "알아서 잘 딱 깔끔하게 센스있게",
        "별다줄" :"별걸 다 줄인다",
        "억텐" : "억지 텐션의 줄임말. 억지로 텐션을 올려서 발랄하게 행동할 때",
        "스불재" : "스스로 불러온 배앙의 줄임말. 자신이 계획한 일로 자신이 고통을 받을 때 씀",
        "좋댓구알" : "좋아요, 댓글, 구독, 알림 설정",
        "어쩔티비" : "어쩌라고 가서 티비나 봐",
        "갓생" : "갓(God) + 생. 부지런하고 열심히 사는 사람에게 쓰는 말",
        "점메추" : "점심 메뉴 추천"
    ]
    
    
    @IBOutlet var searchTextField: UITextField!
    @IBOutlet var searchButton: UIButton!
    
    @IBOutlet var tagButton1: UIButton!
    @IBOutlet var tagButton2: UIButton!
    @IBOutlet var tagButton3: UIButton!
    @IBOutlet var tagButton4: UIButton!
    
    
    
    @IBOutlet var meaningLabel: UILabel!
    @IBOutlet var backgroundImage: UIImageView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        backgroundImage.image = UIImage(named: "word_logo")
        backgroundImage.contentMode = .scaleAspectFill

        
        // 디자인
        designSearchTextField(searchTextField)
        designTagButton(tagButton1, "뉴진스")
        designTagButton(tagButton2, "알잘딱깔센")
        designTagButton(tagButton3, "별다줄")
        designTagButton(tagButton4, "억텐")
        designSearchButton(searchButton)
        designMeaningLabel(meaningLabel)
       
    }
    
    
    /* ==== 초기 디자인 함수 ==== */
    // search textfield 디자인
    func designSearchTextField(_ field: UITextField) {
        field.placeholder = "신조어를 입력하세요"
        field.layer.borderColor = UIColor.black.cgColor
        field.layer.borderWidth = 2
    }
    
    // search button 디자인
    func designSearchButton(_ button: UIButton) {
        button.setImage(UIImage(systemName: "pencil"), for: .normal)
        button.tintColor = .white
        button.backgroundColor = .black
        button.layer.borderColor = UIColor.black.cgColor
        button.layer.borderWidth = 2
        button.setTitle(nil, for: .normal)
    }
    
    // tag button 디자인
    func designTagButton(_ button: UIButton, _ name: String) {
        
        button.layer.cornerRadius = 10
        button.layer.borderColor = UIColor.black.cgColor
        button.layer.borderWidth = 1
        button.setTitle(name, for: .normal)
        button.setTitleColor(.black, for: .normal)
    }
    
    // meaning label 디자인
    func designMeaningLabel(_ label: UILabel) {
        label.textAlignment = .center
        label.numberOfLines = 0
    }
    
    
    /* ==== 기능 함수 ==== */
    // tag 버튼에 쓰인 단어 랜덤으로 재분베
    func randomTagButton() {
        
        // 딕셔너리에서 단어만 랜덤으로 4개 꺼낸다 (겹치지 않게)
        let keys = wordDict.keys    // 바로 배열 타입이 아닌 것 같아서 하나씩 꺼내서 append해준다
        var randomKeys: [String] = []
        
        for i in keys {
            randomKeys.append(i)
        }
        randomKeys.shuffle()    // 누를 때마다 서로 다른 단어가 조합될 수 있도록 shuffle 해준다
        
        // 버튼 텍스트 교체
        tagButton1.setTitle(randomKeys[0], for: .normal)
        tagButton2.setTitle(randomKeys[1], for: .normal)
        tagButton3.setTitle(randomKeys[2], for: .normal)
        tagButton4.setTitle(randomKeys[3], for: .normal)
    }
    
    // 올바르지 않은 단어가 입력되었을 때 alert 팝업 창
    func showAlert(title: String, message: String) {
        
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        
        let cancel = UIAlertAction(title: "취소", style: .cancel)
        let ok = UIAlertAction(title: "확인", style: .default)
        
        alert.addAction(cancel)
        alert.addAction(ok)
        
        present(alert, animated: true)
        
        backgroundImage.image = UIImage(named: "word_logo")
        meaningLabel.text = ""
    }
    
    // textfield에 있는 단어를 토대로 뜻을 출력. 뜻이 없다면 팝업창
    func showMeaning() {
        // 0. image 변경
        backgroundImage.image = UIImage(named: "background")
        
        
        // 1. textfield에 있는 걸 읽는다 (Optional)
        let txt = searchTextField.text
        
        // 2. optional binding
        if let txt {
            
            // 3. 한 글자이거나 빈칸이면 바로 탈락
            if txt.count <= 1 {
                showAlert(title: "글자 수가 부족합니다", message: "다시 입력해주세요")
                
            }
            
            else {
                // 4. 딕셔너리에서 찾는다
                let meaning = wordDict[txt]
                
                // 5 - 1. 딕셔너리에 있으면 화면에 출력
                if meaning != nil {
                    meaningLabel.text = meaning
                }
                
                // 5 - 2. 없으면 탈락
                else {
                    showAlert(title: "뜻이 없는 단어입니다", message: "다시 입력해주세요")
                    
                }
                
                
            }
        }
    }
    
    
    // return 버튼
    @IBAction func keyboardReturnTapped(_ sender: UITextField) {
        showMeaning()
        randomTagButton()
    }
    
    // 검색 버튼
    @IBAction func searchButtonTapped(_ sender: UIButton) {
        showMeaning()
        randomTagButton()
    }
    
    // 배경 터치
    @IBAction func tapGesture(_ sender: UITapGestureRecognizer) {
        view.endEditing(true)
    }
    
    // 태그 버튼
    @IBAction func tagButtonTapped(_ sender: UIButton) {
        // 1. textfield에 적히게
        searchTextField.text = sender.currentTitle
        
        // 2. 그대로 검색 (showMeaning)
        showMeaning()
        
        // 3. 랜덤 태그버튼
        randomTagButton()
    }
    
    
}

Emotion Count

//
//  EmotionCountViewController.swift
//  0725hw
//
//  Created by 임승섭 on 2023/07/25.
//


// 7/26 update
// 1. enum 좀 더 다양하게 써보기
// 2. tag 코드로 구현
// 3. UserDefaults 손보기
// 4. reset 버튼 -> alert 띄워주기 (확인 / 취소)


import UIKit

class EmotionCountViewController: UIViewController {
    
    /* 원래 생각
     버튼들을 하나의 배열에 저장해서
     각 버튼에 접근하는 방식을 index 번호로 처리함
     index번호와 tag가 동일하기 때문에 접근이 용이함
     */
    
    
    /* 열거형 이용해보기
     버튼들을 따로 outlet으로 저장해서, 각 버튼별로
     디자인할 때 열거형에 따라 디자인되도록 함
     */
    
    // 버튼 개수를 특정지어서 5라고 안하고, 배열의 count를 계산하였다
    
    // Outlet collection으로 버튼들 가졍
    // Q. 배열에 저장되는 순서는, 스토리보드에 연결한 순서일까?
    //@IBOutlet var emotionButton: [UIButton]!
    
    
    
    // 버튼 outlet
    @IBOutlet var veryGoodButton: UIButton!
    @IBOutlet var goodButton: UIButton!
    @IBOutlet var sosoButton: UIButton!
    @IBOutlet var badButton: UIButton!
    @IBOutlet var veryBadButton: UIButton!
    

    @IBOutlet var pullDownButton3: UIBarButtonItem!
    
    // 몇 점씩 올릴지 변수
    var m = 1;
    
    
    // 각 버튼의 터치 횟수 (카운트 수)
    var countNum = [0, 0, 0, 0, 0]
    let names = ["완전행복지수", "적당미소지수", "그냥그냥지수", "좀속상한지수", "많이슬픈지수"]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // countNum 초기화
        for i in 0...4 {
            countNum[i] = 0
            UserDefaults.standard.set(countNum[i], forKey: names[i])
        }

        designButton(veryGoodButton, Emotion(rawValue: 0)!)
        designButton(goodButton, Emotion(rawValue: 1)!)
        designButton(sosoButton, Emotion(rawValue: 2)!)
        designButton(badButton, Emotion(rawValue: 3)!)
        designButton(veryBadButton, Emotion(rawValue: 4)!)
        
        designPullDownButton(pullDownButton3)
    }
    
    // 버튼 디자인
    func designButton(_ sender: UIButton, _ emoji: Emotion) {
        
        // (0726) tag 지정
        sender.tag = emoji.rawValue
        
        switch emoji {
        case .veryGood:
            sender.setImage(UIImage(named: "emoji1"), for: .normal)
            sender.backgroundColor = .systemPink
        case .good:
            sender.setImage(UIImage(named: "emoji2"), for: .normal)
            sender.backgroundColor = .systemOrange
        case .soso:
            sender.setImage(UIImage(named: "emoji3"), for: .normal)
            sender.backgroundColor = .systemYellow
        case .bad:
            sender.setImage(UIImage(named: "emoji4"), for: .normal)
            sender.backgroundColor = .systemCyan
        case .veryBad:
            sender.setImage(UIImage(named: "emoji5"), for: .normal)
            sender.backgroundColor = .systemBlue
        // default 구문 필요 없다
        }
    }
    
    // pull down button 디자인
    func designPullDownButton(_ sender: UIBarButtonItem) {
        sender.image  = UIImage(systemName: "pencil.circle")
        
        let mul1 = UIAction(title: "x 1", handler: {_ in self.m = 1})
        let mul5 = UIAction(title: "x 5", handler: {_ in self.m = 5})
        let mul10 = UIAction(title: "x 10", handler: {_ in self.m = 10})
        
        
        let buttonMenu = UIMenu(title: "점수를 선택하세요", children: [mul1, mul5, mul10])
        
        sender.menu = buttonMenu
    }
    
    
    
    
    @IBAction func emotionButtonTapped(_ sender: UIButton) {
        countNum[sender.tag] += m
        
        UserDefaults.standard.set(countNum[sender.tag], forKey: names[sender.tag])
        
        
        print("현재 감정(\(sender.tag)) 터치 횟수 : \(countNum[sender.tag])")
    }
    
    

    // 시간 걸리는 중
    // pull down button 구현중인데, 그냥 바깥에다가 둘 때는 정상적으로 작동
    // navigation bar 안에 넣어서 UIBarButtonItem이 되면 작동하지가 않는다
    
    // UIButton을 Navigation bar 안에 넣으면 UIBarButtonItem이 되는데
    // 그냥 UIButton으로 했을 때와 어떤 차이가 있는지
    
    // Navigation bar 안에 버튼을 넣을 땐 반드시 UIBarButton으로 넣어줘야 한다!!!
    
    
    // (0726) reset Button alert
    @IBAction func resetButtonTapped(_ sender: UIBarButtonItem) {
        
        // 1. 내용

        let alert = UIAlertController(title: "버튼 횟수를 모두 초기화하시겠습니까?", message: "count는 (x 1)로 초기화됩니다", preferredStyle: .alert)
        
        // 2. 취소 / 확인
        let cancel = UIAlertAction(title: "취소", style: .cancel)
        let ok = UIAlertAction(title: "확인", style: .default) { _ in
            self.m = 1
            for i in 0...4 {
                self.countNum[i] = 0
                UserDefaults.standard.set(self.countNum[i], forKey: self.names[i])
            }
        }
        
        // 3. 연결
        alert.addAction(cancel)
        alert.addAction(ok)
        
        // 4. 띄우기
        present(alert, animated: true)
    }
}
//
//  EmotionResultViewController.swift
//  0725hw
//
//  Created by 임승섭 on 2023/07/25.
//

import UIKit

class EmotionResultViewController: UIViewController {

    // view와 감정 이름 레이블은 굳이 enum을 쓸 필요가 없고, 디자인만 할 거라서 outlet collection으로 저장한다
    
    @IBOutlet var resultViews: [UIView]!
    @IBOutlet var nameLabels: [UILabel]!
    

    @IBOutlet var emojiPoints: [UILabel]!
    
    let names = ["완전행복지수", "적당미소지수", "그냥그냥지수", "좀속상한지수", "많이슬픈지수"]
    override func viewDidLoad() {
        super.viewDidLoad()

        for i in 0...resultViews.count-1 {
            designView(resultViews[i], i)
            nameLabels[i].text = names[i]
            nameLabels[i].textColor = .white
            
            emojiPoints[i].text = "\(UserDefaults.standard.integer(forKey: "\(names[i])")) 점"
            emojiPoints[i].textColor = .white
            emojiPoints[i].font = UIFont.systemFont(ofSize: 30)
        }
    }
    
    
    // 탭을 왔다갔다 할 때 viewDidLoad가 계속 실행되는 건 아니기 때문에
    // viewWillAppear가 실행될 때 점수 업데이트를 해준다
    override func viewWillAppear(_ animated: Bool) {
        
        for i in 0...resultViews.count-1 {
            emojiPoints[i].text = "\(UserDefaults.standard.integer(forKey: "\(names[i])")) 점"
        }
    }
    
    func designView(_ sender: UIView, _ index: Int) {
        sender.layer.cornerRadius = 10
        switch index {
        case 0:
            sender.backgroundColor = .systemPink
        case 1:
            sender.backgroundColor = .systemOrange
        case 2:
            sender.backgroundColor = .systemYellow
        case 3:
            sender.backgroundColor = .systemCyan
        case 4:
            sender.backgroundColor = .systemBlue
        default:
            break
        }
    }
}

Sign Up Page

//
//  SignUpViewController.swift
//  0726hw
//
//  Created by 임승섭 on 2023/07/26.
//

// 1. textfield들 열거형으로 구분하기
// 2. 모든 textfield들이 작성되어 있어야 다른 화면으로 넘어갈 수 있도록 하기.
//    다 채워져야 버튼 색이 변하게끔 -> 이건 못하겠다. 어디서 함수가 계속 실행되는지 모르겠음
//    만약 하나라도 없으면 alert -> alert title도 열거형으로 구분
// -> 다음 화면으로 넘어가는 걸 코드로 배우지 않아서 이거 못한다. 따로 확인하는 버튼을 만들어보자
// 3. datepicker로 본인 생일 선택할 수 있도록 하기
// 4. 모든 값을 UserDefaults로 저장해서 다음 화면에서 확인할 수 있도록 하기

import UIKit

class SignUpViewController: UIViewController {
    
    let mine = UserDefaults.standard
    let format = DateFormatter()
    
    
    @IBOutlet var mainLabel: UILabel!
    
    @IBOutlet var idLabel: UILabel!
    @IBOutlet var passwordLabel: UILabel!
    @IBOutlet var passwordConfirmLabel: UILabel!
    @IBOutlet var nicknameLabel: UILabel!
    @IBOutlet var birthdayLabel: UILabel!
    
    @IBOutlet var idTextField: UITextField!
    @IBOutlet var passwordTextField: UITextField!
    @IBOutlet var passwordConfirmTextField: UITextField!
    @IBOutlet var nicknameTextField: UITextField!
    
    @IBOutlet var birthdayPicker: UIDatePicker!
    
    @IBOutlet var confirmButton: UIButton!
    @IBOutlet var nextButton: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        
        // 메인 레이블 디자인
        mainLabel.text = "회원가입"
        mainLabel.textColor = .black
        mainLabel.font = UIFont.boldSystemFont(ofSize: 30)
        
        // 서브 레이블 디자인
        designSubLabel(idLabel, .id)
        designSubLabel(passwordLabel, .password)
        designSubLabel(passwordConfirmLabel, .confirmpassword)
        designSubLabel(nicknameLabel, .nickname)
        designSubLabel(birthdayLabel, .birthday)
        
        // 텍스트필드 디자인
        designTextField(idTextField, .id)
        designTextField(passwordTextField, .password)
        designTextField(passwordConfirmTextField, .confirmpassword)
        designTextField(nicknameTextField, .nickname)
        
        // 데이트피커 디자인
        birthdayPicker.preferredDatePickerStyle = .compact
        birthdayPicker.datePickerMode = .date
        
        // 확인 버튼 디자인
        confirmButton.setTitle("확인", for: .normal)
        confirmButton.backgroundColor = .systemPink
        confirmButton.tintColor = .white
        confirmButton.layer.cornerRadius = 10
        
        // 다음으로 버튼 디자인
        nextButton.setTitle("다음으로", for: .normal)
        nextButton.backgroundColor = .systemGray5
        nextButton.tintColor = .darkGray
        nextButton.layer.cornerRadius = 10
        
    }
    
    // 서브 레이블 디자인 함수
    func designSubLabel(_ sender: UILabel, _ type: Sign) {
        // 공통
        sender.textColor = .gray
        sender.font = UIFont.systemFont(ofSize: 12)
        
        // switch
        switch type {
        case .id :
            sender.text = "아이디"
        case .password :
            sender.text = "비밀번호"
        case .confirmpassword :
            sender.text = "비밀번호 확인"
        case .nickname :
            sender.text = "닉네임"
        case .birthday :
            sender.text = "생년월일"
        }
    }
    
    // 텍스트필드 디자인 함수
    func designTextField(_ sender: UITextField, _ type: Sign) {
        
        // 공통
        sender.backgroundColor = .systemGray6
        sender.layer.cornerRadius = 10
        sender.borderStyle = .none
        // textfield padding 넣어주기?
        sender.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 40))
        sender.leftViewMode = .always
        
        sender.tag = type.rawValue
        
        
        // switch -> placeholder
        switch type {
        case .id :
            sender.placeholder = "사용할 아이디를 입력하세요"
            sender.textContentType = .emailAddress
        case .password :
            sender.placeholder = "사용할 비밀번호를 입력하세요"
            sender.textContentType = .password
            sender.isSecureTextEntry = true
        case .confirmpassword :
            sender.placeholder = "비밀번호를 다시 한 번 입력하세요"
            sender.textContentType = .password
            sender.isSecureTextEntry = true
        case .nickname :
            sender.placeholder = "사용할 닉네임을 입력하세요"
            sender.textContentType = .nickname
        default :
            break;
        }
    }
    
    // 다음으로 넘어갈 수 있는 상태인지 확인
    func checkNextPage() -> Bool {
        if let t1 = idTextField.text, let t2 = passwordTextField.text,
           let t3 = passwordConfirmTextField.text, let t4 = nicknameTextField.text {
            if (!t1.isEmpty && !t2.isEmpty && !t3.isEmpty && !t4.isEmpty) &&
                (t2 == t3) {
                return true
            }
        }
        
        return false
    }
    
    
    // confirm button tapped
    @IBAction func confirmButtonTapped(_ sender: UIButton) {
        // 확인 조건
        // 1. textfield가 비어있으면 탈락
        // 2. 비밀번호랑 비밀번호 확인이 다르면 탈락
        // 3. 1, 2 아니면 통과
        
        var title: String = ""
        var message: String = ""
        
        if let t1 = idTextField.text, let t2 = passwordTextField.text,
           let t3 = passwordConfirmTextField.text, let t4 = nicknameTextField.text {
            
            if (t1.isEmpty) {
                title = "아이디를 입력하세요"
            }
            else if (t2.isEmpty) {
                title = "비밀번호를 입력하세요"
            }
            else if (t3.isEmpty) {
                title = "비밀번호 확인을 입력하세요"
            }
            else if (t4.isEmpty) {
                title = "닉네임을 입력하세요"
            }
            else if (t2 != t3) {
                title = "비밀번호가 일치하지 않습니다"
            }
            else {
                title = "모든 입력이 완료되었습니다"
                message = "다음으로 버튼을 눌러주세에요"
            }
        }

        // 1. 내용
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        // 2. 확인
        let ok = UIAlertAction(title: "확인", style: .default)
        // 3. 연결
        alert.addAction(ok)
        // 4. 띄우기
        present(alert, animated: true)
    }
    
    // next button tapped
    @IBAction func nextButtonTapped(_ sender: UIButton) {
        
        format.dateFormat = "yyyy년 M월 dd일"
        
        mine.set(idTextField.text, forKey: "id")
        mine.set(passwordTextField.text, forKey: "pw")
        mine.set(nicknameTextField.text, forKey: "nickname")
        mine.set(format.string(from: birthdayPicker.date), forKey: "birthday")
    }
    
    
    @IBAction func datePickerTapped(_ sender: UIDatePicker) {
        
    }
    
    
    // tap gesture
    @IBAction func tapgestureTapped(_ sender: UITapGestureRecognizer) {
        view.endEditing(true)
    }
    
    
    // 주의 : 여기서 땡겨서 스토리보드랑 연결할 때, Did End On Exit은 하나만 먹는다
    // Editing Changed로 입력하는 도중에 다음으로 버튼 색 바꿀 수도 있을 것 같은데
    // -> 찾아보자
    // 키보드의 return키를 누르면, 포커스가 다음 입력창으로 넘어가게 할 수 없을까
    @IBAction func returnKeyTapped(_ sender: UITextField) {
        switch sender.tag {
        case 0 :
            passwordTextField.becomeFirstResponder()
        case 1 :
            passwordConfirmTextField.becomeFirstResponder()
        case 2  :
            nicknameTextField.becomeFirstResponder()
        case 3 :
            view.endEditing(true)
        default :
            break;
        }
        
        
    }
    
    
    // 모든 입력이 완료되면 버튼 색이 변하게 설정
    // -> 이제 실제 버튼이 안눌리게도 하는 방법 찾아보자
    @IBAction func EditingIdTextfield(_ sender: UITextField) {
        if (checkNextPage()) {
            nextButton.tintColor = .white
            nextButton.backgroundColor = .systemPink
        }
        else {
            nextButton.tintColor = .darkGray
            nextButton.backgroundColor = .systemGray5
        }
    }
    
    
    
    // 7/27
    @IBAction func countButtonTapped(_ sender: UIButton) {
        
        let cnt = UserDefaults.standard.integer(forKey: "count")
        let result = cnt + 1
        UserDefaults.standard.set(result, forKey: "count")
    }
    
}
//
//  ResultViewController.swift
//  0726hw
//
//  Created by 임승섭 on 2023/07/26.
//

import UIKit

class ResultViewController: UIViewController {

    let mine = UserDefaults.standard
    
    
    
    @IBOutlet var mainLabel: UILabel!
    
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        

        let id = mine.string(forKey: "id")
        let pw = mine.string(forKey: "pw")
        let nickname = mine.string(forKey: "nickname")
        let birthday = mine.string(forKey: "birthday")
        
        mainLabel.numberOfLines = 0
        
        if let id, let pw, let nickname, let birthday {
            mainLabel.text = "아이디 : \(id) \n비밀번호 : \(pw) \n닉네임 : \(nickname) \n생일 : \(birthday)"
        }
        else {
            mainLabel.text = "에러입니당"
        }
        
    }
}

Shopping List

//
//  ShoppingTableViewController.swift
//  0727hw
//
//  Created by 임승섭 on 2023/07/27.
//

import UIKit

// extension으로 textfield 시작하는 부분에 padding 넣어주는 함수 추가하기
extension UITextField {
    
  func addLeftPadding() {
    let paddingView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: self.frame.height))
    self.leftView = paddingView
    self.leftViewMode = ViewMode.always
  }
}



class ShoppingTableViewController: UITableViewController {
    
    
    /* 텍스트필드에 입력 후 추가 버튼을 누르면 cell이 추가되는 페이지*/
    // 1. 텍스트필드에 제대로 입력되었는지 확인 -> nil이거나 빈글자는 x
    // 2. pull down 버튼을 넣어서 섹션을 구분해볼까
        // 2 - 1. 섹션도 계속 추가하는건 어려우니까 섹션은 고정시켜두자
        // 2 - 2. 선택한 섹션이 레이블로 떠있게 해주기
    // 3. 섹션 별 cell들을 배열로 저장 -> 총 하나의 dictionary로 관리
    // 4. 가장 최근에 추가한게 맨 위에 뜨게 하기
        // 4 - 1. 배열의 맨 앞에 추가하기 (insert?)
    
    
    // pull down button
    // textlabel에 현재 선택된 type 띄우고, 오른쪽에 아래화살표 이미지
    // 누르면 pull down으로 옵션 선택할 수 있게
    @IBOutlet var pulldownButton: UIButton!
    @IBOutlet var shoppingTextField: UITextField!
    @IBOutlet var addButton: UIButton!
    
    @IBOutlet var searchView: UIView!
    
    
    
    // 현재 선택된 옵션 -> 선언만 해두고 초기값은 viewDidLoad에서 typeList[0]로 잡아주자
    // 려고 했는데 저장속성 초기화 안하면 안되니까 그냥 "일반"으로 해주자
    var option: String = "일반"
    
    
    // 현재 저장된 값들 -> 딕셔너리
    var shoppingDict: [String: [String]]
        = ["일반" : [], "음식" : [], "옷" : [] ]
    // 타입 -> 배열
    let typeList = ["일반", "음식", "옷"]

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 디자인
        searchView.backgroundColor = .systemGray5
        searchView.layer.cornerRadius = 10
        
        pulldownButton.setImage(UIImage(systemName: "chevron.down"), for: .normal)
        pulldownButton.semanticContentAttribute = .forceRightToLeft
        pulldownButton.tintColor = .black
        
        shoppingTextField.backgroundColor = .systemGray5
        shoppingTextField.placeholder = "추가할 항목을 입력하세요"
        shoppingTextField.borderStyle = .none
        shoppingTextField.addLeftPadding()
        
        addButton.tintColor = .black
        addButton.layer.cornerRadius = 10
        addButton.layer.backgroundColor = UIColor.systemGray4.cgColor

        
        // 초기 옵션
        option = typeList[0]
        
        // pull down button
        designPullDownButton(pulldownButton)
    }
    
    // 섹션의 개수
    override func numberOfSections(in tableView: UITableView) -> Int {
        return shoppingDict.keys.count
    }
    
    // 섹션의 헤더 이름
    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        
        return typeList[section]
    }
    
    // 1. 셀의 개수
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // 배열에서 먼저 찾고, dictionary에서 찾기
        return shoppingDict[typeList[section]]!.count
    }
    
    // 2. 셀 디자인 및 데이터 처리
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "shoppingPage")!
        // 먼저 섹션의 이름을 찾고,
        let t = typeList[indexPath.section]
        // 해당 섹션에 해당하는 배열의 요소를 찾는다
        cell.textLabel?.text = shoppingDict[t]![indexPath.row]
        
        return cell
    }
    
    
    
    // pull down button design
    func designPullDownButton(_ sender: UIButton) {
        
        // 현재 선택된 옵션을 레이블에 띄워준다
        sender.setTitle(option, for: .normal)
        
        
        let op1 = UIAction(title: "일반") { _ in
            self.option = self.typeList[0]
            sender.setTitle(self.option, for: .normal)  // 선택하자마자 바로 업데이트되도록
        }
        let op2 = UIAction(title: "음식") { _ in
            self.option = self.typeList[1]
            sender.setTitle(self.option, for: .normal)
        }
        let op3 = UIAction(title: "옷") { _ in
            self.option = self.typeList[2]
            sender.setTitle(self.option, for: .normal)
        }
        let buttonMenu = UIMenu(title: "옵션을 선택하세요", children: [op1, op2, op3])
        
        sender.menu = buttonMenu
    }
    
    
    // textField에 잘 써있는지 확인
    func checkTextField(_ sender: UITextField) -> Bool {
        if let txt = sender.text {
            if txt.count >= 1 {
                return true
            }
        }
        
        // nil이거나 count가 0이면 false를 리턴한다
        return false
    }
    
    // return / 추가 버튼 클릭 시 실행
    func updateList() {
        // 1. 텍스트필드에 정상적으로 써있는지 확인
        if (checkTextField(shoppingTextField)) {
            let txt = shoppingTextField.text!   // 함수 통과했으니까 강제 언래핑 해주기
            
            // 2. 현재 선택된 옵션에 해당하는 배열에 추가해주기. 추가할 때 맨 앞에 추가 - insert 사용
            shoppingDict[option]?.insert(txt, at: 0)
            
            // 3. 화면 다시 로드
            tableView.reloadData()
            
            // 4. textfield 초기화
            shoppingTextField.text = ""
            
        }
        // 1 - 1. 텍스트필드 제대로 쓰라고 alert
        else {
            let alert = UIAlertController(title: "텍스트가 올바르지 않습니다", message: "다시 써주세요", preferredStyle: .alert)
            let ok = UIAlertAction(title: "확인", style: .default)
            alert.addAction(ok)
            present(alert, animated: true)
        }
    }
    
    
    // 기본 설정
    // return 키 눌렀을 때 추가 버튼과 동일하게 동작 / 키보드 내려가기
    // 배경 터치 시 키보드 내려가기
    
    /* IBAction */
    // 추가 버튼 클릭
    @IBAction func addButtonTapped(_ sender: UIButton) {
        updateList()
    }
    
    // 리턴 버튼 클릭
    @IBAction func returnKeyTapped(_ sender: UITextField) {
        updateList()
    }
    
    
    // tap gesture 올릴 때 view controller랑 다르다 -> 기능도 다른게 있는지 확인하기
    @IBAction func tapGesture(_ sender: UITapGestureRecognizer) {
        view.endEditing(true)
    }
    
    // cell에 tapgesture을 얹으면 맨 위에 있는 Cell에만 적용된다
    // table view의 scroll view의 keyboard dismiss on drag
    @IBAction func tapGestuerCell(_ sender: UITapGestureRecognizer) {
        view.endEditing(true)
    }

    
    
    // 시간 씀
    // pull down button 말고 그냥 button으로 추가해줬을 땐 옵션들이 안나왔는데
    // pull down button으로 땡겨오니까 정상적으로 나옴
}

MovieList / LikeMovieList

업로드중..

//
//  MovieListTableViewController.swift
//  0728hw
//
//  Created by 임승섭 on 2023/07/28.
//

import UIKit


// 과제 +
// 즐겨찾기 한 리스트만 따로 보게 하기
// 1. pull down button (1. 전체 / 2. 즐겨찾기)
// 2. cell의 우측 상단에 별 버튼
//      2 - 1. 선택하면 즐겨찾기 배열에 추가 -> index로 할 지?
//      2 - 2. 취소하면 즐겨찾기에서 제외 -> index를 어떻게 저장하냐. 딕셔너리?

// 7/29 재도전
// 1. data를 불러옴 (전역x)
// 2. 빈 배열 2개 생성 (fullList, likeList) Array<Movie>
// 3. 초기값 추가 (fullList - 전체 / likeLise - true)
// 4. 어떤 변수를 설정하고 왔다갔다 하는 것 보다, 그냥 screenType에 따라 두 배열을 보여주는 쪽으로 하자
// 성공ㅎ




// 스크린 상태
// 전체 / 즐겨찾기
enum screenType: Int {
    case all
    case like
}


class MovieListTableViewController: UITableViewController {
    
    
    var data = MovieInfo()          // 초기 데이터 선언
    var fullList: [Movie] = []      // 전체 영화 리스트
    var likeList: [Movie] = []      // 즐겨찾기 영화 리스트
    
    var screen = screenType.all.rawValue      // 현재 스크린 상태 (초기값 = 0)
    
    @IBOutlet var pullDownButton: UIBarButtonItem!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        designPullDownButton(pullDownButton)    // pull down button 디자인
        
        
        // 전체/즐겨찾기 영화 리스트 초기화
        // fullList는 여기서 data를 통해 초기화 하고 끝
        // likeList는 앞으로 makeLikeList() 함수에서 fullList를 통해 초기화 계속 할 예정
        for i in data.movie {
            fullList.append(i)
            
            if i.like {
                likeList.append(i)
            }
        }
    }
    
    
    // 1. 셀 개수
    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return (screen == 0) ? fullList.count : likeList.count
    }
    
    // 2. 셀 데이터 및 디자인
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        // MovieListTableViewCell 클래스의 함수를 사용하기 위해 타입 캐스팅
        let cell = tableView.dequeueReusableCell(withIdentifier: MovieListTableViewCell.identifier) as! MovieListTableViewCell
        
        // 스크린에 따라 다른 배열 적용
        if ( screen == 0 ) {
            cell.designCell(fullList[indexPath.row])
            cell.likeButton.tag = indexPath.row
            cell.likeButton.addTarget(self, action: #selector(likeButtonTapped), for: .touchUpInside)
        }
        else {
            cell.designCell(likeList[indexPath.row])
            cell.likeButton.tag = indexPath.row
            cell.likeButton.addTarget(self, action: #selector(likeButtonTapped), for: .touchUpInside)
        }
        
        return cell
    }
    
    @objc
    func likeButtonTapped(_ sender: UIButton) {
        
        if (screen == 0) {
            fullList[sender.tag].like.toggle()
            makeLikeList()
            tableView.reloadData()
        }
        else {
            // 즐겨찾기 창에 나온 영화들은 일단 like가 모두 true
            // 눌렀다는 건 해제한다는 뜻
            // 해당 영화를 fullList에서 찾아서 like를 false로 바꿔주고 makeLikeList() 호출
            
            let title = likeList[sender.tag].title
            
            for i in 0...fullList.count-1 {
                if fullList[i].title == title {
                    fullList[i].like = false;
                }
            }
            
            makeLikeList()
            tableView.reloadData()
        }
    }
    
    
    
    // pull down button design
    func designPullDownButton(_ sender: UIBarButtonItem) {

        let op1 = UIAction(title: "전체") { _ in
            self.screen = screenType.all.rawValue
            self.tableView.reloadData()
        }
        let op2 = UIAction(title: "즐겨찾기") { _ in
            self.screen = screenType.like.rawValue
            self.tableView.reloadData()
        }
        
        let buttonMenu = UIMenu(title: "옵션을 선택하세요", children: [op1, op2])
        
        sender.menu = buttonMenu
    }
    
    
    // fullList에서 likeList를 추출하는 함수
    func makeLikeList() {
        likeList.removeAll()
        
        for m in fullList {
            if m.like {
                likeList.append(m)
            }
        }
    }

}
//
//  MovieListTableViewCell.swift
//  0728hw
//
//  Created by 임승섭 on 2023/07/28.
//

import UIKit

class MovieListTableViewCell: UITableViewCell {
    
    static let identifier = "MovieListTableViewCell"
    
    @IBOutlet var moviePoster: UIImageView!
    @IBOutlet var titleLabel: UILabel!
    @IBOutlet var subLabel: UILabel!
    @IBOutlet var storyLabel: UILabel!
    @IBOutlet var likeButton: UIButton!
    
    // 2. 셀 데이터 및 디자인
    func designCell(_ row: Movie) {
        
        // (1). 이미지
        moviePoster.image = UIImage(named: row.title)
        
        // (2). 제목
        titleLabel.text = row.title
        titleLabel.font = .boldSystemFont(ofSize: 20)
        
        // (3). 부가 정보
        subLabel.text = "\(row.releaseDate) | \(row.runtime)분 | \(row.rate)점"
        subLabel.font = .systemFont(ofSize: 17)
        
        // (4). 줄거리
        storyLabel.text = row.overview
        storyLabel.numberOfLines = 5
        storyLabel.font = .systemFont(ofSize: 13)
        
        // (5). 버튼
        likeButton.setImage(UIImage(systemName:
                                        (row.like) ? "star.fill" : "star"), for: .normal)
    }
}

1개의 댓글

comment-user-thumbnail
2024년 6월 4일

와 어케 검색만 하면 승섭님 블로그가 일케 마니 나와요?
미춌따

답글 달기