<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>code_dang.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sat, 02 Mar 2024 14:18:51 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>code_dang.log</title>
            <url>https://velog.velcdn.com/images/code_dang/profile/9b4acfde-c5f3-459f-ba4b-dbf8a97ea496/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. code_dang.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/code_dang" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[VSCod 단축키, HTML 주석]]></title>
            <link>https://velog.io/@code_dang/VSCod-%EB%8B%A8%EC%B6%95%ED%82%A4</link>
            <guid>https://velog.io/@code_dang/VSCod-%EB%8B%A8%EC%B6%95%ED%82%A4</guid>
            <pubDate>Sat, 02 Mar 2024 14:18:51 GMT</pubDate>
            <description><![CDATA[<p>ctrl + B : 매뉴 닫기
ctrl + F : 검색창
ctrl + H : 검색 단어 변환창
Tab : 들여쓰기
shift + Tab : 밀어쓰기</p>
<p>ctrl + P : 모든파일 표시(폴더내)
ctrl + shift + P : 모든명령 표시
ctrl + W : 편집기 닫기</p>
<p>ctrl + \ : 편집기 분할 
ctrl + page up : 편집기 왼쪽으로 전환 
ctrl + page down : 편집기 오른쪽으로 전환 
alt + right, left 방향키 : 편집기 전환</p>
<p>ctrl + alt + L : Beautify(익스텐션) 코드정리</p>
<p>alt + up, down 방향키 : 줄 이동
alt + shift + up, down 방향키 : 줄 복사</p>
<br>
<br>
HTML 주석처리방법

<pre><code class="language-html">&lt;!-- 내용 --&gt;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[기술면접 준비]]></title>
            <link>https://velog.io/@code_dang/%EA%B8%B0%EC%88%A0%EB%A9%B4%EC%A0%91-%EC%A4%80%EB%B9%84</link>
            <guid>https://velog.io/@code_dang/%EA%B8%B0%EC%88%A0%EB%A9%B4%EC%A0%91-%EC%A4%80%EB%B9%84</guid>
            <pubDate>Tue, 19 Dec 2023 13:14:10 GMT</pubDate>
            <description><![CDATA[<h3 id="1-ios-앱의-생명주기-이벤트앱-시작-백그라운드-이동-등를-이해하고-처리하는-방법은-무엇인가요">1. iOS 앱의 생명주기 이벤트(앱 시작, 백그라운드 이동 등)를 이해하고 처리하는 방법은 무엇인가요?</h3>
<p>앱의 생명주기 이벤트를 처기하기위해선 UIApplicationDelegate 프로토콜을 준수하는 클래스에서 이벤트에 대한 메서드를 구현해야 합니다.
앱이 시잘될 때 application(<em>:didFinishLaunchingWithOptions:) 매써드가 호출되어 앱의 초기화와 초기 설정을 수행합니다.
앱이 활성화되면 applicationDidBecomeActive(</em>:) 이 호출되어 UI업데이트와 사용자와의 상호작용을 처리합니다.
앱이 백그라운드로 이동할때는 applicationDidEnterBackground(<em>:) 가 호출되며 앱이 백그라운드에서 실행되는 동안 필요한 작업들을 수행합니다.
applicationWillEnterForeground(</em>:) 는 앱이 백그라운드에서 활성 상태로 전환되기 직전에 호출되며 화면 업데이트나 다른 초기화 작업을 수행합니다.
applicationWillTerminate(_:)는 앱이 종료될 때 호출됩니다. 이때 마지막으로 저장되지 앟ㄴ는 데이터를 저장하거나 정리하는 작업을 수행합니다.</p>
<p>iOS 앱의 생명주기 이벤트는 앱이 시작되고 종료되는 과정 및 앱이 활성 상태에서 백그라운드 상태로 이동하거나 백그라운드 상태에서 다시 활성 상태로 복귀하는 과정을 다룹니다. 앱의 생명주기 이벤트를 처리하려면 UIApplicationDelegate 프로토콜을 준수하는 클래스에서 이벤트에 대한 메서드를 구현해야 합니다. 아래에서 주요 생명주기 이벤트와 그에 대응하는 메서드를 설명하겠습니다:</p>
<ul>
<li>앱 시작 (App Launch):<ul>
<li>application(_:didFinishLaunchingWithOptions:): 앱이 처음 시작될 때 호출됩니다. 앱의 초기화 및 설정을 수행합니다.</li>
</ul>
</li>
<li>활성 상태 (Active State):<ul>
<li>applicationDidBecomeActive(_:): 앱이 활성 상태가 되면 호출됩니다. 이때 사용자와 상호작용이 가능한 상태입니다. 화면이 표시되고 사용자 입력을 받을 수 있습니다.</li>
<li>applicationWillResignActive(_:): 앱이 비활성 상태로 전환되기 직전에 호출됩니다. 예를 들어 전화가 왔을 때나 백그라운드로 전환될 때 호출됩니다.</li>
</ul>
</li>
<li>백그라운드 상태 (Background State):<ul>
<li>applicationDidEnterBackground(_:): 앱이 백그라운드 상태로 전환될 때 호출됩니다. 이 상태에서는 일반적으로 앱이 백그라운드에서 실행되는 동안 필요한 정리 작업을 수행합니다.</li>
<li>applicationWillEnterForeground(_:): 앱이 백그라운드에서 활성 상태로 전환되기 직전에 호출됩니다. UI를 업데이트하거나 다른 초기화 작업을 수행할 수 있습니다.</li>
</ul>
</li>
<li>종료 (Termination):<ul>
<li>applicationWillTerminate(_:): 앱이 종료될 때 호출됩니다. 이때 마지막으로 저장되지 않은 데이터를 저장하거나 정리 작업을 수행할 수 있습니다.</li>
</ul>
</li>
</ul>
<p>이러한 메서드를 사용하여 앱의 상태 변화에 따라 적절한 작업을 수행할 수 있습니다. 예를 들어, 백그라운드 상태에서 데이터를 저장하거나 활성 상태로 복귀할 때 UI를 업데이트하는 작업을 처리할 수 있습니다.
또한 iOS 13부터는 SceneDelegate가 도입되어 멀티-윈도우 환경에서 앱의 생명주기 이벤트를 더 세밀하게 관리할 수 있게 되었습니다. SceneDelegate를 사용하면 앱의 여러 화면을 병렬로 다루는 데 도움이 됩니다.
앱의 생명주기 이벤트를 처리할 때 주의할 점은 백그라운드 상태에서 실행 중에 시간 제한이 있고, 메모리 경고와 같은 제한이 있을 수 있다는 것입니다. 앱이 백그라운드로 이동하거나 종료될 때 데이터를 저장하고 작업을 중단할 적절한 시점을 신중하게 처리해야 합니다.</p>
<ul>
<li>application(_:didFinishLaunchingWithOptions:): 앱이 초기화된 직후에 호출되며 초기 설정 및 데이터 로딩을 수행합니다.</li>
<li>applicationDidBecomeActive(_:): 앱이 활성화된 직후에 호출되며 UI 업데이트 및 사용자 상호작용을 처리합니다.</li>
<li>applicationDidEnterBackground(_:): 앱이 백그라운드로 이동할 때 호출되며 데이터 저장 및 정리를 수행합니다.</li>
<li>applicationWillEnterForeground(_:): 앱이 백그라운드에서 다시 활성화될 때 호출되며 초기화 및 화면 업데이트를 수행합니다.</li>
<li>applicationWillTerminate(_:): 앱이 종료되기 직전에 호출되며 데이터 저장 또는 마지막 작업을 수행합니다.</li>
</ul>
<h3 id="2-뷰-컨트롤러-사이를-전환하는-방법에-대해서-설명해주세요">2. 뷰 컨트롤러 사이를 전환하는 방법에 대해서 설명해주세요.</h3>
<p>다양한 전환 방법들이 있습니다. 먼저 UINavigationController 이용한 화면전환의 경우 스택형식으로 뷰 컨트롤러를 관리하며 이전화면으로 돌아가기 용이합니다.
UITapbarController 의 경우 탭 바를 통하여 여러 뷰컨트롤러들의 화면을 전환합니다.
Present 를 사용할 경우 모달 형식으로 뷰컨트롤러를 표시하며 현재 화면 위에 새로운 화면을 띄울때 사용됩니다.  </p>
<p>iOS 앱에서 뷰 컨트롤러 간의 전환은 앱 내에서 다양한 화면 간의 이동을 관리하는 중요한 부분입니다. 뷰 컨트롤러 사이의 전환은 사용자 경험을 개선하고 다양한 기능을 제공하는 데 사용됩니다. 뷰 컨트롤러 간의 전환을 처리하는 방법은 다음과 같습니다:</p>
<ul>
<li>Segue (스토리보드에서의 전환):<ul>
<li>스토리보드를 사용하여 뷰 컨트롤러 간의 전환을 정의할 수 있습니다. 스토리보드에서 컨트롤러 간에 연결된 세그웨이(segue)를 생성하고 목적 뷰 컨트롤러를 지정합니다.</li>
<li>세그웨이의 활성화는 주로 사용자 동작(버튼 탭 등)에 의해 트리거됩니다.</li>
<li>prepare(for:sender:) 메서드를 사용하여 전환 전에 데이터를 전달하거나 설정할 수 있습니다.</li>
</ul>
</li>
<li>프로그래밍 방식으로 뷰 컨트롤러 전환:<ul>
<li>코드로 뷰 컨트롤러를 생성하고 화면 간의 전환을 관리할 수 있습니다.</li>
<li>UINavigationController를 사용하여 스택 기반의 뷰 컨트롤러 전환을 처리할 수 있습니다. pushViewController(_:animated:) 및 popViewController(animated:) 메서드를 사용하여 새로운 뷰 컨트롤러를 스택에 푸시하거나 팝할 수 있습니다.</li>
<li>present(_:animated:completion:) 메서드를 사용하여 모달로 뷰 컨트롤러를 표시할 수 있습니다.</li>
<li>dismiss(animated:completion:) 메서드를 사용하여 모달 뷰 컨트롤러를 닫을 수 있습니다.</li>
</ul>
</li>
<li>Tab Bar Controller:<ul>
<li>탭 바 컨트롤러는 여러 뷰 컨트롤러를 탭 바 아이템으로 구성하여 사용자가 간단하게 전환할 수 있는 인터페이스를 제공합니다.</li>
</ul>
</li>
<li>다른 컨트롤러와의 연결:<ul>
<li>뷰 컨트롤러는 present(<em>:animated:completion:), dismiss(animated:completion:), pushViewController(</em>:animated:), popViewController(animated:) 등의 메서드를 사용하여 다른 뷰 컨트롤러와의 전환을 처리할 수 있습니다.</li>
</ul>
</li>
</ul>
<ul>
<li>UINavigationController: 스택 형식으로 뷰 컨트롤러를 관리하며, 이전 화면으로 돌아가거나 새로운 화면으로 이동할 때 사용됩니다.</li>
<li>UITabBarController: 탭 바를 통해 여러 뷰 컨트롤러 간을 전환할 수 있습니다.</li>
<li>present(_:animated:completion:): 모달 형식으로 뷰 컨트롤러를 표시하고 현재 화면 위에 새로운 화면을 띄울 때 사용됩니다.</li>
</ul>
<h3 id="3-프로퍼티-옵저버property-observer에-대해서-설명해주세요-didset-willset-난이도--중">3. 프로퍼티 옵저버(Property Observer)에 대해서 설명해주세요. (didSet, willSet) 난이도 : 중</h3>
<p>프로퍼티 옵저버는 Swift 프로그래밍 언어에서 제공하는 기능 중 하나로, 클래스, 구조체, 또는 열거형의 프로퍼티에 할당되는 값의 변화를 감시하고 이에 반응하는 코드를 작성하는 데 사용됩니다.
willSet 은 프로퍼티에 새로운 값이 할당되기 직전에 호출되는 프로퍼티옵저버로 프로퍼티 값이 변화할때 실행할 작업을 정의합니다.
didSet 은 변화되기 이전의 값을 oldValue 라는 프로퍼티로 제공합니다.
willSet 은 새로 변화된 값을 newValue 라는 프로퍼티로 제공합니다.</p>
<p>프로퍼티 옵저버(Property Observer)는 Swift 프로그래밍 언어에서 제공하는 기능 중 하나로, 클래스, 구조체, 또는 열거형의 프로퍼티에 할당되는 값의 변화를 감시하고 이에 반응하는 코드를 작성하는 데 사용됩니다. 프로퍼티 옵저버는 프로퍼티의 값이 변경되는 시점에 자동으로 호출되며, 두 가지 주요 형태가 있습니다.</p>
<ul>
<li>willSet: willSet은 프로퍼티에 새로운 값이 할당되기 직전에 호출되는 프로퍼티 옵저버입니다. 이 시점에서 프로퍼티의 현재 값(newValue 라는 기본 매개변수 이름으로 사용 가능)과 새로 할당될 값이 제공됩니다. willSet 블록 내에서 이전 값과 새로운 값에 대한 추가 작업을 수행할 수 있습니다. swift  Copy codevar myProperty: Int = 0 { willSet(newPropertyValue) { print(&quot;현재 값: (myProperty)&quot;) print(&quot;새로운 값: (newPropertyValue)&quot;) } }   </li>
<li>didSet: didSet은 프로퍼티에 새로운 값이 할당된 직후에 호출되는 프로퍼티 옵저버입니다. 이 시점에서 프로퍼티의 이전 값(oldValue 라는 기본 매개변수 이름으로 사용 가능)과 현재 값이 제공됩니다. didSet 블록 내에서 새로운 값과 이전 값에 대한 추가 작업을 수행할 수 있습니다. swift  Copy codevar myProperty: Int = 0 { didSet(oldPropertyValue) { print(&quot;이전 값: (oldPropertyValue)&quot;) print(&quot;현재 값: (myProperty)&quot;) } }   
프로퍼티 옵저버의 사용 사례:</li>
<li>값의 변화를 추적하고 로깅 또는 디버깅 목적으로 사용합니다.</li>
<li>값의 변화에 따라 다른 프로퍼티나 메서드 호출을 활성화 또는 비활성화합니다.</li>
<li>값의 유효성을 검사하고, 유효하지 않은 경우 특정 작업을 수행합니다.</li>
<li>프로퍼티의 값 변경에 따라 UI 업데이트 또는 다른 동작을 트리거합니다.
프로퍼티 옵저버는 계산된 프로퍼티(computed properties)에는 적용할 수 없고, 저장 프로퍼티(stored properties)와 지연 저장 프로퍼티(lazy stored properties)에만 사용할 수 있습니다. 프로퍼티 옵저버를 사용하여 프로퍼티의 값 변화를 감시하고 제어하는 것은 애플리케이션의 로직과 동작을 더욱 정확하고 예측 가능하게 만드는 데 도움이 됩니다.</li>
</ul>
<ul>
<li>프로퍼티 옵저버는 저장 프로퍼티의 값이 변하는 것을 관찰하기 위해 사용합니다. didSet, willSet 을 사용해 프로퍼티의 값이 변화할 때에 실행할 작업을 정의할 수 있습니다.</li>
<li>didSet: 변화되기 전의 값을 oldValue라는 프로퍼티로 제공합니다.</li>
<li>willSet: 새로 변화될 값을 newValue라는 프로퍼티로 제공합니다.</li>
</ul>
<h3 id="4-bound와-frame의-차이에-대해서-설명해주세요-난이도--중">4. bound와 frame의 차이에 대해서 설명해주세요. 난이도 : 중</h3>
<p>frame은 뷰가 부모 뷰의 좌표 시스템 내에서 위치하고 크기를 나타내는 프로퍼티이며 UIView의 위치나 크기를 설정할 때 사용합니다.
반면에 bounds는 뷰 자체의 좌표 시스템에서 위치와 크기를 나타내며 View의 크기를 알고싶거나 View 내부의 뷰를 그랠때 사용됩니다.</p>
<ul>
<li>frame : 상위 뷰의 좌표 시스템에서 상대적인 위치(x, y) 와 크기(width, height)를 나타냅니다(사각형). frame은 UIView의 위치나 크기를 설정할 때 사용합니다.</li>
<li>bounds : 자신의 좌표 시스템 (0, 0)를 기준으로 위치 (x, y) 와 크기(width, height)를 나타냅니다(사각형). bounds는 View의 크기를 알고 싶거나 View 내부에 뷰를 그릴 때 사용합니다.</li>
</ul>
<h3 id="5-codable-프로토콜을-사용하여-json-데이터를-swift-객체로-어떻게-디코딩하나요">5. Codable 프로토콜을 사용하여 JSON 데이터를 Swift 객체로 어떻게 디코딩하나요?</h3>
<p>먼저 Codable 프로토콜을 준수하는 Swift 구조체 또는 클래스를 정의해준 후 JSON 데이터를 가져옵니다. 그리고 JSON 데이터를 Swift 객체로 디코딩하기 위해 JSONDecoder를 사용해준 후 JSONDecoder를 통해 디코딩한 객체를 사용하면 됩니다.</p>
<p>Codable 프로토콜을 사용하여 JSON 데이터를 Swift 객체로 디코딩(복원)하는 과정은 다음과 같습니다:</p>
<ul>
<li>JSON 데이터와 Swift 객체 간의 대응 관계를 정의합니다.</li>
<li>JSON 데이터를 Swift 객체로 디코딩합니다.
아래는 단계별로 설명한 방법입니다.</li>
</ul>
<ol>
<li>JSON 데이터와 Swift 객체 간의 대응 관계 정의
먼저, JSON 데이터의 구조와 Swift 객체의 구조를 맞춰야 합니다. Swift 객체를 디코딩하기 위해 Codable 프로토콜을 준수하는 Swift 구조체 또는 클래스를 정의해야 합니다. Codable을 준수하는 객체는 JSON 키와 객체의 속성을 매핑할 수 있어야 합니다. 예를 들어, 다음은 JSON 데이터와 매핑될 수 있는 Swift 구조체의 예제입니다:
swift</li>
</ol>
<p>Copy code
struct Person: Codable { var name: String var age: Int var email: String? }
위의 Person 구조체는 JSON 데이터의 &quot;name&quot;, &quot;age&quot;, &quot;email&quot; 키와 객체의 속성을 매핑할 수 있습니다. Codable 프로토콜은 Decodable과 Encodable 프로토콜을 결합한 것으로, 데이터를 디코딩하고 인코딩하는 데 사용됩니다.
2. JSON 데이터를 Swift 객체로 디코딩
이제 정의한 Swift 객체를 사용하여 JSON 데이터를 디코딩합니다. Swift에서는 JSONDecoder 클래스를 사용하여 JSON 데이터를 디코딩할 수 있습니다. 아래는 디코딩하는 예제 코드입니다:
swift</p>
<pre><code class="language-swift">Copy code
import Foundation // JSON 데이터를 담은 Data 객체 
let jsonData = &quot;&quot;&quot; { &quot;name&quot;: &quot;John Doe&quot;, &quot;age&quot;: 30, &quot;email&quot;: &quot;john@example.com&quot; } &quot;&quot;&quot;.data(using: .utf8)! do { // JSONDecoder를 생성 
let decoder = JSONDecoder() // JSON 데이터를 Swift 객체로 디코딩 
let person = try decoder.decode(Person.self, from: jsonData) // 디코딩된 객체를 사용 
print(&quot;Name: \(person.name)&quot;) print(&quot;Age: \(person.age)&quot;) if let email = person.email { print(&quot;Email: \(email)&quot;) } } catch { print(&quot;디코딩 오류: \(error.localizedDescription)&quot;) }</code></pre>
<p>위 코드에서 Person 구조체를 사용하여 JSON 데이터를 디코딩하고, 결과 객체를 person 상수에 저장합니다. 만약 디코딩 중에 오류가 발생하면 catch 블록에서 해당 오류를 처리할 수 있습니다.
이렇게 하면 JSON 데이터를 Codable 프로토콜을 준수하는 Swift 객체로 쉽게 디코딩할 수 있습니다.</p>
<ul>
<li>Codable 프로토콜을 준수하는 Swift 구조체 또는 클래스를 정의합니다.</li>
<li>JSON 데이터를 가져옵니다.</li>
<li>JSON 데이터를 Swift 객체로 디코딩하기 위해 JSONDecoder를 사용합니다.</li>
<li>JSONDecoder를 통해 디코딩한 객체를 사용합니다.</li>
</ul>
<h3 id="6-auto-layout에서-스택-뷰와-같은-컨테이너-뷰의-역할과-사용법은-무엇인가요">6. Auto Layout에서 스택 뷰와 같은 컨테이너 뷰의 역할과 사용법은 무엇인가요?</h3>
<p>Auto Layout에서 컨테이너 뷰의 역할은 UI요소들을 간편하게 정렬하거나 배치하는데 사용됩니다. 스택 뷰는 하위 뷰를 수직 또는 수평으로 배열하고 간격을 조절할 수 있습니다. 컨테이너 뷰는  동적인 크기 조정 및 화면 회전에 대응하기 용이하며 간단한 인터페이스 구성 요소들을 모아놓았기 때문에 레이아웃 관리에 효과적입니다. </p>
<p>Auto Layout에서 스택 뷰(Stack View)는 화면 레이아웃을 관리하는 유용한 컨테이너 뷰 중 하나입니다. 스택 뷰는 뷰 계층 구조 내에서 여러 하위 뷰(서브뷰)를 수직 또는 수평으로 배열하는 데 사용됩니다. 스택 뷰의 역할과 사용법은 다음과 같습니다:</p>
<ol>
<li>스택 뷰의 역할:</li>
</ol>
<ul>
<li>레이아웃 관리: 스택 뷰는 포함된 하위 뷰의 크기 및 위치를 자동으로 관리합니다. 이를 통해 Auto Layout 제약 조건을 개별적으로 설정하지 않고도 레이아웃을 구축할 수 있습니다.</li>
<li>다양한 정렬 방식: 스택 뷰는 하위 뷰를 수직으로 또는 수평으로 정렬할 수 있으며, 간격과 여백을 지정할 수 있습니다. 또한 하위 뷰의 크기를 균일하게 맞출 수도 있습니다.</li>
<li>동적 크기 조정: 스택 뷰는 하위 뷰의 크기 조정을 자동으로 처리하므로, 화면 크기 또는 내용의 변경에 따라 스택 뷰와 하위 뷰가 동적으로 조정됩니다.</li>
</ul>
<ol start="2">
<li>스택 뷰 사용법:</li>
</ol>
<ul>
<li>스토리보드 또는 코드로 생성: 스택 뷰는 스토리보드를 사용하여 뷰 컨트롤러의 인터페이스를 구성하거나 코드를 사용하여 생성할 수 있습니다.</li>
<li>하위 뷰 추가: 스택 뷰에 하위 뷰를 추가하려면 스택 뷰의 arrangedSubviews 배열에 하위 뷰를 추가합니다. 이 배열에서의 순서가 스택 뷰에 표시되는 순서를 결정합니다.</li>
<li>정렬 및 간격 지정: 스택 뷰의 방향(수평 또는 수직)과 간격을 설정합니다. 간격은 하위 뷰 사이 또는 주위에 적용할 수 있으며, 균등한 간격을 사용하거나 커스텀 간격을 지정할 수 있습니다.</li>
<li>크기 및 우선순위 설정: 각 하위 뷰에 대해 크기(너비 또는 높이)와 우선순위(높을수록 우선)를 설정하여 레이아웃을 세밀하게 제어할 수 있습니다.</li>
<li>내용에 따른 크기 조정: 스택 뷰는 하위 뷰의 내용에 따라 동적으로 크기를 조정할 수 있습니다.</li>
<li>간격 및 정렬 변경: 화면 크기 또는 내용 변경에 따라 스택 뷰 내부 레이아웃이 동적으로 조정됩니다.
스택 뷰는 복잡한 레이아웃을 단순화하고 관리하기 위한 강력한 도구로, 특히 동적 컨텐츠를 가진 사용자 인터페이스를 구축하는 데 매우 유용합니다. Auto Layout과 함께 사용하면 화면 크기와 내용 변화에 대응하는 유연한 레이아웃을 만들 수 있습니다.</li>
</ul>
<p>Auto Layout에서 스택 뷰와 같은 컨테이너 뷰의 역할은 UI 요소를 간단하게 정렬 및 배치하는 데 도움을 줍니다. 스택 뷰는 하위 뷰를 수직 또는 수평으로 배열하고 간격을 조정할 수 있으며, 동적인 크기 조정 및 화면 회전에 대응하기 용이합니다. 간단한 인터페이스 구성 요소를 묶어서 레이아웃을 효과적으로 관리하고 코드를 최소화합니다.</p>
<h3 id="7-grand-central-dispatch-gcd와-operation-queue의-차이점은-무엇인가요">7. Grand Central Dispatch (GCD)와 Operation Queue의 차이점은 무엇인가요?</h3>
<p>Grand Central Dispatch는 iOS 앱에서 다중 스레딩 및 병렬 작업 처리를 위한 저수준 API입니다. GCD는 큐와 블록을 사용하여 작업을 관리하며 스레드 풀을 자동으로 관리합니다.
반면, Operation Queue는 GCD 위에 구축된 고수준 API로, 작업(Operation)을 사용하여 작업 관리 및 의존성을 관리할 수 있습니다. Operation Queue는 GCD를 내부적으로 사용하며 추가적인 기능을 제공합니다.
Operation은 Task의 실행, 정지, 대기 같은 State를 알 수 있고, 이들의 취소, 순서 지정이 가능합니다.
Operation State에는 ready, executing, finished, cancelled 상태들이 있습니다.</p>
<p>Grand Central Dispatch (GCD)와 Operation Queue는 다중 스레드 환경에서 작업을 관리하는 데 사용되는 두 가지 다른 메커니즘입니다. 이들 간의 주요 차이점은 다음과 같습니다:</p>
<ul>
<li>추상화 수준:<ul>
<li>GCD: GCD는 낮은 수준의 C 언어 API로, 스레드와 큐의 개념을 사용하여 작업을 관리합니다. 직접 스레드 관리와 큐 처리가 필요하며, 작업간의 의존성을 명시적으로 처리해야 합니다.</li>
<li>Operation Queue: Operation Queue는 더 높은 수준의 객체 지향 API로, Operation 및 OperationQueue 클래스를 사용하여 작업을 추상화하고 의존성을 처리합니다. 이로 인해 더 간단한 작업 관리 및 작업의 실행 순서를 지정하는 데 도움이 됩니다.</li>
</ul>
</li>
<li>의존성 관리:<ul>
<li>GCD: GCD는 작업간의 의존성을 수동으로 설정해야 합니다. 이것은 작업이 다른 작업이 완료되기를 기다리거나 여러 작업이 동시에 실행되는 것을 관리해야 할 때 복잡성을 증가시킬 수 있습니다.</li>
<li>Operation Queue: Operation Queue는 Operation 객체를 사용하여 작업의 의존성을 간단하게 설정할 수 있습니다. 이렇게 하면 작업 간의 실행 순서를 쉽게 제어할 수 있습니다.</li>
</ul>
</li>
<li>취소 및 일시 중지:<ul>
<li>GCD: GCD는 작업을 취소하거나 일시 중지하는 메커니즘을 제공하지만 이것을 직접 구현해야 합니다.</li>
<li>Operation Queue: Operation Queue는 작업을 쉽게 취소하고 일시 중지하며 작업의 상태를 관리하는 기능을 제공합니다.</li>
</ul>
</li>
<li>재사용성:<ul>
<li>GCD: GCD는 코드에서 직접 구현되므로 더 낮은 수준의 작업을 처리할 때 유용하며 코드가 더 직접적입니다.</li>
<li>Operation Queue: Operation Queue는 높은 수준의 추상화를 제공하므로 더 복잡한 작업을 관리하는 데 유용하며 코드가 더 추상적입니다.
일반적으로 GCD는 간단한 비동기 작업을 처리할 때 유용하며, Operation Queue는 더 복잡하거나 의존성이 있는 작업을 처리할 때 유용합니다. 프로젝트의 요구 사항에 따라 어떤 메커니즘을 선택할지 결정할 수 있으며, 두 가지를 혼합하여 사용할 수도 있습니다.</li>
</ul>
</li>
</ul>
<p>Grand Central Dispatch(GCD)는 iOS 앱에서 다중 스레딩 및 병렬 작업 처리를 위한 저수준 API입니다. GCD는 큐와 블록을 사용하여 작업을 관리하며 스레드 풀을 자동으로 관리합니다.
반면, Operation Queue는 GCD 위에 구축된 고수준 API로, 작업(Operation)을 사용하여 작업 관리 및 의존성을 관리할 수 있습니다. Operation Queue는 GCD를 내부적으로 사용하며 추가적인 기능을 제공합니다.
Operation은 Task의 실행, 정지, 대기 같은 State를 알 수 있고, 이들의 취소, 순서 지정이 가능합니다.
Operation State에는 ready, executing, finished, cancelled 상태들이 있습니다.</p>
<h3 id="8-탈출-클로저escaping-closure에-대해-설명해주세요">8. 탈출 클로저(escaping closure)에 대해 설명해주세요.</h3>
<p>탈출 클로저(escaping closure)는 스위프트에서 클로저의 특성 중 하나로, 클로저가 함수 외부에서 저장되거나 다른 함수로 전달되어 나중에 호출될 수 있는 경우를 가리킵니다. 이는 비동기 작업이나 콜백 기반의 API와 같은 상황에서 주로 사용됩니다.
탈출 클로저를 이해하기 위해 몇 가지 핵심 개념을 살펴보겠습니다:</p>
<ul>
<li>클로저의 범위(scope): 클로저는 주로 그 클로저가 정의된 함수 내에서 사용됩니다. 일반적으로 함수 내부에서 정의된 클로저는 함수 내부에서 호출되며, 함수의 실행이 완료되면 그 클로저는 사라집니다. 이를 비탈출 클로저(Non-escaping closure)라고 합니다.</li>
<li>탈출 클로저(Escaping Closure): 반면, 탈출 클로저는 함수 내부에서 정의되었지만 함수 외부로 &quot;탈출&quot;할 수 있는 클로저입니다. 이것은 클로저가 함수의 실행이 완료된 후에도 호출될 수 있다는 것을 의미합니다. 주로 비동기 작업, 콜백, 델리게이트 패턴 등에서 사용됩니다.
탈출 클로저의 사용 사례:</li>
<li>비동기 API: 비동기 작업이 완료된 후에 결과를 처리하기 위해 탈출 클로저를 사용할 수 있습니다.</li>
<li>델리게이트 패턴: 델리게이트 객체에 클로저를 저장하고 이 객체가 생명주기를 관리하기 위해 탈출 클로저를 사용할 수 있습니다.</li>
<li>클로저를 함수 외부로 반환: 함수가 클로저를 반환하고, 반환된 클로저가 함수 외부에서 호출될 때 탈출 클로저로 처리됩니다.
예를 들어, 비동기 작업을 수행하는 함수는 탈출 클로저를 인자로 받아 작업이 완료되면 클로저를 호출합니다. 이것은 비동기 호출이 완료되기 전에 함수가 반환되어도 클로저가 나중에 호출될 수 있기 때문입니다.
swift</li>
</ul>
<p>Copy code
func performAsyncTask(completion: @escaping () -&gt; Void) { // 비동기 작업을 수행하고 완료 시 클로저를 호출 DispatchQueue.global().async { // 작업 완료 completion() } } // 함수를 호출할 때 탈출 클로저를 전달 performAsyncTask { print(&quot;비동기 작업이 완료되었습니다.&quot;) }
여기서 @escaping 키워드는 클로저 매개변수가 탈출 클로저임을 나타냅니다. 탈출 클로저를 사용할 때 주의할 점은 메모리 누수를 방지하기 위해 적절한 시점에 클로저를 적절하게 해제해야 한다는 것입니다.</p>
<ul>
<li>Delegate pattern을 간단히 정의하자면 A 객체의 일(일부)을 B 객체에서 대신 하도록 일을 일임하는 패턴을 말합니다. 즉, 일부 객체의 책임을 다른 객체에게 위임 또는 전달할 수 있는 패턴입니다. 특정 객체에서 일어나는 이벤트 혹은 전송할 데이터에 관한 코드를 다른 객체에게 처리하는 것입니다.</li>
<li>대표적으로 UITableViewDelegate는 뷰 컨트롤러가 Delegate를 채택하여 Delegate 메서드를 정의하면, TableView의 동작이 일어났을 때 해당 Delegate 메서드를 호출하고 뷰 컨트롤러에 정의된 대로 뷰 컨트롤러에서 대신 일을 처리해줍니다.</li>
</ul>
<h3 id="9-구조체-정의">9. 구조체 정의</h3>
<p>구조체는 값 타입을 나타내는 데이터 유형입니다. 구조체는 객체를 만들 수 있는 사용자 정의 데이터 유형이며, 속성과 메서드를 포함할 수 있습니다. 값타입이란 구조체가 인스턴스를 복사하여 전달하거나 대입할 때 새로운 복사본을 생성한다는 것을 의미합니다. 이는 데이터를 안전하게 공유하거나 변경하지 않도록 보장하고 예기치 않은 동작을 방지하는 데 도움을 줍니다.
구조체는 클래스처럼 속성을 포함할 수 있고 구조체 내에서 메서드를 정의할 수 도 있습니다.
또 구조체는 extensions 을 사용할 수 도 있고 Codable을 준수하도록 만들 수 도 있어서 JSON 형식이 필요할 때 이용할 수 도 있습니다. 
구조체는 작은 데이터 모델이나 좌표와 범위같은 간단한 값, 그리고 메서드를 포함할 때 유용하게 사용되며 클래스와는 달리 값 타입으로서 테이터의 변경이 의도하지 않은 곳에서 영향을 주는것을 방지하는데 도움이 됩니다.</p>
<p>Swift에서 구조체(Structures)는 값 타입(Value Type)을 나타내는 데이터 유형입니다. 구조체는 객체를 만들 수 있는 사용자 정의 데이터 유형이며, 속성과 메서드를 포함할 수 있습니다. 구조체의 주요 특징은 다음과 같습니다:</p>
<ul>
<li>값 타입(Value Type): 구조체는 값 타입으로 처리됩니다. 이것은 구조체 인스턴스를 복사하여 전달하거나 대입할 때 새로운 복사본을 생성한다는 것을 의미합니다. 이는 데이터를 안전하게 공유하거나 변경하지 않도록 보장하고 예기치 않은 동작을 방지하는 데 도움이 됩니다.</li>
<li>속성(Properties): 구조체는 속성(프로퍼티)을 포함할 수 있으며, 이러한 속성은 구조체의 상태나 데이터를 나타냅니다.</li>
<li>메서드(Methods): 구조체는 메서드(함수)를 정의하여 특정 동작을 수행할 수 있습니다.</li>
<li>초기화(Initialization): 구조체는 초기화 메서드를 가질 수 있으며, 인스턴스를 생성할 때 이러한 초기화 메서드를 사용하여 속성을 초기화합니다.</li>
<li>확장(Extensions): 구조체에 대해 나중에 추가적인 메서드나 계산된 속성을 확장(Extensions)할 수 있습니다.</li>
<li>Codable 프로토콜 준수: 구조체는 Codable 프로토콜을 준수하도록 만들 수 있어, JSON 형식으로 직렬화하거나 역직렬화하는 데 사용됩니다.
일반적으로 구조체는 작은 데이터 모델, 좌표나 범위와 같은 간단한 값, 그리고 메서드를 포함할 때 유용합니다. 구조체는 클래스(class)와 달리 참조(reference) 타입이 아니기 때문에 데이터의 변경이 예기치 않게 다른 곳에서 영향을 주는 것을 방지하는 데 도움이 됩니다.
예시:
swift</li>
</ul>
<pre><code class="language-swift">Copy code
struct Point { var x: Double var y: Double // 초기화 메서드 
init(x: Double, y: Double) { self.x = x self.y = y } // 메서드 
func distanceToOrigin() -&gt; Double { return sqrt(x * x + y * y) } } var myPoint = Point(x: 3.0, y: 4.0) let distance = myPoint.distanceToOrigin() // 5.0</code></pre>
<p>위의 예시에서 Point 구조체는 x와 y 속성을 가지며, 거리 계산을 위한 distanceToOrigin 메서드를 포함합니다. 구조체의 인스턴스 myPoint는 값 타입이므로 변경 가능성이 없으며 새로운 복사본을 생성하여 값을 전달합니다.</p>
<h3 id="10-구조체struct의-mutating-키워드에-대해서-설명해주세요">10. 구조체(Struct)의 mutating 키워드에 대해서 설명해주세요.</h3>
<p>구조체 내의 메서드에서 속성 값을 변경하려면 mutating 를 사용해야 합니다. 이 키워드는 해당 메서드가 구조체 내부에서 속성을 수정할 수 있음을 의미합니다. 구조체는 기본적으로 값 타입이기 때문에 속성을 수정하려면 명시적으로 mutating 키워드를 사용해줘야 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] 콜렉션뷰 filter 기능 버튼 만들기 (2)]]></title>
            <link>https://velog.io/@code_dang/iosSwift-%EC%BD%9C%EB%A0%89%EC%85%98%EB%B7%B0-filter-%EA%B8%B0%EB%8A%A5-%EB%B2%84%ED%8A%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0-2</link>
            <guid>https://velog.io/@code_dang/iosSwift-%EC%BD%9C%EB%A0%89%EC%85%98%EB%B7%B0-filter-%EA%B8%B0%EB%8A%A5-%EB%B2%84%ED%8A%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0-2</guid>
            <pubDate>Thu, 09 Nov 2023 12:03:13 GMT</pubDate>
            <description><![CDATA[<p>이번엔 변경한 정보를 다른 페이지에서도 반영하도록 만들려고 한다.</p>
<p>&#39;String&#39; 정보들을 보낼 것이기 때문에 &#39;String&#39; 배열을 담을 수 있는 변수를 클로저를 이용하여 선언해줬다. 
그리고 스트링 정보들을 받아서 새로운 화면에서 반영할 매써드도 만들어줬다.</p>
<pre><code class="language-swift">var onConfirmation: (([String], [String]) -&gt; Void)?

 func updateOptionLabel(tier: String, position: String) {
 선택된 결과 반영... }
</code></pre>
<br>

<p>그리고 &#39;확인&#39;버튼을 눌렀을때 선택한 정보들을 onConfirmation 변수에 담아줬다.</p>
<pre><code class="language-swift">@objc func confirmationButtonTapped() {
        if let selectedTier = selectedTierOption,
           let selectedPosition = selectedPositionOption
        {
            onConfirmation?([selectedTier], [selectedPosition])
        }
        saveSelectedCellInfo()
        dismiss(animated: true, completion: nil)
    }</code></pre>
<br>
그리고 다른 페이지에서 받아온 정보를 updateOptionLabel 라벨에 넣어준다.


<pre><code class="language-swift"> @objc func searchOptionButtonTapped() {
        let searchOptionVC = SearchOptionVC()

        searchOptionVC.onConfirmation = { [weak self] selectedTier, selectedPosition in
            self?.selectedTier = selectedTier
            self?.selectedPosition = selectedPosition
            self?.updateOptionLabel(tier: selectedTier.first ?? &quot;&quot;, position: selectedPosition.first ?? &quot;&quot;)
            self?.viewWillAppear(true)
        }
        present(searchOptionVC, animated: true, completion: nil)
    }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] 콜렉션뷰 filter 기능 버튼 만들기 (1)]]></title>
            <link>https://velog.io/@code_dang/iosSwift-%EC%BD%9C%EB%A0%89%EC%85%98%EB%B7%B0-filter-%EA%B8%B0%EB%8A%A5-%EB%B2%84%ED%8A%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0-1</link>
            <guid>https://velog.io/@code_dang/iosSwift-%EC%BD%9C%EB%A0%89%EC%85%98%EB%B7%B0-filter-%EA%B8%B0%EB%8A%A5-%EB%B2%84%ED%8A%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0-1</guid>
            <pubDate>Tue, 07 Nov 2023 09:22:54 GMT</pubDate>
            <description><![CDATA[<p>콜렉션뷰로 필터기능을 가진 버튼을 만들기 위해 먼저 버튼과 이를 선택할 수 있는 기능을 먼저 만들었다.</p>
<p>셀을 탭했다는 정보를 저장하고 활용하기 위해 변수들을 선언해주었다.</p>
<pre><code class="language-swift">var selectedTierIndexPath: IndexPath?
var selectedPositionIndexPath: IndexPath?
var selectedTierOption: String?
var selectedPositionOption: String?</code></pre>
<br>

<p>그리고 유저디폴트를 사용하여 이를 저장하고 불러오는 매써드도 만들어주었다.</p>
<pre><code class="language-swift">func saveSelectedCellInfo() {
        let defaults = UserDefaults.standard
        defaults.set(selectedTierIndexPath?.row, forKey: &quot;selectedTierIndex&quot;)
        defaults.set(selectedPositionIndexPath?.row, forKey: &quot;selectedPositionIndex&quot;)
    }

    func loadSelectedCellInfo() {
        let defaults = UserDefaults.standard
        if let tierIndex = defaults.value(forKey: &quot;selectedTierIndex&quot;) as? Int,
           let positionIndex = defaults.value(forKey: &quot;selectedPositionIndex&quot;) as? Int
        {
            selectedTierIndexPath = IndexPath(row: tierIndex, section: 0)
            selectedPositionIndexPath = IndexPath(row: positionIndex, section: 1)
        }
    }</code></pre>
<br>

<p>그리고 이를 didSelectItemAt 에 적용하여 기능을 구현하였다. </p>
<pre><code class="language-swift"> func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        if indexPath.section == 0 {
            if indexPath == selectedTierIndexPath {
                // 이미 선택된 셀을 다시 탭한 경우, 선택 해제
                selectedTierIndexPath = nil
                selectedTierOption = &quot;default&quot;
                UserDefaults.standard.removeObject(forKey: &quot;selectedTierIndexPath&quot;)

                if let selectedCell = collectionView.cellForItem(at: indexPath) as? TierCell {
                    selectedCell.tierLabel.layer.borderColor = UIColor.systemGray4.cgColor

                }
            } else {
                if let previousIndexPath = selectedTierIndexPath {
                    if let previousCell = collectionView.cellForItem(at: previousIndexPath) as? TierCell {
                        previousCell.tierLabel.layer.borderColor = UIColor.systemGray4.cgColor
                    }
                }

                selectedTierIndexPath = indexPath

                if let selectedCell = collectionView.cellForItem(at: indexPath) as? TierCell {
                    selectedCell.tierLabel.layer.borderColor = UIColor.systemBlue.cgColor
                    selectedTierOption = tierName[indexPath.row]
                }
            }
        } else {
            if indexPath == selectedPositionIndexPath {
                // 이미 선택된 셀을 다시 탭한 경우, 선택 해제
                selectedPositionIndexPath = nil
                selectedPositionOption = &quot;default&quot;
                UserDefaults.standard.removeObject(forKey: &quot;selectedPositionIndexPath&quot;)

                if let selectedCell = collectionView.cellForItem(at: indexPath) as? PositionCell {
                    selectedCell.positionFrame.layer.borderColor = UIColor.systemGray4.cgColor
                }
            } else {
                if let previousIndexPath = selectedPositionIndexPath {
                    if let previousCell = collectionView.cellForItem(at: previousIndexPath) as? PositionCell {
                        previousCell.positionFrame.layer.borderColor = UIColor.systemGray4.cgColor
                    }
                }

                selectedPositionIndexPath = indexPath

                if let selectedCell = collectionView.cellForItem(at: indexPath) as? PositionCell {
                    selectedCell.positionFrame.layer.borderColor = UIColor.systemBlue.cgColor
                    selectedPositionOption = positionName[indexPath.row]
                }
            }
        }
    }</code></pre>
<p>위 코드로 </p>
<p>1) 선택된 셀의 보더컬러가 바뀌도록 만들었고 
2) 선택된 셀들을 변수들에 저장하여 활용할 수 있독록 만들었다.(다른 페이지로 정보 전달)
3) 유저디폴트에도 정보를 저장함으로 다시 필터기능 선택창을 열었을때 기존의 선택 정보가 반영되도록 만들었으며 
4) 선택된 셀을 다시 누른다면 선택을 취소시키고, 선택정보를 초기화시키는 기능을 구현하였다.  </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] Button 내 텍스트와 이미지 여백 추가하기]]></title>
            <link>https://velog.io/@code_dang/iosSwift-Button-%EB%82%B4-%ED%85%8D%EC%8A%A4%ED%8A%B8%EC%99%80-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%97%AC%EB%B0%B1-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@code_dang/iosSwift-Button-%EB%82%B4-%ED%85%8D%EC%8A%A4%ED%8A%B8%EC%99%80-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%97%AC%EB%B0%B1-%EC%B6%94%EA%B0%80%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 02 Nov 2023 12:07:34 GMT</pubDate>
            <description><![CDATA[<p>버튼 내에서도 텍스트나 이미지에 패팅값을 줄 수 있는 방법이 있는데 아래 메써드를 사용해주면 된다.</p>
<pre><code class="language-swift">button.titleEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
 button.imageEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
 button.contentEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)</code></pre>
<p>단 contentEdgeInsets 은 버튼 크기제약에는 영향을 주지 않기때문에 콘텐츠가 버튼을 벗어날 수도 있다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] SheetViewController (모달 화면 크기 커스텀)]]></title>
            <link>https://velog.io/@code_dang/iosSwift-SheetViewController-%EB%AA%A8%EB%8B%AC-%ED%99%94%EB%A9%B4-%ED%81%AC%EA%B8%B0-%EC%BB%A4%EC%8A%A4%ED%85%80</link>
            <guid>https://velog.io/@code_dang/iosSwift-SheetViewController-%EB%AA%A8%EB%8B%AC-%ED%99%94%EB%A9%B4-%ED%81%AC%EA%B8%B0-%EC%BB%A4%EC%8A%A4%ED%85%80</guid>
            <pubDate>Tue, 24 Oct 2023 08:54:22 GMT</pubDate>
            <description><![CDATA[<p>SwiftUI에서 Sheet은 모달 또는 팝업 스타일의 뷰를 표시하기 위해 사용되는 컴포넌트이다. Sheet를 사용하면 사용자에게 다른 뷰 위에 새로운 뷰를 나타낼 수 있어 사용자 경험을 향상시키는 데 도움을 준다.</p>
<p>Sheet를 표시하는 데 사용되는 뷰 컨트롤러가 SheetViewController이며 SheetViewController는 하위 뷰 또는 컨텐츠 뷰와 함께 모달 또는 팝업 스타일의 화면을 나타낸다.</p>
<p>이를 이용하여 모달로 화면을 전환할 때 높이를 커스텀할 수 있는데 detents 를 이용하며 예시는 다음과 같다.</p>
<br>

<h4 id="모달-창의-높이가-전체-화면의-중간">모달 창의 높이가 전체 화면의 중간</h4>
<pre><code class="language-swift">override func viewWillAppear(_ animated: Bool) {
        if let sheetPresentationController = sheetPresentationController {
            sheetPresentationController.detents = [.midium()]
        }
    }</code></pre>
<br>


<h4 id="화면의-높이를-임의로-커스텀">화면의 높이를 임의로 커스텀</h4>
<pre><code class="language-swift">override func viewWillAppear(_ animated: Bool) {
        if let sheetPresentationController = sheetPresentationController {
            sheetPresentationController.detents = [
                .custom { _ in
                    360
                }
            ]
        }
    }</code></pre>
<br>

<h4 id="모달-화면의-높이와-추가로-resizable-크기도-커스텀">모달 화면의 높이와 추가로 resizable 크기도 커스텀</h4>
<pre><code class="language-swift">if let sheet = viewController.sheetPresentationController {
    sheet.detents = [
        .custom { _ in
            return 360
        },
        .custom { context in
            return context.maximumDetentValue * 0.6
        }
    ]
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] 코드로 팝업 버튼 만들기]]></title>
            <link>https://velog.io/@code_dang/iosSwift-%EC%BD%94%EB%93%9C%EB%A1%9C-%ED%8C%9D%EC%97%85-%EB%B2%84%ED%8A%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@code_dang/iosSwift-%EC%BD%94%EB%93%9C%EB%A1%9C-%ED%8C%9D%EC%97%85-%EB%B2%84%ED%8A%BC-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Thu, 19 Oct 2023 14:09:15 GMT</pubDate>
            <description><![CDATA[<p>팝업 버튼을 만들기는 간단하다.</p>
<pre><code class="language-swift">let positionPopupButton: UIButton = {
        let button = UIButton()
        button.titleLabel?.font = .systemFont(ofSize: 15, weight: .medium)
        button.setTitle(&quot;&quot;, for: .normal)
        button.setTitleColor(.black, for: .normal)
        button.backgroundColor = .white
        button.layer.cornerRadius = (4)
        button.addTarget(self, action: #selector(positionPopUpButton), for: .touchUpInside)
        return button
    }()</code></pre>
<br>

<p>위와같이 먼저 버튼을 선언해 준 후</p>
<br>
<br>

<pre><code class="language-swift"> @objc private func positionPopUpButton() {
            let popUpButtonClosure = { (action: UIAction) in
                if action.title == &quot;1 번&quot; {
                    self.positionPopupButton.setTitle(&quot;1 번&quot;, for: .normal)
                }
                else if action.title == &quot;2 번&quot; {
                    self.positionPopupButton.setTitle(&quot;정2 번&quot;, for: .normal)
                }
                else if action.title == &quot;3 번&quot; {
                    self.positionPopupButton.setTitle(&quot;3 번&quot;, for: .normal)
                }
                else {
                }

                return
            }

        positionPopupButton.menu = UIMenu(title: &quot;위치선택&quot;, children: [
                UIAction(title: &quot;1 번&quot;, handler: popUpButtonClosure),
                UIAction(title: &quot;2 번&quot;, handler: popUpButtonClosure),
                UIAction(title: &quot;3 번&quot;, handler: popUpButtonClosure)
            ])

        positionPopupButton.showsMenuAsPrimaryAction = true
        }</code></pre>
<br>

<p>UIMenu 클래스를 이용한 팝업기능 매써드를 만들어 이어주면 된다.
그럼 아래와 같은 팝업창이 만들어진다.</p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/1bfb3ae3-1d49-4839-b62e-1550e86ce7de/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] 이미지에 틴트컬러 적용하기]]></title>
            <link>https://velog.io/@code_dang/iosSwift-%EC%9D%B4%EB%AF%B8%EC%A7%80%EC%97%90-%ED%8B%B4%ED%8A%B8%EC%BB%AC%EB%9F%AC-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@code_dang/iosSwift-%EC%9D%B4%EB%AF%B8%EC%A7%80%EC%97%90-%ED%8B%B4%ED%8A%B8%EC%BB%AC%EB%9F%AC-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 17 Oct 2023 11:25:29 GMT</pubDate>
            <description><![CDATA[<p>이미지의 색상만 변경할 수 있다면 얼마나 좋을까? 이를 위해 이것저것 알아보니 틴트컬러 적용을 통해 색상만 변경할 수 있음을 알아냈다.
그래서 틴트컬러를 적용하려 하니 적용되지 않는다.. 뭐가문제지?</p>
<br>




<pre><code class="language-swift"> let searchOptionButtonImage: UIImageView = {
        var imageView = UIImageView()
        let image = UIImage(named: &quot;optionIcon&quot;)
        imageView.image = image
        imageView.tintColor = UIColor.white
        return imageView
    }()</code></pre>
<br>
알아보니 해결책은 간단했다.

<br>
<br>


<pre><code class="language-swift">let searchOptionButtonImage: UIImageView = {
        var imageView = UIImageView()
        let image = UIImage(named: &quot;optionIcon&quot;)?.withRenderingMode(.alwaysTemplate)
        imageView.image = image
        imageView.tintColor = UIColor.white
        return imageView
    }()</code></pre>
<br>
withRenderingMode 를 붙여줌으로 해결했다.

<p>withRenderingMode 는 아래의 세 가지 옵션을 가지고있다.
틴트컬러에 적용하기 위해선 .alwaysOriginal 을 사용하면 된다.</p>
<pre><code class="language-swift">case automatic = 0 // Use the default rendering mode for the context where the image is used

case alwaysOriginal = 1 // Always draw the original image, without treating it as a template

case alwaysTemplate = 2 // Always draw the image as a template image, ignoring its color information요</code></pre>
<br>
<br>
<br>

<h3 id="버튼-이미지에-틴트컬러-적용하기">버튼 이미지에 틴트컬러 적용하기</h3>
<p>버튼 이미지에 틴트 컬러를 주는 방법도 꽤나 간단하다.
우선 버튼에는 setImage 라는 매써드로 이미지를 추가하게 되는데 예를 들면 이렇다.</p>
<pre><code class="language-swift"> let button: UIButton = {
            var button = UIButton()
            button.translatesAutoresizingMaskIntoConstraints = false
            button.titleLabel?.adjustsFontForContentSizeCategory = true
            button.setImage(UIImage(named: &quot;optionIcon&quot;), for: .normal)
            button.addTarget(self, action: #selector(searchOptionButtonTapped), for: .touchUpInside)
            return button
        }()</code></pre>
<br>

<p>위와 같이 코드를 짜주면 버튼에 이미지가 들어가는데 여기에 위 이미지에 틴트컬러를 넣어줬던 방법처럼 withRenderingMode 매써드를 추가해준 후 틴트컬러를 추가해주면 된다.</p>
<br>


<pre><code class="language-swift"> let button: UIButton = {
            var button = UIButton()
            button.translatesAutoresizingMaskIntoConstraints = false
            button.titleLabel?.adjustsFontForContentSizeCategory = true
            button.setImage(UIImage(named: &quot;optionIcon&quot;)? .withRenderingMode(.alwaysTemplate), for: .normal)
            button.tintColor = .white
            button.addTarget(self, action: #selector(searchOptionButtonTapped), for: .touchUpInside)
            return button
        }()</code></pre>
<p>이렇게 하면 버튼에도 이미지와 틴트컬러를 모두 적용가능하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] Result]]></title>
            <link>https://velog.io/@code_dang/iosSwift-Result</link>
            <guid>https://velog.io/@code_dang/iosSwift-Result</guid>
            <pubDate>Thu, 21 Sep 2023 06:54:05 GMT</pubDate>
            <description><![CDATA[<p>Swift에서 Result는 주로 에러 처리를 위해 사용되는 제네릭 열거형(Enumeration)입니다. Result를 사용하면 함수나 메서드에서 성공 또는 실패를 반환할 때 명시적으로 처리할 수 있습니다.</p>
<p>Result 열거형은 주로 두 가지 경우를 다룰 때 사용됩니다.</p>
<p>1) 성공 (Success): 함수 또는 메서드가 원하는 작업을 성공적으로 완료한 경우에 해당합니다. 이 경우 Result에는 연관 값으로 성공한 값을 포함합니다.</p>
<p>2) 실패 (Failure): 함수 또는 메서드가 작업을 실패한 경우에 해당합니다. 이 경우 Result에는 연관 값으로 에러 또는 실패 원인을 포함합니다.</p>
<p>예를 들어, 파일을 읽는 함수를 생각해보겠습니다.</p>
<pre><code class="language-swift">func readFile(atPath path: String) -&gt; Result&lt;String, Error&gt; {
    // 파일을 읽어오는 작업 수행
    if let fileContents = try? String(contentsOfFile: path) {
        return .success(fileContents) // 성공 시 결과에 파일 내용을 포함
    } else {
        let error = NSError(domain: &quot;FileReadErrorDomain&quot;, code: 0, userInfo: nil)
        return .failure(error) // 실패 시 에러를 결과에 포함
    }
}</code></pre>
<p>이 함수는 성공한 경우 Result.success로 성공 결과를 반환하고, 실패한 경우 Result.failure로 실패 원인을 반환합니다. 호출자는 switch 문이나 다른 방법을 사용하여 결과를 처리할 수 있습니다.</p>
<pre><code class="language-swift">let filePath = &quot;example.txt&quot;

switch readFile(atPath: filePath) {
case .success(let fileContents):
    print(&quot;파일 내용: \(fileContents)&quot;)
case .failure(let error):
    print(&quot;파일 읽기 실패: \(error)&quot;)
}</code></pre>
<p>이를 통해 함수가 성공 또는 실패를 명시적으로 전달하고, 에러 처리를 더 쉽게 관리할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] Generic
]]></title>
            <link>https://velog.io/@code_dang/iosSwift-Generic</link>
            <guid>https://velog.io/@code_dang/iosSwift-Generic</guid>
            <pubDate>Wed, 20 Sep 2023 12:55:15 GMT</pubDate>
            <description><![CDATA[<p>제네릭 함수는 다양한 데이터 유형과 형식에 대해 작동하는 함수를 작성할 때 사용되는 Swift의 강력한 기능 중 하나입니다. 제네릭 함수를 사용하면 함수의 인자나 반환 값의 데이터 유형을 미리 지정하지 않고, 호출 시에 실제 데이터 유형을 결정할 수 있습니다. 이렇게 하면 코드의 재사용성을 높이고 유연성을 제공할 수 있습니다.</p>
<blockquote>
<p>실제로 Swift 표준 라이브러리의 여러 코드들이 제네릭 코드로 구성되어 있는데 배열(Array), 딕셔너리(Dictionary), 세트(Set) 등의 타입은 모두 제네릭 컬렉션입니다.</p>
</blockquote>
<p>제네릭 함수를 정의할 때는 함수 이름 뒤에 <T>와 같은 형태로 제네릭 타입 매개변수를 선언합니다. 이렇게 선언한 제네릭 타입 매개변수 T는 함수 내에서 사용되며, 함수가 호출될 때 실제 데이터 유형으로 대체됩니다.
여기서 이 T를 Type Parameter라고 부르며 T라는 새로운 형식이 생성되는 것이 아닌 실제 함수가 호출될 때 해당 매개변수의 타입으로 대체되는 Placeholder입니다.</p>
<p>제네릭은 아래와 같은 형태로 사용됩니다.</p>
<pre><code class="language-swift">// 제네릭 함수
func swapTwoValues&lt;T&gt;(_ a: inout T, _ b: inout T) {
    let temp = a
    a = b
    b = temp
}

// 제네릭 함수 호출
var num1 = 5
var num2 = 10
swapTwoValues(&amp;num1, &amp;num2)
print(&quot;num1: \(num1), num2: \(num2)&quot;) // 출력: num1: 10, num2: 5

var str1 = &quot;Hello&quot;
var str2 = &quot;World&quot;
swapTwoValues(&amp;str1, &amp;str2)
print(&quot;str1: \(str1), str2: \(str2)&quot;) // 출력: str1: World, str2: Hello
</code></pre>
<p>위의 예제에서 swapTwoValues 함수는 제네릭 함수로 정의되어 있으며, inout 매개변수 a와 b를 통해 두 값의 위치를 교환합니다. 이 함수는 T라는 제네릭 타입 매개변수를 사용하므로 num1과 num2처럼 정수 또는 str1과 str2처럼 문자열을 교환할 수 있습니다.</p>
<blockquote>
<h4 id="inout-매개변수와-앰퍼샌드">inout 매개변수와 앰퍼샌드(&amp;)</h4>
<p>함수의 매개변수는 기본적으로 상수인데, 이 매개변수 값을 해당 함수의 본문 내에서 변경하려 하면 컴파일 오류가 생깁니다. 함수에서 매개변수의 값을 수정하고 함수 호출이 종료된 후에도 변경 사항을 유지하려면 inout 파라미터를 사용해야 합니다.
inout 매개변수는 함수에 전달된 값을 가지며, 함수에 의해 수정되며 원래 값을 대체하기 위해 함수에 다시 전달됩니다.
inout 매개변수는 변수 var 에만 전달할 수 있고, 상수 및 리터럴은 수정 불가하므로 인수로 전달할 수 없으며 변수 이름 앞에 앰퍼샌드(&amp;)를 사용해 수정될 수 있음을 나타냅니다.</p>
</blockquote>
<p>이와 같이 제네릭 함수를 사용하면 함수의 다양한 유형 및 데이터에 대한 재사용성을 높일 수 있으며, 타입 안전성을 유지하면서 코드를 더 간결하게 작성할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] URLSession]]></title>
            <link>https://velog.io/@code_dang/iosSwift-URLSession</link>
            <guid>https://velog.io/@code_dang/iosSwift-URLSession</guid>
            <pubDate>Tue, 19 Sep 2023 11:07:27 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="urlsession-이란">URLSession 이란?</h2>
