원.밥.영 어플 프로젝트 3차

  • 테스트 기능을 추가하는 것이 목표로 하였다.
  • 테스트 기능
    • TisprCardStack 라이브러리를 사용하여 카드 형식의 문제를 보여준다.
    • 문제는 영어, 한글이 랜덤으로 출제된다.
    • 답은 4가지 종류로 구성되어 있고 터치하여 선택한다.
    • CRToast 라이브러리를 사용하여 선택한 답이 맞으면 초록색 Toast창을, 틀리면 빨간색 Toast창을 띄운다.
  • 문제는 sentence.json에 입력해놓은 문제들을 사용하였다.

Model 구현

Question.swift

// 문제는 두개의 상태를 가진다. 영어 문제와 한글 문제.
enum TestStatus {
    case englishQuestion
    case koreanQuestion
}

class Question {
    var text: String = ""
    var answerList: [String] = ["", "", "", ""]
    var realAnswerIndex: Int = 0
    
    init(status: TestStatus) {
	  // 랜덤으로 Sentence 모델 문제를 정한다. 
        guard let questionSentence = Sentence.random() else {
            return
        }
        // 정답 문장의 Index를 정한다.
        self.realAnswerIndex = Int(arc4random() % 4)
        
        switch. status {
        case .englishQuestion:
            self.text = questionSentence.english
                // 0~3번째 까지의 답 문장을 random으로 정한다.
            for index in 0..<4 {
                repeat {
                    let sentence = Sentence.random()!
                        // 영어 문제이므로 답 문장들은 한글로 설정한다.
                        // 답 문장이 정답 문장과 겹칠 경우 다시 random하게 sentence를 정한다.
                    self.answerList[index] = sentence.korean
                } while self.answerList[index] == questionSentence.korean
            } 
            // 정해놓은 정답 index에 정답을 덮어쓴다.
            self.answerList[self.realAnswerIndex] = questionSentence.korean
        case .koreanQuestion:
            self.text = questionSentence.korean
            for index in 0..<4 {
                repeat {
                    let sentence = Sentence.random()!
                    self.answerList[index] = sentence.english
                } while self.answerList[index] == questionSentence.english
            }
            self.answerList[self.realAnswerIndex] = questionSentence.english
        }
    }
}

Cell 구현

CardCell.swift

class CardCell: TisprCardStackViewCell {
    @IBOutlet var questionLabel: UILabel!
    @IBOutlet var answer1Button: UIButton!
    @IBOutlet var answer2Button: UIButton!
    @IBOutlet var answer3Button: UIButton!
    @IBOutlet var answer4Button: UIButton!
    
    var question: Question!
    
    var block: (() -> Void)?
        
    override func awakeFromNib() {
        super.awakeFromNib()
        // 카드 모양 설정
        layer.cornerRadius = 12
        layer.shadowColor = UIColor.black.cgColor
        layer.shadowOpacity = 0.2
        layer.shadowOffset = CGSize(width: 0, height: 4)
        layer.shadowRadius = 5
        clipsToBounds = false
    }
        
    override internal func apply(_ layoutAttributes: UICollectionViewLayoutAttributes) {
        super.apply(layoutAttributes)
    }
        
    func setQuestion(question: Question, index: Int) {
        self.question = question
        questionLabel.text = "문제 \(index).\n\"\(question.text)\"의 뜻은?"
        answer1Button.setTitle("1. \(question.answerList[0])", for: .normal)
        answer2Button.setTitle("2. \(question.answerList[1])", for: .normal)
        answer3Button.setTitle("3. \(question.answerList[2])", for: .normal)
        answer4Button.setTitle("4. \(question.answerList[3])", for: .normal)
    }
    // 답을 선택했을 때 실행되는 함수
    @IBAction func selectAnswer(sender: UIButton) {
        if sender.tag == question.realAnswerIndex {
        CRToastManager.showNotification(options: [
            kCRToastTextKey: "정답!",
            kCRToastBackgroundColorKey: UIColor.green,
            kCRToastTextColorKey: UIColor.black,
            kCRToastTimeIntervalKey: 0.2,
            kCRToastNotificationTypeKey: CRToastType.navigationBar.rawValue,
            kCRToastFontKey: UIFont.boldSystemFont(ofSize: 24)
        ], completionBlock: nil)
        } else {
        CRToastManager.showNotification(options: [
            kCRToastTextKey: "틀렸습니다..",
            kCRToastBackgroundColorKey: UIColor.red,
            kCRToastTimeIntervalKey: 0.2,
            kCRToastNotificationTypeKey: CRToastType.navigationBar.rawValue,
            kCRToastFontKey: UIFont.boldSystemFont(ofSize: 24)
        ], completionBlock: nil)
        }
        self.block?()
    }
}

Controller 구현

TestViewController.swift

class TestViewController: TisprCardStackViewController, TisprCardStackViewControllerDelegate {
    var questions: [Question] = []
        
    override func viewDidLoad() {
        super.viewDidLoad()
        // 카드 라이브러리 설정
        setAnimationSpeed(0.85)
            
        let size = CGSize(width: view.bounds.width - 40, height: 2 * view.bounds.height / 3)
        setCardSize(size)
        
        cardStackDelegate = self
        layout.topStackMaximumSize = 4
        layout.bottomStackMaximumSize = 30
        layout.bottomStackCardHeight = 45
        // 미리 100개정도의 문제 생성
        for _ in 0..<100 {
            if Int(arc4random() % 2) == 0 {
                questions.append(Question(status: .englishQuestion))
            } else {
                questions.append(Question(status: .koreanQuestion))
            }
        }
    }
        
    override func numberOfCards() -> Int {
        return 100
    }
    
    override func card(_ collectionView: UICollectionView, cardForItemAtIndexPath indexPath: IndexPath) -> TisprCardStackViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CardCell", for: indexPath) as! CardCell
        
        cell.setQuestion(question: questions[indexPath.row], index: indexPath.row + 1)
        cell.block = {
            self.moveCardDown()
        }
        return cell
    }

    @objc func cardDidChangeState(_ cardIndex: Int) {
    }
}

결과

Image Image Image


Choi Hyowon

열심히 공부 중 입니다.