본문 바로가기
IT/swift

100 days of SwiftUI - Day29, 30

by 가능성1g 2024. 11. 25.
반응형

이번엔 영단어 만들기.. 한국어로 하는걸로 바꾸고 싶었지만.. 지금은 실력이 부족해서 패스!

 

//
//  ContentView.swift
//  WordScramble
//
//  Created by HanTJ on 11/25/24.
//

import SwiftUI

struct ContentView: View {
    
    @State private var usedWords = [String]()
    @State private var rootWord = ""
    @State private var newWord = ""
    
    @State private var errorTitle = ""
    @State private var errorMessage = ""
    @State private var showingError = false
    
    var body: some View {
        NavigationStack {
            List {
                Section {
                    TextField("Enter your word", text: $newWord)
                        .textInputAutocapitalization(.never)
                }
                
                Section {
                    ForEach(usedWords, id: \.self) { word in
                        HStack {
                            //동그란거 안에 길이를 표시해주게 아이콘 만들기!
                            Image(systemName: "\(word.count).circle")
                            Text(word)
                        }
                    }
                }
            }
            .navigationTitle(rootWord)
            .onSubmit(addNewWord)  //UI내에서 엔터 치면 호출하는 함수 정의
            .onAppear(perform: startGame) //프로그램 시작시 호출되는 함수 정의
            .alert(errorTitle, isPresented: $showingError) {} message: { //OK버튼 생략 가능
                Text(errorMessage)
            }
        }
    }
    
    func addNewWord() {
        let answer = newWord.lowercased().trimmingCharacters(in: .whitespacesAndNewlines)
        
        // 남은 수가 empty 면 리턴
        guard answer.count > 0 else { return }
        
        //단어의 적정성 체크
        guard isOriginal(word: answer) else {
            wordError(title: "Word used already", message: "Be more original!")
            return
        }
        
        guard isPossible(word: answer) else {
            wordError(title: "Word not Possible", message: "You can't spell that word from '\(rootWord)'!")
            return
        }
        
        guard isReal(word: answer) else {
            wordError(title: "Word not recogized", message: "You can't just make them up, you know!")
            return
        }
        
        //기본으로 withAnimation으로 해도 동작한다!
        withAnimation {
            //가장 앞에 넣음
            usedWords.insert(answer, at: 0)
        }
        newWord = ""
    }
    
    func startGame() {
        if let startWordsURL = Bundle.main.url(forResource: "start", withExtension: "txt") {
            
            if let startWords = try? String(contentsOf: startWordsURL) {
                let allWords = startWords.components(separatedBy: "\n")
                rootWord = allWords.randomElement() ?? "silkworm"
                return
            }
        }
        //fatalError는 무조건 프로그램을 종료시킨다.
        fatalError("Could not load start.txt from bundle.")
    }
    
    //중복체크
    func isOriginal(word: String) -> Bool {
        !usedWords.contains(word)
    }
    
    //rootWord를 이용해서 만든 글자인가 체크
    func isPossible(word: String) -> Bool {
        var tempWord = rootWord
        
        for letter in word {
            if let pos = tempWord.firstIndex(of: letter) {
                tempWord.remove(at: pos)
            } else {
                return false
            }
        }
        return true
    }
    
    //맞는 단어인지 체크!(영어만 되더라..)
    func isReal(word: String) -> Bool {
        let checker = UITextChecker()
        let range = NSRange(location: 0, length: word.utf16.count)
        let misspelledRange = checker.rangeOfMisspelledWord(in: word, range: range, startingAt: 0, wrap: false, language: "en")

           return misspelledRange.location == NSNotFound
    }
    
    func wordError(title: String, message: String) {
        errorTitle = title
        errorMessage = message
        showingError = true
    }
}

#Preview {
    ContentView()
}

guard 의 실전 사용 방법. 역시 validation 체크에 좋다!

외부 텍스트 파일을 가져오는 방법 Bundle이용. 프로젝트에서는 같은 레벨에 첨부해두니 동작한다. (asset에 넣으면 안됨)

TextFiled는 항상 첫문자 대문자 켜져있다. 끄는 속성 .textInputAutocapitalization(.never)

아이콘은 Image를 이용해서 추가 가능! 시스템 아이콘을 이용한 서클 문자 추가 아이디어 좋다!

onAppear 이벤트는 최초 시작 자동호출이 필요할때 쓴다.

 

한국어로 만들려고 잠깐 8글자의 단어 리스트 만들기를 해보려고 했는데 어떻게 해야 하나 하는생각이 ㅡㅜ;

다른 방법으로 해야 할까나..

반응형