<p>URLSession은 네트워크 작업을 수행하는 데 사용되는 기본적인 클래스로서 URL로 표시된 엔드포인트에서 데이터를 다운로드하고 엔드포인트에 데이터를 업로드하기 위한 API를 제공합니다. 
즉 URLSession은 웹 서버와 데이터를 주고받는 HTTP 요청과 응답을 처리하며, 웹 서비스와 통신하고 데이터를 다운로드 또는 업로드하는 등의 작업을 수행할 때 주로 사용됩니다. </p>
</blockquote>
<br>

<h2 id="📌-urlsession-의-기능">📌 URLSession 의 기능</h2>
<ul>
<li><p>HTTP 요청 보내기: URLSession을 사용하여 HTTP GET, POST, PUT, DELETE 등의 메소드를 사용하여 서버에 요청을 보낼 수 있습니다.</p>
</li>
<li><p>비동기 네트워크 요청: 네트워크 요청은 주로 비동기적으로 처리되며, 앱의 주 스레드를 차단하지 않고 네트워크 작업을 수행할 수 있습니다.</p>
</li>
<li><p>데이터 다운로드 및 업로드: URLSession을 사용하여 원격 서버로부터 데이터를 다운로드하거나 업로드할 수 있습니다. 이를 통해 이미지, 파일, JSON 데이터 등을 전송하고 수신할 수 있습니다.</p>
</li>
<li><p>세션 관리: URLSession을 사용하여 여러 네트워크 작업을 그룹화하고 관리할 수 있습니다. 또한 세션 구성을 사용하여 타임아웃, 캐시 처리, 쿠키 관리 등을 설정할 수 있습니다.</p>
</li>
<li><p>백그라운드 작업: URLSession은 앱이 백그라운드에서 실행 중일 때도 네트워크 작업을 지원하며, 이를 통해 데이터 동기화 및 백그라운드 업데이트를 처리할 수 있습니다.</p>
</li>
</ul>
<br>

