<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>lets_make_app.log</title>
        <link>https://velog.io/</link>
        <description>Hello World!</description>
        <lastBuildDate>Sat, 08 Jun 2024 15:56:33 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>lets_make_app.log</title>
            <url>https://velog.velcdn.com/images/lets_make_app/profile/fbfd3acf-f6fe-4f2f-9026-f61036feb618/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. lets_make_app.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/lets_make_app" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Udemy - BMI App]]></title>
            <link>https://velog.io/@lets_make_app/Udemy-BMI-App</link>
            <guid>https://velog.io/@lets_make_app/Udemy-BMI-App</guid>
            <pubDate>Sat, 08 Jun 2024 15:56:33 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-swift">
    @IBAction func calculatePressed(_ sender: UIButton) {
        let height = heightSlider.value
        let weight = weightSlider.value

        calculatorBrain.calculateBMI(height: height, weight: weight)

        self.performSegue(withIdentifier: &quot;goToResult&quot;, sender: self)

    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == &quot;goToResult&quot; {
            let destinationVC = segue.destination as! ResultViewController
            destinationVC.bmiValue = calculatorBrain.getBMIValue()
            destinationVC.advice = calculatorBrain.getAdvice()
            destinationVC.color = calculatorBrain.getColor()
        }
    }
</code></pre>
<p>이번 앱을 공부하면서, prepare라는 함수를 배웠다.
잘은 모르겠지만 segue가 발동이 될 때, 초기화를 진행하는 코드로 설명이 나왔다.</p>
<p>앞으로 더 활용을 해봐야 더 익숙해질 거 같다.</p>
<p>결과:</p>
<p align="center"><img src="https://velog.velcdn.com/images/lets_make_app/post/d5d7be17-a94f-46b4-bad5-46bfe46745b9/image.gif" height="100px" width="250px"></p>