<blockquote>
<p>Swift의 URLSession은 iOS, macOS, watchOS, tvOS 등 다양한 Apple 플랫폼에서 사용할 수 있으며, 네트워크 통신을 쉽게 구현하고 관리할 수 있는 강력한 도구입니다. 이를 통해 앱은 웹 서버와 데이터를 안전하게 교환하고 다양한 기능을 제공할 수 있습니다.</p>
</blockquote>
<br>

<hr>
<br>


<h2 id="📌-urlsession-의-구성요소들">📌 URLSession 의 구성요소들</h2>
<p>URLSession을 주로 구성하는 요소들은 다음과 같습니다.</p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/742d955e-d3be-4808-86bd-ecb2df8af4f9/image.png" alt=""></p>
<ol>
<li><p>URL (Uniform Resource Locator):
URLSession의 첫 번째 구성 요소는 요청을 보낼 웹 서버 또는 리소스의 URL입니다. URL은 웹 서버의 주소와 포트, 경로 및 쿼리 문자열을 포함하여 원격 리소스를 고유하게 식별합니다.</p>
</li>
<li><p>URLRequest:
URLSession을 사용하여 네트워크 요청을 보낼 때, URLRequest 객체를 생성하여 요청에 대한 세부 정보를 설정합니다. 이 객체에는 요청 메소드(GET, POST, PUT 등), 헤더, 요청 본문 데이터 등이 포함됩니다.</p>
</li>
<li><p>URLSessionConfiguration:
URLSessionConfiguration은 URLSession의 동작을 제어하는 구성 객체입니다. 이 객체를 사용하여 세션의 동작을 조정할 수 있으며, 예를 들어 타임아웃, 캐시 정책, 쿠키 관리 등을 설정할 수 있습니다.</p>
</li>
<li><p>URLSession:
URLSession은 네트워크 작업을 수행하는 주요 클래스입니다. URLSession은 위에서 구성한 URL 및 URLSessionConfiguration을 사용하여 네트워크 요청을 서버로 보내고 응답을 받아오는 역할을 합니다.</p>
</li>
<li><p>URLSessionTask:
URLSessionTask는 실제로 네트워크 작업을 나타내는 객체입니다. URLSession은 다양한 유형의 URLSessionTask를 생성할 수 있으며, 주로 데이터 다운로드, 데이터 업로드, 백그라운드 작업 등을 처리합니다.</p>
</li>
<li><p>URLSessionDelegate:
URLSessionDelegate는 네트워크 작업의 진행 상황 및 완료 상태를 모니터링하고 처리하기 위한 프로토콜입니다. URLSessionDelegate를 채택하여 네트워크 응답을 처리하고 오류 처리를 수행할 수 있습니다.
이러한 구성 요소들은 URLSession을 통해 원격 서버와의 통신을 구성하고 관리하는 데 사용됩니다. URLSession을 적절하게 설정하고 URLRequest를 생성하여 서버에 요청을 보내며, URLSessionTask를 사용하여 비동기적으로 네트워크 작업을 수행합니다. 이를 통해 데이터를 다운로드하거나 업로드하고, 웹 서버와 효율적으로 통신할 수 있습니다.</p>
</li>
</ol>
<br>

<hr>
<br>


<h2 id="📌-urlsession-의-작업순서">📌 URLSession 의 작업순서</h2>
<ol>
<li><p>URL 생성: URLSession을 사용하여 네트워크 요청을 보낼 URL을 생성합니다. 이 URL은 웹 서버의 엔드포인트를 나타냅니다.</p>
</li>
<li><p>URLRequest 생성: URL을 기반으로 URLRequest 객체를 생성합니다. 이 객체에는 요청 메소드(GET, POST 등), 헤더, 요청 본문 데이터 등 요청에 필요한 모든 정보가 포함됩니다.</p>
</li>
<li><p>URLSession 설정: URLSession을 생성하고 필요한 설정을 구성합니다. URLSessionConfiguration을 사용하여 세션의 동작을 제어할 수 있습니다. 예를 들어, 타임아웃, 캐시 정책, 쿠키 관리 등을 설정할 수 있습니다.</p>
</li>
<li><p>네트워크 작업 수행: URLSession을 사용하여 URLRequest를 서버로 보내고 응답을 기다립니다. 네트워크 작업은 주로 비동기로 실행되므로, 작업이 완료될 때까지 기다리지 않고 다른 작업을 수행할 수 있습니다.</p>
</li>
<li><p>응답 처리: 서버로부터 받은 응답 데이터를 처리합니다. 이 단계에서는 응답의 상태 코드를 확인하고, 데이터를 파싱하거나 화면에 표시하는 등의 작업을 수행합니다.</p>
</li>
<li><p>에러 처리: 네트워크 작업 중에 오류가 발생할 수 있으므로, 에러 처리를 수행합니다. URLSession은 네트워크 관련 오류를 NSError 객체로 반환하므로, 이를 확인하고 적절한 조치를 취해야 합니다.</p>
</li>
<li><p>정리 및 마무리: 네트워크 작업이 완료되면 URLSession을 정리하고 메모리 누수를 방지하기 위해 모든 리소스를 해제합니다.</p>
</li>
</ol>
<br>