<p>끝!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Udemy - Optional]]></title>
            <link>https://velog.io/@lets_make_app/Udemy-Optional</link>
            <guid>https://velog.io/@lets_make_app/Udemy-Optional</guid>
            <pubDate>Sat, 08 Jun 2024 15:32:13 GMT</pubDate>
            <description><![CDATA[<p>이번 챕터에서는 조금이나마 옵셔널에 대해 배우고 활용을 할 수 있었다.</p>
<p>예시:</p>
<pre><code class="language-swift">
struct CalculatorBrain {
    var bmi: Float?

    func getBMIValue() -&gt; String {

    let bmiTo1DecimalPlace = String(format: &quot;%.1f, bmi)
    return bmiTo1DecimalPlace

    }
}

// 이러한 코드가 있다면, 일단 bmi는 옵셔널이 되어 있기 때문에, 함수 안에 있는 bmi 언래핑 처리가 필요할 수도 있다.

1. 
struct CalculatorBrain {
    var bmi: Float?

    func getBMIValue() -&gt; String {
        if bmi != nil { // if else을 활용하여, 만약에 bmi가 nil이 아닐시
            let bmiTo1DecimalPlace = String(format: &quot;%.1f, bmi!) //!로 강제 해제
                return bmiTo1DecimalPlace
        } else { // nil일 시 아래 코드 실행
        return = &quot;0.0&quot;
    }
}

2.
struct CalculatorBrain {
    var bmi: Float?

    func getBMIValue() -&gt; String {

    if let safeBMI = bmi { //if let을 활용하여, bmi에 값이 있다면 safeBMI(Float)를 사용
        let bmiTo1DecimalPlace = String(format: &quot;%.1f, safeBMI) //언래핑이 필요 없이 safeBMI 사용
        return bmiTo1DecimalPlace
    } else { // nil일 시 아래 코드 실행
      return = &quot;0.0&quot;
    }
}

3.
struct CalculatorBrain {
    var bmi: Float?

    func getBMIValue() -&gt; String {

    // nil coalescing 활용, bmi에 값이 없다면 0.0으로 설정
    let bmiTo1DecimalPlace = String(format: &quot;%.1f, bmi ?? 0.0) 
    return bmiTo1DecimalPlace
    }
}</code></pre>
<p>이러한 방식으로 옵셔널을 활용했을 때, 언래핑을 하는 여러가지 방식을 배웠다.
아직은 옵셔널을 사용하는 것 조차 힘들지만, 앞으로의 챕터에서 더 활용해보면서 익히기로 하자.</p>
<p>끝!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Udemy - Destini App]]></title>
            <link>https://velog.io/@lets_make_app/Udemy-Destini-App</link>
            <guid>https://velog.io/@lets_make_app/Udemy-Destini-App</guid>
            <pubDate>Thu, 06 Jun 2024 22:20:15 GMT</pubDate>
            <description><![CDATA[<ol>
<li>MVC</li>
</ol>
<p>더 공부가 필요하겠지만, 이번 챕터는 MVC 디자인패턴을 조금이라도 활용해볼 수 있었다.</p>
<p>간단히 말해서,</p>
<p>Model, View, Controller 이다</p>
<p>모델(Model)</p>
<ul>
<li>모델은 애플리케이션의 데이터와 비즈니스 로직을 담당</li>
<li>데이터베이스나 네트워크를 통해 데이터를 가져오고 저장하는 역할을 하며, 데이터의 상태를 관리 </li>
<li>모델은 뷰나 컨트롤러에 의존하지 않기 때문에 재사용성이 높다</li>
</ul>
<p>예시:</p>
<pre><code class="language-swift">struct User {
    var name: String
    var age: Int
}</code></pre>
<p>뷰(View)</p>
<ul>
<li>뷰는 사용자 인터페이스 요소를 담당</li>
<li>모델의 데이터를 사용하여 화면에 표시하며, 사용자와의 상호작용을 받아들인다</li>
<li>뷰는 데이터를 표시하는 역할만 수행하고, 데이터의 변경에 대한 로직은 포함하지 않는다</li>
</ul>
<p>예시:</p>
<pre><code class="language-swift">import UIKit

class UserView: UIView {
    private var nameLabel: UILabel!
    private var ageLabel: UILabel!

    override init(frame: CGRect) {
        super.init(frame: frame)
        setupView()
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupView()
    }

    private func setupView() {
        nameLabel = UILabel()
        ageLabel = UILabel()
        // 뷰 레이아웃 설정 코드
    }

    func updateView(with user: User) {
        nameLabel.text = user.name
        ageLabel.text = &quot;\(user.age)&quot;
    }
}</code></pre>
<p>컨트롤러(Controller)</p>
<ul>
<li>컨트롤러는 모델과 뷰를 연결하는 중재자 역할</li>
<li>사용자의 입력을 받아 모델을 업데이트하고, 모델의 변화를 감지하여 뷰를 업데이트</li>
<li>컨트롤러는 애플리케이션의 흐름을 제어하며, 비즈니스 로직을 처리</li>
</ul>
<p>예시:</p>
<pre><code class="language-swift">import UIKit

class UserController: UIViewController {
    private var userView: UserView!
    private var user: User! {
        didSet {
            userView.updateView(with: user)
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        userView = UserView(frame: view.bounds)
        view.addSubview(userView)

        user = User(name: &quot;John Doe&quot;, age: 30)
    }

    func updateUser(name: String, age: Int) {
        user.name = name
        user.age = age
    }
}</code></pre>
<p>나의 실제 앱 코드:</p>
<p><img src="https://velog.velcdn.com/images/lets_make_app/post/8bf646eb-dc61-459a-945c-4804737e8a5c/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/lets_make_app/post/f9f510ab-b0de-422c-a3ea-00d2f84b6549/image.png" alt=""></p>
<p>결과:</p>
<p align="center"><img src="https://velog.velcdn.com/images/lets_make_app/post/ce5b9a51-2f9e-4387-b31b-91f99c6d05bf/image.gif" height="100px" width="250px"></p>

<p>끝!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Udemy Quizzler App]]></title>
            <link>https://velog.io/@lets_make_app/Udemy-Quizzler-App</link>
            <guid>https://velog.io/@lets_make_app/Udemy-Quizzler-App</guid>
            <pubDate>Fri, 31 May 2024 18:53:21 GMT</pubDate>
            <description><![CDATA[<p>View의 라이프사이클 (일부)</p>
<pre><code class="language-swift">import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var questionLabel: UILabel!
    @IBOutlet weak var progressBar: UIProgressView!
    @IBOutlet weak var trueButton: UIButton!
    @IBOutlet weak var falseButton: UIButton!

    let quiz = [
        &quot;Four + Two is euqal to Six.&quot;,
        &quot;Five = Three is greater than One&quot;,
        &quot;Three + Eight is less than Ten&quot;
    ]

    var questionNumber = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        updateUI()
    }


    @IBAction func answerButtonPressed(_ sender: UIButton) {
        questionNumber += 1
        updateUI() //버튼이 누린다면, 질문이 바껴야함. 그러므로 다시 호출!
    }

    func updateUI() {
        questionLabel.text = quiz[questionNumber]
    }

}</code></pre>
<p>이번 챕터를 진행하면서, if/else 그리고 dictionary 등, 여러가지 문법들을 활용할 수 있었다.</p>
<pre><code class="language-swift">
// dictionary
struct QuizBrain {
    let quiz = [
        Question(q: &quot;Which is the largest organ in the human body?&quot;,
                 a: [&quot;Heart&quot;, &quot;Skin&quot;, &quot;Large Intestine&quot;],
                 correctAnswer: &quot;Skin&quot;),
        Question(q: &quot;Five dollars is worth how many nickels?&quot;,
                 a: [&quot;25&quot;, &quot;50&quot;, &quot;100&quot;],
                 correctAnswer: &quot;100&quot;)
               ]

// 이러한 mutating을 사용한 함수
    mutating func checkAnswer(_ userAnswer: String) -&gt; Bool {
        if userAnswer == quiz[questionNumber].correctAnswer {
            score += 1
            return true
        } else {
            return false
        }

// 그리고 반환 값을 필요로 하는 함수까지
    func getQuestionText() -&gt; String {
        return quiz[questionNumber].text
    }

    func getAnswerChoices() -&gt; [String] {
        return quiz[questionNumber].answer //a는 안됨...
    }

    func getProgress() -&gt; Float {
        let progress = Float(questionNumber) / Float(quiz.count)
        return progress
    }</code></pre>
<p>예전에 과제를 할 땐, 시간이 부족해 자세하게 무슨 역할을 하는지 몰랐지만, 이번 챕터를 공부하면서
그래도 예전보단 이해력이 많이 상승했다.</p>
<p>결과:</p>
<p align="center"><img src="https://velog.velcdn.com/images/lets_make_app/post/a4292cf4-9ee4-4c03-8273-14b766ece13f/image.gif" height="100px" width="250px"></p>

<p>끝!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Udemy Xylophone App]]></title>
            <link>https://velog.io/@lets_make_app/Udemy-Xylophone-App</link>
            <guid>https://velog.io/@lets_make_app/Udemy-Xylophone-App</guid>
            <pubDate>Fri, 31 May 2024 13:10:45 GMT</pubDate>
            <description><![CDATA[<p>이번 챕터에서는 버튼을 눌렀을 때 소리가 재생되는 자일로폰 앱을 공부했다.</p>
<ol>
<li>AVFoundation &amp; AVAudioPlayer
사운드를 재생할 시에는 AVAudioPlayer 라는 변수를 생성한다.
그리고 그에 맡는 함수를 생성했다. (그냥 강의를 보고 따라했다!)</li>
</ol>
<pre><code class="language-swift">import UIKit
import AVFoundation

class ViewController: UIViewController {

    var player: AVAudioPlayer!

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    @IBAction func keyPressed(_ sender: UIButton) {

        print(sender.currentTitle)
//        print(sender.titleLabel?.text)

        playSound()

    }

    func playSound() {
        let url = Bundle.main.url(forResource: &quot;C&quot;, withExtension: &quot;wav&quot;)
        player = try! AVAudioPlayer(contentsOf: url!)
        player.play()

    }
}</code></pre>
<p>코드에도 보이듯이 AVFoundation이 import되어야 한다.</p>
<ol start="2">
<li>Interface Builder Action (IBAction)</li>
</ol>
<p>지금까지 IBAction은 UI만 연결이 되는 줄 알았다.
하지만, 아니었다...
솔직히 이건 정말 깜놀...</p>
<p align="center"><img src="https://velog.velcdn.com/images/lets_make_app/post/3f511617-8d1f-4fff-8eee-06b35550f1eb/image.png" height="100px" width="700px"></p>

<p>사진에 보이는 것처럼, IBAction에 마우스를 올려 놓으면, 모든 버튼들이 연결되었다고 보여주는 것을 확인할 수 있다.</p>
<ol start="3">
<li>Type Inference</li>
</ol>
<p>swift는 DataType을 알아내는 능력이 있어서 모든 데이터를 지정해주지 않아도 된다.</p>
<pre><code class="language-swift">var number = 123 //swift는 이미 123을 보고 Int 타입이라는 것을 알고 있다.

var number: Int = 123 //즉 이렇게 타입을 넣어주지 않아도 에러가 안 났던 이유라고 볼 수 있다.

//주의
var number = &quot;abc&quot; //하지만 주의할 점은, 그 데이터 타입을 바꾸지는 못 한다.</code></pre>
<ol start="4">
<li>Parameter &amp; Argument</li>
</ol>
<p>이 부분은 코딩을 배우면서 항상 헷갈렸던 부분이다.</p>
<pre><code class="language-swift">func greeting () {

}

//보통 이렇게 함수를 만든다는 것은 알고 있었지만 () 이 자리에 정확히 뭐가 들어가야 하는지는 잘 몰랐다.

//정답은 input이었다. 아래 쉬운 예시로 공부를 했다.

func greeting(whoToGreet: String) {
     print(&quot;Hello \(whoToGreet)&quot;)
}

//이러한 방식처럼 parameter인 whoToGreet를 받아서 무언가를 해줘 라고 하는 것과 같다.
//그리고 그 parameter의 타입인 argument도 같이 써줘야 한다!</code></pre>
<p><img src="https://velog.velcdn.com/images/lets_make_app/post/d0909dc1-2916-40da-a389-910fe1bb2119/image.png" alt=""></p>
<p>그럼 선언을 했을 때, 이렇게 input 값을 항상 넣어서 사용할 수가 있다.</p>
<ol start="5">
<li>코드 시간차 설정</li>
</ol>
<pre><code class="language-swift">@IBAction func keyPressed(_ sender: UIButton) {  
    playSound(soundName: sender.currentTitle!)

    sender.alpha = 0.5
    print(&quot;start&quot;)

DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { //0.2초 후에 실행
    sender.alpha = 1.0
    print(&quot;end&quot;)
}</code></pre>
<p>강의의 미션으로 등장해서, 검색을 해서 코드를 찾아냈다.</p>
<p>Result:</p>
<p align="center"><img src="https://velog.velcdn.com/images/lets_make_app/post/958c54e5-bd6b-4ac6-8f17-870cd9c2bd46/image.gif" height="100px" width="250px"></p>

<p>끝!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Udemy - EggTimer App]]></title>
            <link>https://velog.io/@lets_make_app/Udemy-EggTimer-App</link>
            <guid>https://velog.io/@lets_make_app/Udemy-EggTimer-App</guid>
            <pubDate>Sun, 26 May 2024 18:38:15 GMT</pubDate>
            <description><![CDATA[<p>이번엔 삶은 계란 시간을 알려주는 타이머를 만드는 챕터였다.
그리고 AVFoundation과 AVAudioPlayer를 활용해 보았다!</p>
<pre><code class="language-swift">import UIKit
import AVFoundation

class ViewController: UIViewController {

    var player: AVAudioPlayer!

    @IBOutlet weak var titleLabel: UILabel!

    @IBOutlet weak var progressBar: UIProgressView!

    //dictionary
    let eggTimes = [&quot;Soft&quot;: 3, &quot;Medium&quot;: 4, &quot;Hard&quot;: 7]

    var timer = Timer()

    var totalTime = 0
    var secondsPassed = 0

    @IBAction func hardnessSelected(_ sender: UIButton) {

        //이 코드가 없다면, 하나의 버튼을 누른 후 실수로 다시 눌렀을 때,
        //타이머가 초기화가 되어서 실행되는게 아니라, 동시에 카운트가 된다.
        //그러므로, invalidate()를 꼭 해줘야 한다.
        timer.invalidate()

        let hardness = sender.currentTitle!

        totalTime = eggTimes[hardness]!

        //눌렸을 때, 다시 시작을 위한 코드
        progressBar.progress = 0.0
        secondsPassed = 0
        titleLabel.text = hardness

        timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(updateTimer), userInfo: nil, repeats: true)

    }

    @objc
    func updateTimer() {
        if secondsPassed &lt; totalTime {

            secondsPassed += 1

            //나누기를 하기 전에, Float로 해야, 시간이 정확하게 계산이 된다.
            progressBar.progress = Float(secondsPassed) / Float(totalTime)

        }
        else {
            timer.invalidate()
            titleLabel.text = &quot;DONE!&quot;
            playSound(soundName: &quot;alarm_sound&quot;) //사운드를 추가
        }
    }

    //사운드 추가 함수
    func playSound(soundName: String) {
        let url = Bundle.main.url(forResource: &quot;alarm_sound&quot;, withExtension: &quot;mp3&quot;)
        player = try! AVAudioPlayer(contentsOf: url!)
        player.play()
    }
}
</code></pre>
<p>완성된 모습:</p>
<p align="center"><img src="https://velog.velcdn.com/images/lets_make_app/post/b1824666-c81a-4497-832d-c6cae187d261/image.gif" height="100px" width="250px"></p>

<p>끝!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Dictionary]]></title>
            <link>https://velog.io/@lets_make_app/Dictionary</link>
            <guid>https://velog.io/@lets_make_app/Dictionary</guid>
            <pubDate>Fri, 24 May 2024 06:47:30 GMT</pubDate>
            <description><![CDATA[<pre><code class="language-swift">// Type Inference를 사용해서 타입 정의를 안 해도 되지만, 할 수도 있다.
var studentScores = [&quot;Alice&quot;: 85, &quot;Bob&quot;: 92, &quot;Charlie&quot;: 78, &quot;David&quot;: 95]
var studentScores: [String: Int] = [&quot;Alice&quot;: 85, &quot;Bob&quot;: 92, &quot;Charlie&quot;: 78, &quot;David&quot;: 95]

// Dictionary의 값에 접근하려면 그 키 값을 입력해야 된다. Array처럼 [0] 이러한 순서로 접근하는 것과 차이가 있다.
print(&quot;Alice&#39;s score is \(studentScores[&quot;Alice&quot;]!)&quot;)
print(&quot;Bob&#39;s score is \(studentScores[&quot;Bob&quot;]!)&quot;)

// Dictionary에 추가
studentScores[&quot;Eve&quot;] = 88

// 수정
studentScores[&quot;Charlie&quot;] = 80

// 제거
studentScores[&quot;David&quot;] = nil

// 반복
for (name, score) in studentScores {
    print(&quot;\(name) scored \(score)&quot;)
}

// Dictionary에 키 값이 있는지 확인 방법
if let score = studentScores[&quot;Charlie&quot;] {
    print(&quot;Charlie&#39;s score is \(score)&quot;)
} else {
    print(&quot;Charlie&#39;s score is not available&quot;)
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[Udemy 챌린지 챕터 #1]]></title>
            <link>https://velog.io/@lets_make_app/Udemy-%EC%B1%8C%EB%A6%B0%EC%A7%80-%EC%B1%95%ED%84%B0-1</link>
            <guid>https://velog.io/@lets_make_app/Udemy-%EC%B1%8C%EB%A6%B0%EC%A7%80-%EC%B1%95%ED%84%B0-1</guid>
            <pubDate>Wed, 22 May 2024 11:01:16 GMT</pubDate>
            <description><![CDATA[<p>이번 챕터는 udemy 안에서 배운 내용을 활용해 혼자서 복습 느낌으로 앱을 만드는 챕터였다.
대부분 보면서 따라하는 수업과 달리 이번에는 혼자서 해야되서 시작하기 전에 조금 긴장이 되었다.</p>
<p>하지만 그래도 지금 3달 정도 swift를 그래도 매일 보고 있기 때문에 자신감을 가지고 시작했다.</p>
<p>목표: 부트캠프에서 배운 것 + udemy에서 배운 것 활용 (코드베이스로 만들기)
Goal:
<img src="https://velog.velcdn.com/images/lets_make_app/post/dcc9e797-7c2f-451c-b937-bad64bd2e2c4/image.png" height="100px" width="250px"></p></p>
<ol>
<li>Snapkit, Then 사용</li>
</ol>
<p><img src="https://velog.velcdn.com/images/lets_make_app/post/3ea69c96-69f7-4d27-aef9-5822e44b11c5/image.png" alt=""></p>
<p>나는 코드 베이스로 이번 챕터를 진행하기로 했다.
그래서 layout과 attribute을 좀 더 효율적이게 잡기 위해 Snapkit과 Then을 사용했다.</p>
<p><img src="https://velog.velcdn.com/images/lets_make_app/post/6c3e408b-8e2e-4d5c-8608-3622f8a715f4/image.png" height="100px" width="500px"></p></p>
<p>Layout 또한 아래의 방식으로 잡았다.</p>
<p><img src="https://velog.velcdn.com/images/lets_make_app/post/968a0a76-e421-4fe1-88c2-8fca0c4713d9/image.png" height="100px" width="500px"></p></p>
<ol start="2">
<li>Button</li>
</ol>
<p>버튼을 탭 했을 때, asset에 있는 그림들이 램덤으로 나오게 기능을 구현했다.</p>
<p>일단 눌렀을 시, 이미지들을 램덤으로 추출할 수 있는 함수를 하나 생성했다.</p>
<p><img src="https://velog.velcdn.com/images/lets_make_app/post/84a0f30b-4185-4b5d-9287-ea671e4d8e78/image.png" height="100px" width="500px"></p></p>
<p>그리고 호출!&#39;</p>
<p><img src="https://velog.velcdn.com/images/lets_make_app/post/b5967347-9dde-438a-856e-f273c049a932/image.png" height="100px" width="500px"></p></p>
<ol start="3">
<li>forEach</li>
</ol>
<p>전에 여러가지 UI를 추가할 때, 코드를 짧게 유지할 수 있는 방법을 배워서 한 번 사용해보고 싶었다.</p>
<p><img src="https://velog.velcdn.com/images/lets_make_app/post/8e20a722-3f79-45f6-9ec1-602fa3fd1315/image.png" height="100px" width="500px"></p></p>
<p>그리고 나의 앱은 이렇게 탄생되었다.</p>
<p><img src="https://velog.velcdn.com/images/lets_make_app/post/0262189a-9f64-4875-9921-2bfafe268177/image.gif" height="100px" width="250px"></p></p>
<p>버튼을 눌렀을 때, 랜덤으로 이미지가 바뀌면서 잘 작동하는 것을 확인할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Udemy - Dicee App - 2편]]></title>
            <link>https://velog.io/@lets_make_app/Udemy-Dicee-App-2%ED%8E%B8</link>
            <guid>https://velog.io/@lets_make_app/Udemy-Dicee-App-2%ED%8E%B8</guid>
            <pubDate>Tue, 21 May 2024 18:24:23 GMT</pubDate>
            <description><![CDATA[<p>새롭게 배운 꿀팁/정보 2탄!</p>
<ol>
<li>일단 개발자들은 반복적인 코드를 싫어한다!</li>
</ol>
<pre><code class="language-swift">    @IBAction func rollButtonPressed(_ sender: UIButton) {

        let diceArray = [#imageLiteral(resourceName: &quot;DiceOne&quot;), 
        #imageLiteral(resourceName: &quot;DiceTwo&quot;), 
        #imageLiteral(resourceName: &quot;DiceThree&quot;), 
        #imageLiteral(resourceName: &quot;DiceFour&quot;), 
        #imageLiteral(resourceName: &quot;DiceFive&quot;), 
        #imageLiteral(resourceName: &quot;DiceSix&quot;)]

        diceImageView1.image = diceArray.randomElement() //아래의 랜덤 방식과 같은 메서드
        diceImageView2.image = diceArray[Int.random(in: 1...5)]

    }
}

위에 코드를 확인해 보면, diceImageView1 과 diceImageView2 둘 다 diceArray를 사용한다.
그럼으로 원래 각각에 배열이 직접 들어가 있었다면, 위에 변수를 생성해 코드를 refactoring 할 수 있다.</code></pre>
<ol start="2">
<li>Randomization</li>
</ol>
<pre><code class="language-swift">//randomization의 여러 방법

Int(in: 1...3)
Float(in:1...3) //2.912319
array.randomElement() //array에서 램덤으로 추출
array.shuffle() //array 안에 있는 값들이 셔플되면서 자리를 바꿈
Bool.random() // true or false</code></pre>
<ol start="3">
<li>현재 앱의 모습:</li>
</ol>
<p align="center"><img src="https://velog.velcdn.com/images/lets_make_app/post/3c33b79e-5701-4eb3-b6b6-faabf7c3e19f/image.gif" width="25%" height="0%">
]]></description>
        </item>
        <item>
            <title><![CDATA[Udemy - Dicee App - 1편]]></title>
            <link>https://velog.io/@lets_make_app/Udemy-Dicee-App-1%ED%8E%B8</link>
            <guid>https://velog.io/@lets_make_app/Udemy-Dicee-App-1%ED%8E%B8</guid>
            <pubDate>Tue, 21 May 2024 15:38:30 GMT</pubDate>
            <description><![CDATA[<p>기본기가 부족해서 결국 udemy 강의를 처음부터 보기로 결정했다.
그리고 공부하게 된 dicee 앱!</p>
<ol>
<li>#imageLiteral</li>
</ol>
<p>아주 기초부터 알려주는 강의라서 대부분 쉽게 따라 할 수 있지만, 따라하는 도중 새롭게 알게 된 기능이 있다.</p>
<p>바로</p>
<p>#imageLiteral(</p>
<p>이렇게 하게되면, 
<img src="https://velog.velcdn.com/images/lets_make_app/post/44cb513b-7b4a-40d9-a841-0bc1845403ba/image.png" alt=""></p>
<p>저렇게 생긴 그림이 나오면서, asset에 있는 사진을 확인하면서 선택할 수 있다!</p>
<ol start="2">
<li>\(코드) - String Interpolation</li>
</ol>
<pre><code class="language-swift">print(&quot;Hello World&quot;)
print(&quot;Hello \(2+5) World&quot;) // Hello 5 World
</code></pre>
<p>가끔식 print 안에 코드를 추가 할 상황이 종종 있었는데, 유용한 방법을 알아냈다.
\ ( ) 이 방식으로 가능했다...</p>
<ol start="3">
<li>변수의 위치 중요성</li>
</ol>
<pre><code class="language-swift">
//누를때마다 + 1
class ViewController: UIViewController {

    @IBOutlet weak var diceImageView1: UIImageView!
    @IBOutlet weak var diceImageView2: UIImageView!

    var leftDiceNumber = 1

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    @IBAction func rollButtonPressed(_ sender: UIButton) {

        diceImageView1.image = [ #imageLiteral(resourceName: &quot;DiceOne&quot;), 
        #imageLiteral(resourceName: &quot;DiceTwo&quot;), 
        #imageLiteral(resourceName: &quot;DiceThree&quot;), 
        #imageLiteral(resourceName: &quot;DiceFour&quot;), 
        #imageLiteral(resourceName: &quot;DiceFive&quot;), 
        #imageLiteral(resourceName: &quot;DiceSix&quot;) ][leftDiceNumber]

        leftDiceNumber = leftDiceNumber + 1

    }

}

//var leftDiceNumber = 1의 위치를 확인해보면, 함수 안에 있는 것을 확인할 수 있다.
//즉 버튼을 누를 때 leftDiceNumber는 다시 1로 돌아온다는 것이다.
//leftDiceNumber는 1과 2를 무한 반복하게 된다.
class ViewController: UIViewController {

    @IBOutlet weak var diceImageView1: UIImageView!
    @IBOutlet weak var diceImageView2: UIImageView!

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    @IBAction func rollButtonPressed(_ sender: UIButton) {

        var leftDiceNumber = 1

        diceImageView1.image = [ #imageLiteral(resourceName: &quot;DiceOne&quot;), 
        #imageLiteral(resourceName: &quot;DiceTwo&quot;), 
        #imageLiteral(resourceName: &quot;DiceThree&quot;), 
        #imageLiteral(resourceName: &quot;DiceFour&quot;), 
        #imageLiteral(resourceName: &quot;DiceFive&quot;), 
        #imageLiteral(resourceName: &quot;DiceSix&quot;) ][leftDiceNumber]

        leftDiceNumber = leftDiceNumber + 1

    }

}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[DispatchQueue에 대해...]]></title>
            <link>https://velog.io/@lets_make_app/DispatchQueue%EC%97%90-%EB%8C%80%ED%95%B4</link>
            <guid>https://velog.io/@lets_make_app/DispatchQueue%EC%97%90-%EB%8C%80%ED%95%B4</guid>
            <pubDate>Fri, 19 Apr 2024 19:38:20 GMT</pubDate>
            <description><![CDATA[<p>Swift에서 DispatchQueue는 Grand Central Dispatch(GCD)를 사용하여 <strong>비동기적</strong>으로 작업을 수행하는 데 사용되는 클래스이다. 
<strong>DispatchQueue를 사용하면 앱에서 다양한 작업을 비동기적으로 실행하고, 작업 간에 우선순위를 지정하거나 제어할 수 있다.</strong></p>
<p>여러 종류의 DispatchQueue가 있지만, 가장 일반적으로 사용되는 두 가지 유형은 다음과 같다:</p>
<ol>
<li><p><strong>Main DispatchQueue</strong>: 앱의 주요 <strong>UI 작업</strong>을 처리하는 DispatchQueue이다. 대부분의 UI 업데이트는 <strong>Main DispatchQueue</strong>에서 수행되어야 한다. <strong>그렇지 않으면 UI가 느리게 응답하거나 멈출 수 있다.</strong> 예를 들어, UI 업데이트나 사용자 이벤트 처리 등은 Main DispatchQueue에서 수행된다.</p>
</li>
<li><p><strong>Global DispatchQueue</strong>: <strong>백그라운드에서 비동기적으로 작업</strong>을 실행하기 위한 DispatchQueue이다. 이것은 <strong>앱의 메인 스레드와 분리된 백그라운드 스레드에서 작업을 처리</strong>하는 데 사용된다. 작업을 수행할 때에는 작업의 성격에 따라 다양한 우선순위의 DispatchQueue를 선택할 수 있다.</p>
</li>
</ol>
<p>*
*
*
*</p>
<p><strong>DispatchQueue를 사용하여 작업을 예약하고 실행하는 방법:</strong></p>
<p><strong>async</strong>: 비동기적으로 작업을 예약한다. 현재 스레드를 차단하지 않고 작업을 실행하며, 작업이 완료될 때까지 대기하지 않는다.</p>
<p><strong>sync</strong>: 동기적으로 작업을 예약한다. 현재 스레드를 차단하고 작업을 실행하며, 작업이 완료될 때까지 대기한다.</p>
<p>일반적으로 UI 업데이트와 관련된 작업은 DispatchQueue.main.async를 사용하여 Main DispatchQueue에서 비동기적으로 예약되고, 백그라운드에서 실행되어야 하는 작업은 Global DispatchQueue에서 비동기적으로 예약된다.</p>
<p>예를 들어, 네트워크 요청을 백그라운드에서 수행하고, 데이터를 받아오면 UI를 업데이트하는 코드는 다음과 같이 작성될 수 있다:</p>
<p>예시:</p>
<pre><code class="language-swift">DispatchQueue.global().async {
    // 네트워크 요청 등 비동기 작업 수행
    let data = fetchDataFromNetwork()

    DispatchQueue.main.async {
        // 받아온 데이터를 사용하여 UI 업데이트
        updateUI(with: data)
    }
}
</code></pre>
<p>이를 통해 앱이 더욱 반응적이고, 작업이 느리거나 차단되는 것을 방지할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[동기(Synchronous) & 비동기(Asynchronous)]]></title>
            <link>https://velog.io/@lets_make_app/%EB%8F%99%EA%B8%B0Synchronous-%EB%B9%84%EB%8F%99%EA%B8%B0Asynchronous</link>
            <guid>https://velog.io/@lets_make_app/%EB%8F%99%EA%B8%B0Synchronous-%EB%B9%84%EB%8F%99%EA%B8%B0Asynchronous</guid>
            <pubDate>Fri, 19 Apr 2024 19:14:17 GMT</pubDate>
            <description><![CDATA[<p>Swift에서의 동기(Synchronous)와 비동기(Asynchronous)는 코드 실행의 흐름과 관련이 있다.</p>
<p><strong>동기(Synchronous):</strong>
동기(synchronous) 코드는 한 번에 &quot;하나&quot;의 작업만을 처리하고, 다음 작업은 이전 작업이 완료된 &quot;후에&quot; 순차적으로 실행된다.
작업이 완료될 때까지 대기하며, 다음 코드 실행은 해당 작업이 완료된 후에 이루어진다.
예를 들어, 함수를 호출하고 그 결과를 기다린 다음, 다음 작업을 수행하는 것이 동기적인 방식이다.</p>
<p><strong>비동기(Asynchronous):</strong>
비동기 코드는 &quot;여러 작업&quot;을 동시에 처리하거나, 한 작업이 완료될 때까지 &quot;대기하지 않고&quot; 다음 코드를 계속 실행할 수 있다.
작업이 완료될 때까지 대기하지 않으므로, 다음 코드 실행은 해당 작업이 완료되기를 기다리지 않고 즉시 진행된다.
예를 들어, 비동기적으로 데이터를 다운로드하고, 데이터가 다운로드되는 동안 다른 작업을 수행하는 것이 비동기적인 방식이다.
Swift에서 비동기 작업을 수행하는 방법으로는 다음과 같은 것들이 있습니다:</p>
<p>예시:</p>
<pre><code class="language-swift">            DispatchQueue.main.async {
                self.imageView.image = nil
                self.titleLabel.text = currentProduct.title
                self.descriptionLabel.text = currentProduct.description</code></pre>
<p>위의 코드는 비동기임으로, 아래의 작업들이 동시에 이뤄진다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[개념 정리 (URLSession, CoreData)]]></title>
            <link>https://velog.io/@lets_make_app/%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC-URLSession-CoreData</link>
            <guid>https://velog.io/@lets_make_app/%EA%B0%9C%EB%85%90-%EC%A0%95%EB%A6%AC-URLSession-CoreData</guid>
            <pubDate>Thu, 18 Apr 2024 18:22:04 GMT</pubDate>
            <description><![CDATA[<p><em><strong>URLSession?</strong></em></p>
<p>Swift의 URLSession은 네트워크 작업을 수행하기 위한 핵심 클래스 중 하나이다. 이 클래스는 HTTP 요청을 생성하고 보내며, 서버로부터 응답을 받아오는 등의 작업을 수행할 수 있다. URLSession은 비동기적으로 작동하며, 네트워크 작업이 완료되었을 때 클로저를 통해 결과를 처리한다.</p>
<p><em><strong>URLSession은 세 가지 주요 작업 수행:</strong></em></p>
<ol>
<li><p>Data Task: 데이터를 다운로드하거나 업로드하는 작업을 처리한다. 이 작업은 JSON, 이미지, 동영상 등의 데이터를 가져오거나 서버에 업로드할 때 사용된다.</p>
</li>
<li><p>Download Task: 파일을 다운로드하는 작업을 처리한다. 이 작업은 대용량 파일을 다운로드할 때 특히 유용하다.</p>
</li>
<li><p>Upload Task: 파일이나 데이터를 서버에 업로드하는 작업을 처리한다. 이 작업은 사용자가 서버에 파일을 전송하거나 업로드할 때 사용된다.</p>
</li>
</ol>
<p>URLSession은 기본적으로 iOS, macOS 및 watchOS에서 사용할 수 있고, 이 클래스는 네트워크 작업을 수행하는 데 있어서 강력하면서도 유연한 API를 제공하여 다양한 요구사항을 충족시킬 수 있다.</p>
<p><strong>코드 예시:</strong></p>
<pre><code class="language-swift">import Foundation

// URLSession 인스턴스 생성
let session = URLSession.shared

// URL 생성
let url = URL(string: &quot;https://api.example.com/data&quot;)!

// URLSessionDataTask 생성
let task = session.dataTask(with: url) { data, response, error in
    // 에러 처리
    if let error = error {
        print(&quot;Error: \(error)&quot;)
        return
    }

    // 응답 처리
    guard let httpResponse = response as? HTTPURLResponse,
          (200...299).contains(httpResponse.statusCode) else {
        print(&quot;Invalid response&quot;)
        return
    }

    // 데이터 처리
    if let data = data {
        let responseData = String(data: data, encoding: .utf8)
        print(&quot;Response data: \(responseData ?? &quot;&quot;)&quot;)
    }
}

// 작업 시작
task.resume()</code></pre>
<p>이 코드에서는 URLSession을 사용하여 지정된 URL에서 데이터를 가져온다. URLSessionDataTask를 생성하고, dataTask(with:) 메서드를 사용하여 URL로부터 데이터를 가져온다. 클로저는 데이터, 응답 및 오류를 처리하고 있고, 마지막으로, resume() 메서드를 호출하여 작업을 시작할 수 있다.</p>
<p><em><strong>CoreData?</strong></em></p>
<p>Core Data는 애플리케이션의 데이터 모델을 관리하고, 해당 데이터를 저장하고 검색하는 프레임워크이다. iOS, macOS, watchOS 및 tvOS에서 사용할 수 있으며, 데이터베이스 관리 및 객체 그래프 관리와 같은 기능을 제공한다. Core Data는 일반적으로 대규모 데이터 집합을 관리하는 애플리케이션에서 많이 사용된다.</p>
<p><em><strong>Core Data의 주요 구성 요소?</strong></em></p>
<ol>
<li><p>Managed Object Model (MOModel): 애플리케이션의 데이터 구조를 정의하는 객체 그래프이다. 이 모델은 앱에서 사용하는 데이터 개체의 유형, 속성 및 관계를 설명한다. MOModel은 .xcdatamodeld 확장자를 가진 Xcode의 데이터 모델 파일에 정의된다.</p>
</li>
<li><p>Managed Object (MO): Core Data가 관리하는 데이터 항목이다. MO는 MOModel에 정의된 개체 유형의 인스턴스이다. 각 MO는 데이터베이스 내에서 고유한 식별자를 가지며, 해당 속성을 사용하여 데이터에 액세스할 수 있다.</p>
</li>
<li><p>Persistent Store Coordinator (PSC): 애플리케이션과 데이터 저장소 간의 중개자 역할을 한다. PSC는 데이터의 영구 저장을 관리하고, 애플리케이션의 데이터 모델과 실제 데이터 저장소 간의 매핑을 관리한다.</p>
</li>
<li><p>Managed Object Context (MOC): 애플리케이션의 데이터 모델을 작업하는 데 사용된다. MOC는 데이터를 추가, 수정, 삭제 및 검색할 수 있는 인터페이스를 제공하며, 이러한 작업은 일반적으로 MOC 내에서 수행된다. 또한, MOC는 데이터 변경을 추적하고 데이터 저장소에 변경 내용을 저장하는 역할도 한다.</p>
</li>
<li><p>Persistent Store: 실제 데이터를 저장하는 데 사용되는 백엔드 데이터베이스이다. SQLite가 Core Data의 기본 데이터 저장소이지만, 다른 유형의 데이터베이스도 지원된다.</p>
</li>
</ol>
<p>Core Data를 사용하면 데이터 모델을 정의하고, 데이터를 저장하고 검색하는 등의 작업을 쉽게 수행할 수 있다. 또한, Core Data는 데이터의 관리를 위해 여러 기능을 제공하며, 데이터 모델이 변경될 때 자동으로 데이터베이스 스키마를 업데이트하는 등의 기능도 포함되어 있다. Core Data는 iOS 및 macOS 개발에서 매우 강력하고 유연한 도구로 널리 사용된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[약수의 합 (프로그래머스)]]></title>
            <link>https://velog.io/@lets_make_app/%EC%95%BD%EC%88%98%EC%9D%98-%ED%95%A9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4</link>
            <guid>https://velog.io/@lets_make_app/%EC%95%BD%EC%88%98%EC%9D%98-%ED%95%A9-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4</guid>
            <pubDate>Tue, 26 Mar 2024 18:06:42 GMT</pubDate>
            <description><![CDATA[<p>오늘 알고리즘 문제를 풀다가, 해설을 보고 풀었는데도 이해가 잘 안되는 문제가 있어서 블로그에 올리게 되었다.</p>
<pre><code class="language-swift">문제 설명:
정수 n을 입력받아 n의 약수를 모두 더한 값을 리턴하는 함수, solution을 완성해주세요.

제한 사항:
n은 0 이상 3000이하인 정수입니다.

입출력 예:
n    return
12    28
5    6

입출력 예 설명:

입출력 예 #1
12의 약수는 1, 2, 3, 4, 6, 12입니다. 이를 모두 더하면 28입니다.

입출력 예 #2
5의 약수는 1, 5입니다. 이를 모두 더하면 6입니다.

//1
func solution(_ n:Int) -&gt; Int {

let divisors = (1...n).filter { n % $0 == 0 }
let sum = divisors.reduce(0, +)

return sum

1번 답은 나의 베프 gpt를 활용해 얻어낸 결과이다.
설명을 하자면, filter라는 메서드를 활용해 n이라는 값에 적용한 후, 그 값이 0과 같다면 이라는 divisors 상수를 생성했다.
그리고 reduce 메서드는 Swift에서 컬렉션(배열 또는 다른 시퀀스)의 모든 요소를 하나의 값으로 결합하는 데 사용된다.
reduce를 하면 윗 줄의 filter 된 값을 하나로 만들어줄 것이며 +를 뒤에 추가해주면 그 값을 다 더할 수 있다.

//2 
func solution(_ n:Int) -&gt; Int {

    var sum = 0

    for i in 1..&lt;n + 1 {
        if n % i == 0 {
            sum += i
        }
    }
     return sum
}

이 방식은 간단하다.
단 for i in 1..&lt;n + 1 { 이 줄이 조금 애매한 부분이 있다.
코드를 1...n으로 돌렸을 때는 오류가 떠서 이 방식으로 진행을 했다.
아마 범위가 광범위해서 그렇다고 검색을 하다 본 것같다. 
</code></pre>
<p>아직도 알고리즘을 풀어도 뭔가 찝찝하다...</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[xib & nib]]></title>
            <link>https://velog.io/@lets_make_app/xib-nib</link>
            <guid>https://velog.io/@lets_make_app/xib-nib</guid>
            <pubDate>Tue, 26 Mar 2024 11:30:07 GMT</pubDate>
            <description><![CDATA[<p>To Do List 과제를 하면서 많이 뜨던 오류들 중 xib 와 nib 관련된 오류를 처음으로 접하게 되었다.
해결책을 검색하고 유튭을 아무리 봐도, 이 두 무언가가 무엇을 하는 애들인지 도무지 알 수 없었다.</p>
<p>그래서 일단 정의와 용도를 정리를 해놓고, 나의 swift 경험치가 더 올랐을 때 다시 와서 봐보기로 했다.</p>
<p><em><strong>XIB( XML Interface Builder)과 NIB( NeXT Interface Builder)은 iOS 개발에서 사용되는 사용자 인터페이스(UI)를 시각적으로 디자인하는 데 사용된다.</strong></em></p>
<ol>
<li>XIB( XML Interface Builder):</li>
</ol>
<ul>
<li>XIB 파일은 하나의 user interface 화면 또는 일부를 설명하는 XML 파일이다.</li>
<li>개발자는 Interface Builder에서 UI 요소(Button, Label, Textfield 등)를 캔버스에 끌어다 놓고 속성을 구성하여 시각적으로 사용자 인터페이스를 디자인할 수 있다.</li>
<li>XIB 파일은 일반적으로 iOS 앱의 개별 화면을 설계하는 데 사용다.</li>
<li>디자인이 완료되면 XIB 파일이 NIB 파일로 컴파일다.</li>
</ul>
<ol start="2">
<li>NIB( NeXT Interface Builder):</li>
</ol>
<ul>
<li>NIB 파일은 XIB 파일의 컴파일된 버전이다. &quot;NeXT Interface Builder&quot;의 약자다.</li>
<li>NIB 파일에는 XIB 파일에 정의된 객체 및 구성의 직렬화된 버전이 포함되어 있다.</li>
<li>iOS 앱을 컴파일할 때 XIB 파일이 처리되고 NIB 파일로 변환된다. 이 파일들은 앱과 번들로 결합됨.</li>
<li>실행 중에 iOS 시스템은 NIB 파일을로드하고 해당하는 사용자 인터페이스 요소를 생성한다. </li>
</ul>
<p><em><strong>요약하면, XIB 파일은 인터페이스 빌더에서 사용자 인터페이스를 시각적으로 디자인하는 데 사용되고, NIB 파일은 XIB 파일의 컴파일된 버전으로 앱에서 실제 사용자 인터페이스를 생성하는 데 사용된다. XIB와 NIB 파일은 iOS 개발 워크플로우에서 시각적으로 매력적이고 상호작용적인 사용자 인터페이스를 만드는 데 필수적인 부분이다.</strong></em></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[To Do List Assignment 1차]]></title>
            <link>https://velog.io/@lets_make_app/To-Do-List-Assignment-1%EC%B0%A8</link>
            <guid>https://velog.io/@lets_make_app/To-Do-List-Assignment-1%EC%B0%A8</guid>
            <pubDate>Fri, 22 Mar 2024 12:04:02 GMT</pubDate>
            <description><![CDATA[<p>과제를 시작하기 전 이 과제를 어떻게 해야 할지 많은 고민을 했다.
하지만, 고민은 나의 수준에서는 시간 낭비에 가깝다는 것을 오늘도 어김없이 깨닫고 검색과 다른 개발자들 그리고 나의 베프 gpt의 가이드를 따라 하면서 그 로직과 문법 그리고 과정들을 학습하는 방식을 택했다.</p>
<p>1단계:</p>
<p>부트 캠프의 지급된 강의를 다시 시청하면서 UITableView를 만들 때 필수적인 코드와 필요한 요소들을 일단 따라서 적어내려 갔다.</p>
<pre><code class="language-swift">class ViewController: UIViewController,UITableViewDelegate, UITableViewDataSource {

꼭 class가 UITableViewDelegate와 UITableViewDataSource를 할당해준다.</code></pre>
<p>2단계:</p>
<pre><code class="language-swift">        //dataSource와 delegate는 self에 지정
        tableView.dataSource = self
        tableView.delegate = self

        tableView.register(UITableViewCell.self, forCellReuseIdentifier: &quot;Cell&quot;)

        //subView??
        view.addSubview(tableView)
        }

        그렇다, 아직 얘네들은 정확히 모른다. 설명 패스.</code></pre>
<p>3단계:</p>
<pre><code class="language-swift">    }
    //Table의 행(row) 수를 보고하는 함수
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
        return data.count
    }
    //각 행에 셀을 만들어주는 함수, 어떤 컨텐츠가 들어갈지 정해준다
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: &quot;Cell&quot;, for: indexPath)
        cell.textLabel?.text = data[indexPath.row]
        return cell
    }
    //셀이 눌렸을 때 문구 프린트와 눌렀다 땐 느낌을 주는 함수
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print(&quot;Selected: \(data[indexPath.row])&quot;)

        //눌렀을 때 음영처리 해주는 애니메이션
        tableView.deselectRow(at: indexPath, animated: true)
    }

}

현재 이 단계까지 온 상태다.</code></pre>
<p><img src="https://velog.velcdn.com/images/lets_make_app/post/049f3c40-61c5-4865-be6f-62f6b5691861/image.png" alt=""></p>
<p>주말 동안 좀 더 과제를 해 볼 예정!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[if / if else / else]]></title>
            <link>https://velog.io/@lets_make_app/if-if-else-else</link>
            <guid>https://velog.io/@lets_make_app/if-if-else-else</guid>
            <pubDate>Mon, 18 Mar 2024 10:44:58 GMT</pubDate>
            <description><![CDATA[<p>Swift에서 else와 else if은 조건문에서 사용되지만 각각 다른 목적으로 사용된다:</p>
<ol>
<li>else: 이는 &#39;if&#39; 문이나 &#39;if&#39;-&#39;else if&#39; 문의 연쇄에서 이전 조건이 모두 거짓일 때 실행되는 기본 조건이다. 이에는 연관된 조건이 없으며 일반적으로 조건 체인의 끝에 배치된다.</li>
</ol>
<pre><code class="language-swift">if 조건1 {
    // 조건1이 참일 때 실행되는 코드
} else if 조건2 {
    // 조건2가 참일 때 실행되는 코드
} else {
    // 조건1과 조건2가 모두 거짓일 때 실행되는 코드
}
</code></pre>
<ol start="2">
<li>else if: 이는 &#39;if&#39; 문의 이전 조건이 거짓일 때 추가적인 조건을 지정하는 데 사용된다. 여러 조건을 연결할 수 있다.</li>
</ol>
<pre><code class="language-swift">if 조건1 {
    // 조건1이 참일 때 실행되는 코드
} else if 조건2 {
    // 조건1이 거짓이고 조건2가 참일 때 실행되는 코드
} else {
    // 조건1과 조건2가 모두 거짓일 때 실행되는 코드
}
</code></pre>
<p>요약하면, else는 이전 조건이 모두 거짓일 때 처리하는 데 사용되고 else if는 이전 조건이 거짓인 경우 추가적인 조건을 체크할 수 있게 해준다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[enumeration (열거형)]]></title>
            <link>https://velog.io/@lets_make_app/enumeration-%EC%97%B4%EA%B1%B0%ED%98%95</link>
            <guid>https://velog.io/@lets_make_app/enumeration-%EC%97%B4%EA%B1%B0%ED%98%95</guid>
            <pubDate>Fri, 15 Mar 2024 10:50:33 GMT</pubDate>
            <description><![CDATA[<p>스위프트(Swift)에서 열거형(enumeration), 일반적으로 enum이라고 불리는 것은 관련된 값들의 집합을 안전한 형태로 정의하는 방법이다. </p>
<p>Swift에서의 enum은 특정 변수나 상수가 가질 수 있는 가능한 상태나 값을 유한한 집합으로 정의할 수 있게 해준다.</p>
<p>스위프트에서 enum에 대한 주요 포인트는 다음과 같다:</p>
<p><em>1. 열거형 정의하기: 열거형은 enum 키워드로 시작하며 열거형의 이름과 각각이 가능한 값을 나타내는 케이스들의 목록으로 구성된다. 예를 들면:</em></p>
<pre><code class="language-swift">enum CompassDirection {
    case north
    case south
    case east
    case west
}
</code></pre>
<ol start="2">
<li><em>연관 값(associated values): Swift의 열거형은 각각의 케이스에 추가 데이터를 연관시킬 수 있는 연관 값(associated values)을 가질 수 있다. 이것은 열거형의 각 케이스에 추가 정보를 첨부하고 싶을 때 특히 유용하다. 예를 들면:</em></li>
</ol>
<pre><code class="language-swift">enum Barcode {
    case upc(Int, Int, Int, Int)
    case qrCode(String)
}
</code></pre>
<ol start="3">
<li><em>원시 값(raw values): Swift의 열거형은 원시 값(raw values)을 가질 수 있습니다. 이는 각 열거형 케이스와 연관된 미리 정의된 값들로, 모든 원시 값들은 동일한 타입이어야 한다. 예를 들면:</em></li>
</ol>
<pre><code class="language-swift">enum Planet: Int {
    case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
</code></pre>
<ol start="4">
<li><p><em>패턴 매칭(pattern matching): Swift에서는 열거형과 패턴 매칭을 함께 사용할 수 있으며, 이를 통해 다른 케이스들을 이용하여 코드를 실행할 수 있다.</em></p>
</li>
<li><p><em>연관 값과 원시 값이 있는 열거형: Swift의 열거형에서는 연관 값과 원시 값을 결합할 수 있다. 그러나 그렇게 할 경우 연관 값이 원시 값보다 우선된다.</em></p>
</li>
</ol>
<p>열거형은 Swift에서 데이터를 모델링할 때 강력한 도구이며, 코드를 더 읽기 쉽고 이해하기 쉽고 유지보수하기 쉽도록 만든다. 사용자 인터페이스 요소의 상태, HTTP 응답 상태 코드 등을 표현하는 데 자주 사용된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[과제를 하면서 배운 것들]]></title>
            <link>https://velog.io/@lets_make_app/%EA%B3%BC%EC%A0%9C%EB%A5%BC-%ED%95%98%EB%A9%B4%EC%84%9C-%EB%B0%B0%EC%9A%B4-%EA%B2%83%EB%93%A4</link>
            <guid>https://velog.io/@lets_make_app/%EA%B3%BC%EC%A0%9C%EB%A5%BC-%ED%95%98%EB%A9%B4%EC%84%9C-%EB%B0%B0%EC%9A%B4-%EA%B2%83%EB%93%A4</guid>
            <pubDate>Thu, 14 Mar 2024 11:09:20 GMT</pubDate>
            <description><![CDATA[<ol>
<li><pre><code class="language-swift">||</code></pre>
이건 제공된 강의 어딘가에 나와있던 기억이 있지만, 
강의의 내용들은 거의 기억이 나지 않음으로 과제를 하면서 사용하면 편할 거 같아 사용하기로 했다.</li>
</ol>
<pre><code>```swift
let a = 5
let b = 10
if a &lt; 0 || b &lt; 0 {
    print(&quot;At least one number is negative.&quot;)
} else {
    print(&quot;Both numbers are non-negative.&quot;)
}

|| 이것은 또는 이라는 의미를 가지고 있다.
즉 ||의 앞 뒤 중 하나만이라도 참이라면 참을 출력해줄 것이다.
하지만 앞 뒤 둘다 거짓이라면 거짓을 출력한다.</code></pre><ol start="2">
<li>repeat {...} while</li>
</ol>
<pre><code class="language-swift">repeat {
    a = Int.random(in: 1...9)
    b = Int.random(in: 1...9)
    c = Int.random(in: 1...9)
} while a == b || b == c || c == a

{...}는 while 조건과 일치하지 않을 때까지 반복 repeat를 해주는 공식이다.
</code></pre>
<ol start="3">
<li>readline()</li>
</ol>
<pre><code class="language-swift">print(&quot;Enter your name:&quot;)
if let name = readLine() {
    print(&quot;Hello, \(name)!&quot;)
}

command-line interface에서 input을 받기 제일 기본적인 방법이다.
text를 standard input으로 받고, 그것을 optional string으로 return해준다.
</code></pre>
<ol start="4">
<li>In Swift, when you have an integer value, you can&#39;t directly access individual digits using array-like indexing.</li>
</ol>
<pre><code class="language-swift">func provideFeedback(playerGuess: Int, answer: Int) {
    let playerGuessString = String(playerGuess)
    let answerString = String(answer)
    var strikes = 0
    var balls = 0

    // Check for strikes and balls
    for (index, digit) in playerGuessString.enumerated() {
        if digit == answerString[index] {
            strikes += 1
        } else if answerString.contains(digit) {
            balls += 1
        }
    }

    해석:
    처음에는 플레이어의 답은 Int로 나올 걸 예상하고 아래의 String부분은 Int로 나와야 한다고
    생각을 했다. 하지만, 과제를 하면서 알게 된 부분은,
    integer 값이 있다면, array 형식의 인덱스에 직접적인 접근이 불가능하다였다.
    그래서 접근을 가능케하려면 String으로 설정을 해야하는 부분이었다.

    let playerGuessString = String(playerGuess)
    let answerString = String(answer)
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[2가지 사칙연산 함수]]></title>
            <link>https://velog.io/@lets_make_app/2%EA%B0%80%EC%A7%80-%EC%82%AC%EC%B9%99%EC%97%B0%EC%82%B0-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@lets_make_app/2%EA%B0%80%EC%A7%80-%EC%82%AC%EC%B9%99%EC%97%B0%EC%82%B0-%ED%95%A8%EC%88%98</guid>
            <pubDate>Thu, 07 Mar 2024 10:37:35 GMT</pubDate>
            <description><![CDATA[<p>부트캠프의 첫 개인과제: 계산기</p>
<p>강의를 다 듣고 또 들어봤지만, 일단 뭔지는 알겠는데... 정확히는 모르겠고...
그래도 제출이 금요일까지라 일단 시도해보기로 했다.</p>
<p>처음 작성한 방식:</p>
<pre><code class="language-swift">class Calculator {

    var num1: Double
    var num2: Double

    init(num1: Double, num2: Double) {
        self.num1 = num1
        self.num2 = num2
    }

    func add() {
        print(&quot;Answer is \(num1 + num2)&quot;)
        }

    func subtract() {
        print(&quot;Answer is \(num1 - num2)&quot;)
        }

    func divide() {
        print(&quot;Answer is \(num1 / num2)&quot;)
        }

    func multiply() {
        print(&quot;Answer is \(num1 * num2)&quot;)
        }
}

let calculator = Calculator(num1: 10, num2: 3)
calculator.add()
calculator.subtract()

이 방식은 2개의 수만 나온다면 잘 활용될 수 있는 방식이지만,
내가 두 수의 합과 곱하기를 알고 싶다면 다시 calculator를 불러서 구현을 해야한다는 단점이 있었다.

그래서 시도한 방법:

class Calculator {

    func add(num1: Double, num2: Double) -&gt; Double {
        return num1 + num2
    }
    func sub(num1: Double, num2: Double) -&gt; Double {
        return num1 - num2
    }
    func multiply(num1: Double, num2: Double) -&gt; Double {
        return num1 * num2
    }
    func divide(num1: Double, num2: Double) -&gt; Double {
        return num1 / num2
    }
}

let calcu = Calculator()
calcu.add(num1: 2, num2: 4)
calcu.sub(num1: 2, num2: 5)
calcu.multiply(num1: 2, num2: 5)
calcu.divide(num1: 4, num2: 3)

이 방식은 위에와 반대로, 2개의 수만 다룬다면, 비효율적이다.
하지만, 왠지 다른 수를 자유롭게 원하는 사칙연산에 넣을 수 있다라는 점이 마음에 들어서 위에 방법으로 결정했다.</code></pre>
<p>오늘의 일등공신 chatGPT.</p>
]]></description>
        </item>
    </channel>
</rss>