<hr>
<br>

<p><a href="https://developer.apple.com/documentation/foundation/urlsession">URLSession</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] HTTP (1)]]></title>
            <link>https://velog.io/@code_dang/iosSwift-HTTP-1</link>
            <guid>https://velog.io/@code_dang/iosSwift-HTTP-1</guid>
            <pubDate>Mon, 18 Sep 2023 10:40:36 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h2 id="http란">HTTP란?</h2>
<p>HTTP (Hypertext Transfer Protocol)이란 인터넷에서 데이터를 전송하는 데 사용되는 통신 프로토콜입니다. 주로 웹 브라우저와 웹 서버 간에 정보(CSS, HTML, 등등)를 주고받을 때 사용되며 클라이언트(웹 브라우저)가 서버로 요청을 보내고, 서버가 그 요청에 대한 응답을 제공하는 방식으로 작동합니다. 이것은 웹 페이지를 불러오고, 웹 애플리케이션과 서버 간의 상호작용을 담당합니다. HTTP는 주로 텍스트 기반의 프로토콜이지만, 보안을 강화하기 위해 HTTPS(SSL/TLS 암호화를 사용한 HTTP)가 널리 사용되고 있습니다. HTTP는 웹의 기본적인 기술 중 하나이며, 웹 브라우징 및 웹 애플리케이션 개발에 중요한 역할을 하고있습니다.</p>
</blockquote>
<br>

<hr>
<br>

<h2 id="📌-http-status-codes">📌 HTTP Status codes</h2>
<p>HTTP Status Code(HTTP상태코드) 란 클라이언트가 서버에게 요청을 보낼 때 그 요청의 결과가 어떻게 되었는지를 알려주는 코드입니다. 이를 통해 요청을 했을 때 그 요청이 성공적인지 또는 에러가 발생했는지를 확인할 수 있습니다.
status code는 서버와의 통신에 있어서 매우 중요한 부분이며, 잘못 사용했을 시 앱을 재설치해야하는 상황이 발생할 수 있습니다.</p>
<p>HTTP Status codes 는 세 자리 숫자로 이루어져 있으며, 첫번째 자리 숫자에 따라 다음과 같은 다섯 종류의 범주로 나눌 수 있습니다:</p>
<h3 id="1-1xx--information-response">1) 1XX : Information response</h3>
<p>앞의 숫자가 1로 시작하는 Status Code는 요청을 처리하는 중이며 추가 정보가 필요할 때 사용됩니다.</p>
<ul>
<li>100 (Continue) : 진행중임을 나타내는 Status code 입니다. 현재까지의 진행 상태에 문제가 없으며 클라이언트가 계속해서 요청을 해도 된다는 뜻입니다.</li>
<li>101(Switching Protocol)</li>
<li>102(Processing) WedDAV : 서버가 요청을 수신하였으며 이를 처리중이지만 아직 제대로된 응답을 주지 못하는 상황을 이야기합니다.</li>
</ul>
<h3 id="2-2xx--successful-response">2) 2XX : Successful response</h3>
<p>앞의 숫자가 2로 시작하는 Status Code는 요청이 성공적으로 처리되었음을 나타냅니다. 예를 들어, 200은 &quot;성공&quot;을 나타냅니다.</p>
<ul>
<li>200(Ok) : 서버가 요청을 성공적으로 처리했음</li>
<li>201(Created) : 요청이 성공적이었으며 새로운 리소스가 생성되었을때, 일반적으로 POST, 혹은 PUT 이후에 받게 됩니다.</li>
<li>202(Accepted) : 서버가 요청을 접수했지만 아직 처리하지는 못했을 때를 말합니다.</li>
<li>203(Non-Authoritative information) : 서버가 요청을 성공적으로 처리했지만 다른 소스에서 수신된 정보를 제공할 때입니다.</li>
<li>204(No content) : 서버가 요청을 성공적으로 처리했지만 콘텐츠가 없을 때 입니다.</li>
<li>205(Reset Content) : 요청을 완수한 이후에 이 요청을 보낸 문서 뷰를 리셋하라는 의미입니다.</li>
<li>*206(Partial Content) *: 서버가 GET 요청의 일부만 처리했을 경우입니다.</li>
<li>*207(Multi-Status) *: 여러 리소스가 여러 Status code인 상황에 해당되는 정보를 전달합니다.</li>
<li>208(Already Reported)</li>
<li>226(IM Used)</li>
</ul>
<h3 id="3-3xx--redirection-message">3) 3XX : Redirection message</h3>
<p>앞의 숫자가 3으로 시작하는 Status Code는 추가 동작이 필요하며, 주로 리다이렉션을 나타냅니다.</p>
<ul>
<li>300(Mulitple Choice) : request에 대해 하나 이상의 응답이 가능합니다. 사용자는 그중에 하나를 선택해야 합니다.</li>
<li>301(Moved Permantly) : 요청한 리소스의 URI가 변경되었을때입니다.</li>
<li>302(Found) : 요청한 리소스의 URI가 일시적으로 변경되었을 때를 의미합니다.</li>
<li>303(See Other) : 클라이언트가 요청한 리소스를 다른 URI에서 GET 요청을 통해 얻어야 할 때.</li>
<li>304(Not modified) : 마지막 요청 이후 요청한 페이지가 수정되지 않았을 때 입니다. 서버가 이 응답을 표시하면 페이지의 콘텐츠를 표시하지 않습니다.</li>
<li>305(Use Proxy) : 요청한 응답은 반드시 프록시를 통해 접속해야 함을 알려줍니다.</li>
<li>*306(Unused) *: 이 status code는 현재 사용되지 않고 있습니다.</li>
<li>*307(Temporary Redirect) *: 현재 서버가 다른 위치의 페이지로 요청에 응답하고 있지만 향후에는 원래의 URI로 요청해야 한다는 의미입니다.</li>
<li>308(Permanent Redirect)</li>
</ul>
<h3 id="4-4xx--client-error-response">4) 4XX : Client error response</h3>
<p>앞의 숫자가 4로 시작하는 Status Code는 클라이언트 요청에 오류가 있음을 나타냅니다.</p>
<ul>
<li>400(Bad Request) : 말 그대로 클라이언트의 request가 유효하지 않은 상태를 의미합니다.</li>
<li>401(Unauthorized) : 클라이언트가 권한이 없어 작업을 진행하지 못할때입니다. 이 요청은 인증이 필요합니다. 보통 서버는 로그인이 필요한 페이지에 대해 이 요청을 제공할 수 있습니다.</li>
<li>403(Forbidden) : 서버가 요청을 거부할 때 입니다. 예를 들어 사용자가 리소스에 대한 필요 권한을 가지고 있지 않을 때를 의미합니다.</li>
<li>404(Not Found) : 서버가 요청한 페이지(resource)를 찾지 못했을 때입니다. 서버에 존재하지 않는 페이지에 대한 요구를 할 때 다음과 같은 status code가 반환됩니다.</li>
<li>405(Method Not Allowed) : 클라이언트의 요청이 허용되지 않은 메서드인 경우입니다. (예를 들어 POST 방식으로만 request가 가능한데 이를 지키지 않고 GET으로 보냈을 때)</li>
<li>409(Conflict) : 서버가 요청을 수행하는 중에 충돌이 발생했을 때 입니다.</li>
<li>414 : 요청하는 URL(일반적으로는 URL)이 너무 길었을 때의 status code 입니다.</li>
<li>419(Too Many Requests) : 사용자가 일정 시간 동안 너무 많은 request를 보냈을 때 입니다.</li>
</ul>
<h3 id="5-5xx--server-errors">5) 5XX : Server errors</h3>
<p>앞의 숫자가 5로 시작하는 Status Code는 (Server Error): 서버에서 요청을 처리하는 동안 오류가 발생했음을 나타냅니다.</p>
<ul>
<li>500(Internal Server Error) : 서버에 오류가 발생하여 요청을 수행할 수 없을 경우</li>
<li>501(Not Implemented) : 서버에 해당 요청을 수행할 수 있는 기능이 없는 경우(서버가 요청 메소드를 인식하지 못하는 경우입니다.)</li>
<li>502(Bad Gateway) : 서버가 게이트웨이나 프록시 역할을 하고 있는 업스트림 서버에서 잘못된 응답을 받았을 경우</li>
<li>504(Gateway Timeout) : 서버가 게이트웨이나 프록시 역할을 하고 있거나 또는 업스트림 서버에서 제때 요청을 받지 못한 경우.</li>
<li>511(Network Authentication Required) : 네트워크 인증이 필요한 경우입니다.</li>
</ul>
<br>

<blockquote>
<p>Swift의 경우 Alamofire 라이브러리 덕분에 http에 대한 이해도가 부족하더라도 iOS에서 http를 쉽게 사용하여 개발할 수 있으나 더 나은 iOS개발자가 되기 위해선 주의해야 하는 http status code 정도는 알아두는 것이 좋다고 합니다.
추가적인 Http Status code들은 <a href="https://www.webfx.com/web-development/glossary/http-status-codes/">WepFX</a> 에서 확인할 수 있습니다.</p>
</blockquote>
<br>

<hr>
<br>



<h2 id="📌-http-message">📌 HTTP Message</h2>
<p>HTTP (Hypertext Transfer Protocol) 메시지는 클라이언트와 웹 서버 간에 정보를 주고받는 데 사용되는 통신 형식입니다. HTTP 메시지는 웹에서 데이터를 요청하고 응답하는 데 사용되며 요청(Request) 메시지와 응답(Response) 메시지라는 두 가지 유형이 존재합니다.</p>
<p>Request와 Response의 메시지 구조는 다음과 같습니다.
<img src="https://velog.velcdn.com/images/code_dang/post/53f76333-d42a-4135-901d-a47c79abf0b1/image.png" alt=""></p>
<h3 id="1-header">1) Header</h3>
<p>HTTP 헤더(Header)는 HTTP 메시지의 일부로, 메시지의 메타 정보와 제어 정보를 포함하는 부분입니다. 헤더는 클라이언트와 서버 간의 통신을 관리하고 메시지의 특성을 설명하기 위해 사용됩니다. </p>
<h3 id="2-body">2) Body</h3>
<p>HTTP 메시지의 본문(body)은 메시지에 포함된 실제 데이터를 나타냅니다. 본문은 메시지의 헤더(Header) 다음에 위치하며, 클라이언트와 서버 간에 주고받아야 하는 실질적인 정보를 담고 있습니다. HTTP Request(요청)와 HTTP Response(응답) 모두 본문을 가질 수 있습니다.</p>
<br>

<hr>
<br>


<h2 id="📌-request와-response">📌 Request와 Response</h2>
<p>HTTP (Hypertext Transfer Protocol)에서 Request(요청)과 Response(응답)는 웹 서버와 웹 클라이언트(일반적으로 웹 브라우저) 간에 데이터를 교환하는 데 사용되는 두 가지 주요 메시지 유형입니다.</p>
<h3 id="1-http-request-요청">1) HTTP Request (요청)</h3>
<p>클라이언트(웹 브라우저)가 웹 서버에게 정보를 요청하는 메시지입니다.</p>
<ul>
<li>HTTP 메소드: 요청의 목적을 나타내는 동사 형태의 메소드 (예: GET, POST, PUT, DELETE).</li>
<li>URI (Uniform Resource Identifier): 요청 대상의 자원을 식별하는 경로 또는 URL.</li>
<li>HTTP 버전: 사용 중인 HTTP 프로토콜 버전 (예: HTTP/1.1).</li>
<li>헤더(Headers): 요청에 대한 추가 정보, 메타데이터를 포함하는 부분.</li>
<li>메시지 본문 (Message Body): 요청과 함께 전송되는 데이터 (일반적으로 POST 또는 PUT 요청 시 사용).</li>
</ul>
<h3 id="2-http-response-응답">2) HTTP Response (응답)</h3>
<p>웹 서버가 클라이언트에게 요청에 대한 결과를 반환하는 메시지입니다.</p>
<ul>
<li>상태 코드 (Status Code): 요청의 결과 상태를 나타내는 세 자리 숫자 (예: 200 OK, 404 Not Found).</li>
<li>상태 메시지 (Status Message): 상태 코드에 대한 간단한 설명.</li>
<li>헤더(Headers): 응답에 대한 추가 정보, 메타데이터를 포함하는 부분.</li>
<li>메시지 본문 (Message Body): 서버로부터 클라이언트로 전송되는 데이터 (웹 페이지의 내용 등).</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[유용한 기능들]]></title>
            <link>https://velog.io/@code_dang/%EC%9C%A0%EC%9A%A9%ED%95%9C-%EA%B8%B0%EB%8A%A5%EB%93%A4</link>
            <guid>https://velog.io/@code_dang/%EC%9C%A0%EC%9A%A9%ED%95%9C-%EA%B8%B0%EB%8A%A5%EB%93%A4</guid>
            <pubDate>Thu, 14 Sep 2023 01:14:52 GMT</pubDate>
            <description><![CDATA[<p>1) summary에 주석 표시하기
/** ..... */<br>///</p>
<p>2) 주석 강조하기 
//MARK: id TODO something</p>
<p>3) 여러 줄 동시에 잡기
control + shift + 방향키</p>
<p>4) 커밋한 사람 내역
command + control + shift + A</p>
<p>5) 검색기능
command + shift + O</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] UserDefaults]]></title>
            <link>https://velog.io/@code_dang/iosSwift-UserDefaults</link>
            <guid>https://velog.io/@code_dang/iosSwift-UserDefaults</guid>
            <pubDate>Wed, 13 Sep 2023 13:36:39 GMT</pubDate>
            <description><![CDATA[<p>UserDefaults는 쉽게 이야기해서 데이터 저장소이다.
UserDefaults는 앱의 어느 곳에서나 데이터를 쉽게 읽고 저장할 수 있게도와주며 float, double, integer, boolean과 같은 유형에 액세스하기위한 메소드를 제공하고 뿐만아니라 NSData, NSString, NSNumber, NSDate, NSArray, NSDictionary 유형의 객체들도 저장이 가능하다.</p>
<p>UserDefaults는 단일데이터 저장에 용이하며 데이터는 [key, value] 로 저장된다.</p>
<p>UserDefaults는 app을 껐다가 키더라도 저장된 데이터가 유지되나 만약 app을 삭제한다면 모든 데이터가 지워지기 때문에 영구히 유지해야하는 데이터를 저장한다면 UserDefaults는 부적합할 수 있다.</p>
<p>또한 UserDefaults는 저장되는 데이터가 암호화되지 않기 때문에 보안에 취약하기도 하다.</p>
<p>UserDefaults는 싱글톤 객체로서 앱 시작시 인스턴스가 생성되고 이를 공유한다. thread safety(스레드 안정성)를 보장하기 때문에 데이터 동기화 문제를 고려하지 않아도 괜찮다.</p>
<p>UserDefaults는 key-value 쌍으로 데이터가 저장되며 key는 String이고 value는 모든 객체를 담을 수 있다.</p>
<p>UserDefaults에 저장된 값은 덮어쓰지 전엔 변하지 않는데 예를들어 변수 x = 5로 저장 되었다면 이후 x를 변경한들 UserDefaults에 저잗된 x 값은 변경되지 않으며 5를 유지한다. 값을 변경하기 원한다면 변경 후 set을 이용하여 다시한번 UserDefaults에 저장해야한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] Team Project, CollectionView 구현]]></title>
            <link>https://velog.io/@code_dang/iosSwift-Team-Project-CollectionView-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@code_dang/iosSwift-Team-Project-CollectionView-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Tue, 12 Sep 2023 10:48:09 GMT</pubDate>
            <description><![CDATA[<p>이번 팀 프로젝트(UhTube) 에서 메인페이지를 맡게 되었는데 콜렉트 뷰를 구현하는게 핵심이었다.</p>
<p>1)
콜렉션 뷰를 구현하기 위해 먼저 스토리보드의 뷰컨트롤러에 콜렉션뷰를 추가해주고 셀 안에 원하는 구성을 추가해준다.</p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/1a22b56d-d27d-45cf-aed5-0ffed94ff016/image.png" alt=""></p>
<br>
<br>

<p>2)
그 후 새로 파일을 만들어서 콜렉션뷰의 셀을 연결할 class collectionViewCell 을 만들어주고 콜렉션뷰 셀의 클래스를 collectionViewCell로 지정해준 후 셀의 내용들(imageView, Label)을 segue를 이용하여 class collectionViewCell 로 연결해줬다.</p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/19c0528c-8102-44cf-8d6c-4ae3dfe9632e/image.png" alt=""></p>
<br>
<br>

<p>3)
콜렉션뷰 셀에 들어갈 이미지와 텍스트들을 배열에 담아주고 아래와 같이 코드를 추가했다.
프로토콜인 UICollectionViewDataSource 와 UICollectionViewDelegate 은 가장 위쪽에 선언된 class ViewController에 추가해도 되지만 코드 가독성을 위해 extension 을 이용하여 분리했다.</p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/cef37916-a92f-4dbe-9875-7c7010098db1/image.png" alt=""></p>
<br>
<br>

<p>4)
UICollectionViewDataSource 에 대한 세부코드들을 추가해준다.</p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/4c1df374-aabc-407d-b65c-f9fe9ebe98bc/image.png" alt=""></p>
<br>
<br>

<p>5)
그 아래로 이미지와 텍스트 어레이를 스토리뷰의 콜렉션뷰 셀안의 이미지와 라벨에 연결해주고 세부적인 부분들을 설정해준다. 그리고 마지막으로 셀이 리턴되도록 추가해준다.</p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/a48cfcd4-d8e4-4ce5-b5da-5fb0a59359b7/image.png" alt=""></p>
<br>
<br>


<p>6) 
마지막으로 레이아웃에 대한 세부설정을 extension으로 추가해주고 ViewDidLoad에 콜렉션뷰에 레이아웃 반영을 위한 코드를 추가한다.</p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/40baa757-eae1-4746-a0cc-716b136fd1bd/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/deec5367-a5c2-48a3-bc62-71b73f95841e/image.png" alt=""></p>
<br>
<br>

<p>콜렉션 뷰를 이용한 간단한 화면이 완성되었다.</p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/688fc021-5ea5-4bf8-a4d4-b678dd572ae9/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] MVC Architecture Pattern]]></title>
            <link>https://velog.io/@code_dang/iosSwift-MVC-Architecture-Pattern</link>
            <guid>https://velog.io/@code_dang/iosSwift-MVC-Architecture-Pattern</guid>
            <pubDate>Mon, 28 Aug 2023 08:40:36 GMT</pubDate>
            <description><![CDATA[<p>아키텍쳐란 영단어로는 ‘건축학’ 이라는 뜻으로, 개발에서 아키텍쳐는 서비스의 동작 원리를 나타내는 것이다.</p>
<p>즉 서비스의 구성과 작동원리가 어떻게 디자인되어있는지를 나타내는 것인데 서비스가 어떻한 패턴으로 디자인되어 있는지는 서비스의 유지 및 관리에 있어서 굉장히 중요한 부분이며 대표적인 아키텍쳐 패턴으로 MVC, MVP, MVVM 이 있다.</p>
<h3 id="mvc-pattern">MVC Pattern</h3>
<p>MVC 패턴은 Model-View-Controller의 약자로서 앱을 Model, View, Controller 라는 세 가지 역할로 구분한 구조 패턴입니다. 
MVC 패턴은 사용자가 Controller를 조작하면 Controller는 Model을 통해 데이터를 가져오고 그 데이터를 바탕으로 View를 통해 시각적 표현을 제어하여 사용자에게 전달하게 됩니다.</p>
<p>이는 Model 과 View 를 구별하고, 이 둘 사이를 중재하는 Controller 를 둠으로 서비스를 구조적으로 유연하며 재사용성이 높은 구조를 만듭니다. model, view, controller 가 각자의 역할에만 충실할 수 있도록 구조를 나누었기 때문에 코드의 유지및 관리의 효율을 높입니다.  </p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/7bd3bad0-4be6-4216-b9a9-d640ae028240/image.png" alt=""></p>
<p>Model
Model은 View에 표시되기 위해 필요한 데이터를 담으며 이와 관련된 일들을 처리힙니다. Model은 비즈니스 로직을 설명하는 클래스의 집합으로 구성되며 어떻게 데이터가 변경되고 조작될 수 있는지에 관한 규칙을 정의합니다.</p>
<p>View
View는 Controller로 부터 받은 UI 데이터를 표시하는 역할을 담당합니다. MVC 패턴에서 View는 데이터의 상태 변화를 업데이트 하기 위해 옵저버 패턴을 이용하여 Model을 관찰합니다.</p>
<p>Controller
Controller는 사용자의 요청을 처리하는 역할을 담당합니다. Controller는 Model을 통해 받은 데이터를 처리하거나, 결과 값을 View에 반환하는 역할을 합니다. 일반적으로 View와 Model사이를 중재하는 역할을 수행합니다.</p>
<br>

<p>MVC 패턴은 쉽게 설명하기 위해 아래의 그림처럼도 표현이 됩니다.</p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/80d4825b-089f-4be8-a179-2720437f921f/image.png" alt=""></p>
<br>

<p>UIViewController는 사실 구조적으로 Controller와 View 가 완전히 분리되어있지 않은데 UIViewController는 이미 내부적으로 UIView를 가지고 있는 구조이다.</p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/409e33c5-5025-4cd0-8c26-0ee234f3ac3d/image.png" alt=""></p>
<p>때문에 그림처럼 Controller는 UIViewController를 이며 View는 UIView에 대입되며 패턴이 첫 번째 이미지와 같은 모습을 가지게 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] Cocoa Touch Framework]]></title>
            <link>https://velog.io/@code_dang/iosSwift-Cocoa-Touch-Framework</link>
            <guid>https://velog.io/@code_dang/iosSwift-Cocoa-Touch-Framework</guid>
            <pubDate>Fri, 25 Aug 2023 12:46:44 GMT</pubDate>
            <description><![CDATA[<h3 id="cocoa-touch-framework">Cocoa Touch Framework</h3>
<p>코코아 터치 프레임워크는 iOS 개발환경, 애플리케이션의 다양한 기능 구현에 필요한 여러 개발 도구를 포함하는 최상위 레벨의 프레임 워크이다.
즉 코코아 터치 프레임워크는 기기에서 필요한 기능, 동작 구조, UI를 구성하는 기본적 객체들을 담고 있다.</p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/9e627b5e-fcab-4a2f-923f-4106ee331226/image.webp" alt=""></p>
<br>
<br>


<h3 id="ios에서-프레임워크의-계층-구조">iOS에서 프레임워크의 계층 구조</h3>
<p>위에서 언급한 최상위 레벨이라는 의미는 필요한 기능을 더 손쉽게 사용할 수 있다는 뜻이다. 즉 상위레벨의 프레임워크는 내부적으로 하위레벨의 프레임워크를 이용하여 기능을 구현할 수 있는데 코코아 터치 프레임워크의 계층 위치는 다음과 같다.</p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/3cea6c2b-87d6-4f94-bdfe-c4e20ffaca2a/image.png" alt=""></p>
<p>코코아 프레임워크는 아랫 계층들인 미디어 레이어, 코어 서비스, 코어 OS를 사용하여 구현된다.</p>
<br>
<br>

<h3 id="uikit">UIkit</h3>
<p>UIkit과 Foundation은 코코아 터치 프레임워크에 속한 대표적인 프레임워크인데 UIkit의 경우 사용자의 인터페이스를 관리하고 이벤트를 처리하기 위한 기능으로 사용된다.</p>
<p>Xcode에서 새롭게 ViewController를 생성하면 상단에 ‘import UIKit’이 기본으로 명시되어있는데 이는
ViewController가 UIkit에 정의된 클래스인 UIViewController를 상속받기 때문이다. </p>
<p>import UIKit을 선언해줌으로 컴파일러는 UIViewController 클래스를 찾아서 빌드해준다.</p>
<p>UIViewController는 사용자의 인터페이스와 액션관리를 도와준다.</p>
<br>
<br>

<h3 id="foundation">Foundation</h3>
<p>Foundation은 어플리케이션의 중심이며 기능적인 부분을 관리한다.</p>
<p>기본 자료형을 포함한 자료구조, 객체 지향 처리와 연산, 각종 구조체, 타이머, 네트워크 통신 등의 기능을 처리하기 위해서 필수적으로 import 되어야 한다. 
하지만 UIkit에 Foundation이 기본적으로 import 되어 있기에 UIkit만 import되어있어도 대부분의 기능을 사용할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] 정예반 미션 (Class)]]></title>
            <link>https://velog.io/@code_dang/iosSwift-%EC%A0%95%EC%98%88%EB%B0%98-%EB%AF%B8%EC%85%98-Class</link>
            <guid>https://velog.io/@code_dang/iosSwift-%EC%A0%95%EC%98%88%EB%B0%98-%EB%AF%B8%EC%85%98-Class</guid>
            <pubDate>Fri, 18 Aug 2023 14:42:28 GMT</pubDate>
            <description><![CDATA[<p>장바구니와 제품을 class로 설계해보는 미션을 받았다.</p>
<p>class 는 보통 붕어빵(instance)을 찍어내는 붕어빵 기계로 비유하곤 하는데 구조를 예를 들면 아래와 같다.</p>
<pre><code class="language-swift">class Car {
    var modelName : String
    var price : Int

    init(modelName : String, price : Int){
        self.modelName = modelName
        self.price = price
    }

    func getModelInfo(){
        print(&quot;이 차의 모델은 \(modelName)이고 가격은 \(price)입니다.&quot;)
    }
}

var hyundai = Car(modelName: &quot;pony&quot;, price: 4000000)
hyundai.getModelInfo()</code></pre>
<p>위의 예시는 Car(자동차) 라는 클래스를 선언했고 프로퍼티 값으로 modelName(모델명)과 price(가격)을 넣었다.</p>
<p>그리고 마지막에 인스턴스로 변수 hyundai 를 통해서 프로퍼티 modelName 에 pony를, price에 40000000 넣었다.
hyundai 라는 인스턴스가 만들어진 것이다.</p>
<p>장바구니와 제품 class에 대해서는 아래와 같이 설계해보았다.</p>
<p><img src="https://velog.velcdn.com/images/code_dang/post/2fb19399-f9fc-4de5-9384-5b08022fce17/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] Array]]></title>
            <link>https://velog.io/@code_dang/iosSwift-Array-jmadieea</link>
            <guid>https://velog.io/@code_dang/iosSwift-Array-jmadieea</guid>
            <pubDate>Wed, 09 Aug 2023 07:45:04 GMT</pubDate>
            <description><![CDATA[<p>배열(Array)에 대해 알아보자</p>
<p>배열은 하나 이상의 데이터들을 연속해서 저장하는 collection으로 배열에는 추가되는 값(value)들이 순차적으로 저장된다.
또한 배열은 타입을 명시해줘야하는데 명시된 하나의 타입값들만 저장할 수 있으며 이 외의 타입값들은 저장할 수 없다. 
타입에는 제한이 있으나 저장되는 값들은 동일한 값이더라도 상관없이 저장할 수 있고 각자 독립적인 값으로 취급된다.
index는 배열속 요소들의 순서를 의미하는데 &#39;0&#39;으로 시작하여 순차적으로 올라간다. 즉 배열의 첫 번째 순서에 저장된 값의 index는 0이고 두번째에 저장된 값의 index는 1이 된다.</p>
<br>

<h2 id="array-literal">Array Literal</h2>
<p>배역은 중괄호([]) 를 이용하여 나타내며 저장가능한 요소(element)의 수는 문법적으론 제한이 없다.</p>
<pre><code class="language-siwft">[element, element, element....]</code></pre>
<p>중괄호 안에 타입이 있다면 배열타입이라 하며 중괄호 안에 값이 있다면 배열 리터럴(array literal)이라고 한다.</p>
<pre><code class="language-swift">let a = [Int]

let b = [1, 2, 3, 4]</code></pre>
<p>배열은 다차원 배열로도 만들 수 있는데 2차원 배열의 예를 들면</p>
<pre><code class="language-swift">let a = [[2, 3, 4, 5], [3, 4, 2, 1]]</code></pre>
<p>위와 같이 만들 수 있으며 배열 속 중괄호의 갯수로 몇 차원 배열인지 유추할 수 있다.</p>
<br>

<h2 id="array-type">Array Type</h2>
<p>배열타입은 아래와 같이 표현할 수 있는데 위쪽이 정식 문법 아랫쪽이 단축문법이다. 둘의 의미는 동일하다.</p>
<pre><code class="language-swift">Array&lt;Type&gt;
//정식문법
[Type]
//단축문법</code></pre>
<p>예를들면 각 방식은 아래와 같이 선언될 수 있다.</p>
<pre><code class="language-swift">let a : Array&lt;Int&gt;
// 정식문법
let a : [Int]
// 단축문법</code></pre>
<br>

<h2 id="array-basics">Array Basics</h2>
<p>배열에서 빈배열은 아래와 같이 선언될 수 있는데 모두 같은 의미를 가진 코드들이다.</p>
<pre><code class="language-swift">let a : [Int] = []

let a = Array&lt;Int&gt;()

let a = [Int]()
</code></pre>
<br>
만약 배열을 만들고 초기값으로 채우고 싶다면 아래의 예시처럼 코드를 짤 수 도 있다.

<pre><code class="language-swift">let a = [Int](repeating: 0, count: 10)</code></pre>
<br>

<p>배열에 저장된 요소의 갯수는 카운트 속성으로 확인할 수 있다.</p>
<pre><code class="language-swift">a.count</code></pre>
<br>
배열이 비어있는지 확인할 수 도 있는데 방법은 아래와 같다.

<pre><code class="language-swift">a.count == 0

a.isEmpty</code></pre>
<br>
<br>

<h2 id="accessing-elements">Accessing Elements</h2>
<p>그럼 배열의 요소에 접근하기 위해선 어떻게 해야할까?
다양한 방법들이 있는데 하나씩 알아가보자</p>
<p>첫번째 방법으로는 중괄호와 인덱스를 이용한 방법이다.
배열이 저장된 요소에 접근하기 위해 중괄호와 인덱스만 써주면 되며 범위도 전달하여 리턴받을 수 있다.</p>
<pre><code class="language-swift">let num = [22, 33, 53, 77]

num[0]
//22

num[3]
// 77

num[0...2]
// 22, 33, 53</code></pre>
<br>
정수 인덱스 대신 속성으로 제공하는 인덱스를 사용하는 접근할 수도 있다.
이는 코드가 복잡해졌을때 보다 안전하게 인덱스에 접근할 수 있도록 도와준다.

<pre><code class="language-swift">let num = [22, 33, 53, 77]

num[num.startIndex]
// 첫번째 인덱스를 호출하는 코드

num[num.index(befor: num.endIndex)]
// 마지막 인텍스를 호출하는 코드
</code></pre>
<p>위의 예시에 마지막 코드를 보면 위의 첫번째 인덱스를 호출하는 코드와 모습이 다른데 그 이유는 startIndex는 첫번째 인덱스를 호출하지만 &#39;endIndex&#39;는 마지막 인덱스 그 다음을 호출하는 코드이다. 즉 마지막 인덱스 다음인 빈 공간을 호출하기 때문에 그대로 쓰면 오류가 발생하고 때문에 위의 코드처럼 한칸 앞당겨 써야한다.</p>
<p>이 첫 번째와 마지막 인덱스를 위 예시보다 쉽게 호출하는 속성들도 있다.</p>
<pre><code class="language-swift">let num = [22, 33, 53, 77]

num.first
// 첫번째 인덱스를 호출하는 코드

num.last
// 마지막 인텍스를 호출하는 코드</code></pre>
<p>위 예시의 경우 옵셔널 속성을 가지고있다. 때문에 배열이 비어있더라도 오류가 나지않고 nil을 리턴해준다.</p>
<p>배열에 접금할때 범위를 지정해서 접근할 수도 있는데 </p>
<pre><code class="language-swift">let list = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;]

list[1...3]
// &quot;b&quot;, &quot;c&quot;, &quot;d&quot;

list[2...]
// &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;

liet.prefix(3)
// &quot;a&quot;, &quot;b&quot;, &quot;c&quot;
</code></pre>
<p>prefix의 경우 선언된 숫자값의 갯수 만큼 배열을 리턴해준다. 또한 prefix의 경우 배열의 최대 갯수 보다 높은 수를 입력하더라도 오류가 발생하지 않는다.</p>
<pre><code class="language-swift">let list = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;]

liet.prefix(20)
// &quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;
</code></pre>
<p>prefix를 이용하는 방법이 더 있는데 </p>
<pre><code class="language-swift">let list = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;]

list.prefix(upTo : 2)
// &quot;a&quot;, &quot;b&quot;

list.prefix(through : 2)
// &quot;a&quot;, &quot;b&quot;, &quot;c&quot;
</code></pre>
<p>위의 코드들은 prefix를 이용하여 인덱스에 접근하는 방식으로 upTo는 값의 하나 적은 수의 인덱스에 접근하는 코드로 위의 예시에선 인덱스&#39;1&#39; 까지 접근하여 인덱스 &#39;0&#39;, &#39;1&#39; 을 리턴하고 through는 해당 값의 인덱스 까지 접근함으로 예시에선 인덱스 &#39;0&#39;, &#39;1&#39;, &#39;2&#39; 까지 리턴해준다.</p>
<p>조건을 지정하는 방법도 있는데 prefix while 을 사용하면 된다.</p>
<pre><code class="language-swift">let list = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;]

let f = list.prefix{$0 != &quot;c&quot;}
f
// &quot;a&quot;, &quot;b&quot;
</code></pre>
<p>위의 코드는 배열 속의 &quot;c&quot; 이전까지의 인덱스들을 추출해주는 코드로 &quot;a&quot;, &quot;b&quot; 가 출력된다.</p>
<br>
prefix가 요소들을 앞쪽 부터 순서대로 추출해준다면 요소들을 뒤쪽부터 추출해주는 코드도 있는데 suffix이다.

<pre><code class="language-swift">let list = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;]

list.suffix(3)
// &quot;c&quot;, &quot;d&quot;, &quot;e&quot;
</code></pre>
<p>위 예시에서 suffix는 배열의 마지막 요소 부터 역순으로 3개의 요소들을 순서대로 추출해주고있다.</p>
<p>suffix를 이용하여 인덱스에 접근하려면 아래와 같이 사용해주면된다.</p>
<pre><code class="language-swift">let list = [&quot;a&quot;, &quot;b&quot;, &quot;c&quot;, &quot;d&quot;, &quot;e&quot;]

list.suffix(from: 2)
// &quot;c&quot;, &quot;d&quot;, &quot;e&quot;
</code></pre>
<p>위 예시에서 from에 들어간 값 &#39;2&#39;는 인덱스 값을 나타낸다. 위 코드는 인덱스 2부터 끝까지 모든 요소들을 리턴하는 코드이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ios_Swift] Collection]]></title>
            <link>https://velog.io/@code_dang/iosSwift-Collection</link>
            <guid>https://velog.io/@code_dang/iosSwift-Collection</guid>
            <pubDate>Tue, 08 Aug 2023 10:38:26 GMT</pubDate>
            <description><![CDATA[<p>swift의 collection에 대해서 알아보자</p>
<p>1)
collection은 값(value)들의 묶음을 의미한다.
swift에서 collection은 Array, Dictionary, Set 으로 총 세 가지 타입이 있다.</p>
<p>Array 는 &#39;배열&#39;이라고도 하는데 값들을 순서대로 저장하는 collection이고 
Dictionary 은 사전처럼 키와 값을 하나의 쌍으로 묶어서 저장해주는 collection 이며
Set 은 집합연산을 제공하는 collection이다.</p>
<p>2)
Swift 이전에 Objective-c 에서 사용하던 collection은 class로 구성 되었으며 따라서 참조형식이었다. 이를 Foundation Collection 이라 한다.
Swift 에서는 collection이 구조체(struct)로 되어있으며 Swift Collections 이라 부른다. 
일반적으로는 Swift Collecton이 사용되며 collection을 참조형식으로 써야할 때 제한적으로 Foundation Collection이 사용된다.</p>
<p>Foundation Collection 의 타입 이름들은 NSArray, NSDictionary, NSSet 으로 Swift Collection 에서 접두에 &#39;NS&#39; 만 붙여주면 된다.</p>
<p>3)
Foundation Collection에는 객체(Object) 만 저장 가능하다. 때문에 Int 타입등의 숫자등을 저장하기 위해선 NSNumber, NSValue등으로 객체화를 한 후 저장해야한다.
반면에 Swift Collection에는 이러한 제약없이 객체(Object)와 값(Value) 모두가 저장 가능하다. 
다만 Swift Collection에는 하나의 Type 만 저장이 가능하다 만약 Int 타입을 저장하는 collection이라면 Int 타입만 저장이 가능하다. 그러나 Foundation Collection은 이러한 타입에 대한 제한이 없다.</p>
<p>4)
Collection에 저장하는 개별 데이터들은 Element 라고 부르며 한글로 요소라고 부른다.</p>
<p>5)
Collection엔 불변(let) Collection과 가변(var) Collection이 있는데 let으로 선언된 collection은 불변하며 변경할 수 없고, var로 선언된 collection은 가변 컬렉션으로서 변경이 가능하다.</p>
<p>단 collection의 가변성이 요소(element)의 가변성에 영향을 주는 건 아니며 요소의 가변성은 해당 요소의 가변성에 영향을 받는다.</p>
<p>6) 
Swift Collection은 구조체의 값형식으로서 값형식은 값을 사용할때 마다 복사되는 형식이다. Swift는 Copy-on-write 이라는 방식으로 Collection을 최적화한다. 이는 요소에 접근할 때는 복사없이 원본에 접근하며 Collection을 변결할 때에만 복사되는 방식이다.</p>
]]></description>
        </item>
    </channel>
</rss>