<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hello_hidi.log</title>
        <link>https://velog.io/</link>
        <description>안뇽희디</description>
        <lastBuildDate>Sat, 24 Dec 2022 14:41:50 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>hello_hidi.log</title>
            <url>https://images.velog.io/images/hello_hidi/profile/091c7716-fa97-4172-bd6d-72f99df741b8/IMG_0239.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. hello_hidi.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hello_hidi" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[iOS] 모야가모야 (진짜 내가 볼라고 만드는 모야정리)]]></title>
            <link>https://velog.io/@hello_hidi/iOS-%EB%AA%A8%EC%95%BC%EA%B0%80%EB%AA%A8%EC%95%BC-%EC%A7%84%EC%A7%9C-%EB%82%B4%EA%B0%80-%EB%B3%BC%EB%9D%BC%EA%B3%A0-%EB%A7%8C%EB%93%9C%EB%8A%94-%EB%AA%A8%EC%95%BC%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@hello_hidi/iOS-%EB%AA%A8%EC%95%BC%EA%B0%80%EB%AA%A8%EC%95%BC-%EC%A7%84%EC%A7%9C-%EB%82%B4%EA%B0%80-%EB%B3%BC%EB%9D%BC%EA%B3%A0-%EB%A7%8C%EB%93%9C%EB%8A%94-%EB%AA%A8%EC%95%BC%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sat, 24 Dec 2022 14:41:50 GMT</pubDate>
            <description><![CDATA[<p>음 개념은 나중에 좀 더 구체적으로 정리하고 
여기서는 내가 서버통신을 할 때 어떤 순서로 차분하고 정확하게 서버통신을 해야되는지
그거에 중점을 둬서 정리하도록 하겠다!</p>
<h1 id="moya의-개념">Moya의 개념</h1>
<p><img src="https://velog.velcdn.com/images/hello_hidi/post/021be4bf-3068-4e11-90d1-1f26ead3f7b8/image.png" alt=""></p>
<h2 id="moya의-구성요소">Moya의 구성요소</h2>
<h4 id="1-provider">1. Provider</h4>
<blockquote>
<p>모든 네트워크 서비스와 상호작용할 때 만들고 사용하는 객체
초기화 시 Moya Target을 가지게 된다.</p>
</blockquote>
<h4 id="2-target">2. Target</h4>
<blockquote>
<p>일반적으로 전체 <strong>API 서비스</strong>를 설명한다!
<img src="https://velog.velcdn.com/images/hello_hidi/post/96314f99-d4b5-44db-abdb-ae7dc4953de6/image.png" alt=""></p>
</blockquote>
<h4 id="3-endpoint">3. Endpoint</h4>
<blockquote>
<p><strong>실제 URLRequest를 요청하게 된다.</strong></p>
</blockquote>
<ul>
<li>Provider가 Target을 EndPoint로 전환한다.</li>
<li>EndPoint에는 Target에 해당하는 모든 데이터가 포함되어 있다!</li>
</ul>
<h1 id="모야로-하는-서버통신-순서대로">모야로 하는 서버통신 순서대로</h1>
<h2 id="1-요청-응답-모델-구현하기dto">1. 요청, 응답 모델 구현하기(Dto)</h2>
<blockquote>
<p>서버에 요청할 값의 틀을 만든다고 생각하면 된다. 
예를 들어 로그인이라면 이메일과 비밀번호가 필요할 것이다.
이걸 먼저 Dto로 정의를 해두는 것이다!!
<strong><a href="https://app.quicktype.io">https://app.quicktype.io</a></strong> -&gt; 이걸로 Json코드를 바로 Swift로 바꿔서 사용하자!</p>
</blockquote>
<h3 id="1-1-요청-모델-구현하기-requestdto">1-1. 요청 모델 구현하기 (RequestDto)</h3>
<blockquote>
<p>서버에 요청할 모델을 작성한다. -&gt; <strong>struct로 만들기</strong></p>
</blockquote>
<pre><code class="language-swift">import Foundation

// MARK: - SignupRequestDto

struct SignupRequestDto: Codable {
    var email: String
    var name: String
    var password: String
}

// MARK: - LoginRequestDto

struct LoginRequestvaSDto: Codable {
    var email: String
    var password: String
}</code></pre>
<h3 id="1-2-응답-모델-구현하기-responsedto">1-2. 응답 모델 구현하기 (ResponseDto)</h3>
<blockquote>
<p>서버에서 응답받을 모델을 작성한다. -&gt; <strong>struct로 만들기</strong></p>
</blockquote>
<pre><code class="language-swift">import Foundation

// MARK: - LoginResponseDto
struct LoginResponseDto: Codable {
    let status: Int
    let message: String
    let result: Results?
}

/// Moya의 Result와 충돌이 나기 때문에 뒤에 s 하나만 붙여주세요!
// MARK: - Results
struct Results: Codable {
    let id: Int
    let name: String
    let profileImage, bio: String?
    let email, password: String
}</code></pre>
<h2 id="2-열거형-target-만들기">2. 열거형 Target 만들기</h2>
<h2 id="2-1-api-목록-정하기">2-1. API 목록 정하기</h2>
<blockquote>
<p>Enum 을 사용해서 사용할 API 목록을 작성해줍니다.</p>
</blockquote>
<ul>
<li>각 기능에 맞는 API를 enum을 통해서 선언해준다.</li>
</ul>
<pre><code class="language-swift">enum UserRouter {
    case signup(param: SignupRequestDto)
    case login(param: LoginRequestDto)
}</code></pre>
<h2 id="2-2-target-정의하기">2-2. Target 정의하기</h2>
<blockquote>
<p>아래 나와있는 Target들을 정의할것이다!</p>
</blockquote>
<ul>
<li>Enum으로 선언한 API를 extension해서 TargetType들을 정의할것이다.</li>
<li>각 프로퍼티마다 switch-case를 통해서 각각 기능에 맞게 정의해준다.</li>
</ul>
<blockquote>
<h3 id="🚨target-property">🚨Target Property</h3>
<p><strong>baseURL</strong> : Server base URL 지정
<strong>path</strong> : API Path 지정
<strong>method</strong> : HTTP Method 지정
<strong>sampleData</strong> : Mock Data for Test
<strong>task</strong> : Parameters for request 지정
<strong>validationType</strong> : 허용할 response 정의 - validationType 참고
<strong>headers</strong> : HTTP headers 적용</p>
</blockquote>
<pre><code class="language-swift">import Foundation
import UIKit

import Moya

enum UserRouter {
    case signup(param: SignupRequestDto)
    case login(param: LoginRequestDto)
}

extension UserRouter: TargetType {
    var baseURL: URL {
        return URL(string: Environment.baseURL)!
    }

    var path: String {
        switch self {
        case .signup(param: _):
            return &quot;/user/signup&quot;
        case .login(param: _):
            return &quot;/user/signin&quot;
        }
    }

    var method: Moya.Method {
        switch self {
        case .signup(param: _):
            return .post
        case .login(param: _):
            return .post
        }
    }

    var task: Task {
        switch self {
        case .signup(param: let param):
//            return .requestJSONEncodable(param)
            return .requestParameters(parameters: try! param.asParameter(), encoding: JSONEncoding.default)

        case .login(param: let param):
            return .requestParameters(parameters: try! param.asParameter(), encoding: JSONEncoding.default)
        }
    }

    var headers: [String : String]? {
        return [&quot;Content-Type&quot;: &quot;application/json&quot;]
    }
}</code></pre>
<h2 id="3-provider-객체-선언하기">3. Provider 객체 선언하기</h2>
<blockquote>
<p>서버통신을 하기 위해서 Provider 객체를 선언해준다!</p>
</blockquote>
<ul>
<li><strong>MoyaProvider&lt;&quot;&quot;Target&quot;&quot;&gt;</strong> 이런식으로 선언해주면 된다!</li>
</ul>
<pre><code class="language-swift">let userProvider = MoyaProvider&lt;UserRouter&gt;()</code></pre>
<h2 id="4-네트워크-요청--처리">4. 네트워크 요청 / 처리</h2>
<blockquote>
<p>서버에 요청했을 때의 결과값을 받아오는 부분이다.
음 버튼을 눌렀을때! 서버통신을 한다!
라고 가정을 하면 버튼을 누르는 행위에 통신함수를 적어두면 좋겠죠?
이건 코드로만 설명 -&gt; 매번 달라질거 같기 때문 So 느낌만!</p>
</blockquote>
<pre><code class="language-swift">// MARK: - Action Helpers

    @objc
    private func touchupSubmitButton() {
        if let email = emailView.popInput(),
           let name = nameView.popInput(),
           let password = passwordView.popInput() {
            let param = SignupRequestDto(email: email, name: name, password: password)
            signup(param: param)
        }
    }

    // MARK: - Network Helpers

    private func signup(param: SignupRequestDto) {
        userProvider.request(.signup(param: param)) { response in
            switch response {
            case .success(let result):
                let status = result.statusCode
                if status &gt;= 200 &amp;&amp; status &lt; 300 {
                    self.pushToLogin()
                }
                else if status &gt;= 400 {

                }
            case .failure(let error):
                print(error.localizedDescription)
            }
        }
    }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[iOS] TableView (4) TableView 구현 - UITableView header 구현]]></title>
            <link>https://velog.io/@hello_hidi/iOS-TableView-4-TableView-%EA%B5%AC%ED%98%84-UITableView-header-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@hello_hidi/iOS-TableView-4-TableView-%EA%B5%AC%ED%98%84-UITableView-header-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Sat, 24 Dec 2022 13:23:33 GMT</pubDate>
            <description><![CDATA[<h2 id="5-uitableviewheader-구현">5. UITableViewHeader 구현</h2>
<p>마지막으로 TableView의 헤더를 구현해보자
여기서는 마이프로필 즉 친구뷰 중에서 자기를 표현하는 부분을 헤더로 구현할 것이다.
그림으로 보면 아래와 같다!</p>
<p><img src="https://velog.velcdn.com/images/hello_hidi/post/6240eeb3-e0f0-497f-8ba3-d53941d282d0/image.png" alt=""></p>
<h3 id="51-friendheaderview-구현하기">5.1 FriendHeaderView 구현하기</h3>
<ul>
<li>헤더뷰를 <strong>UITableViewHeaderFooterView</strong> 상속을 받아서 구현해준다!</li>
<li>이때 신경써야 될 부분은 <strong>identifier를 선언해줘야 되는 부분</strong>인데, 그 이유는 헤더뷰 또한 뷰컨트롤러에서 register함수를 통해 테이블뷰에 등록해서 사용할 것이기 때문이다!!!</li>
</ul>
<pre><code class="language-swift">import Foundation
import UIKit

import SnapKit
import SwiftyColor
import Then

final class FriendHeaderView: UITableViewHeaderFooterView { //중요중요!!!

    //MARK: - Properties

    static let identifier = &quot;FriendHeaderView&quot; // 꼭!!!! identifier 선언!!

    //MARK: - UI Components

    private let profileImageView = UIImageView().then{
        $0.image = Image.friendProfileImage
    }

    private let profileNameLabel = UILabel().then {
        $0.text = &quot;김솝트&quot;
        $0.font = UIFont(name: &quot;AppleSDGothicNeo-SemiBold&quot;, size: 16)
        $0.textColor = 0x191919.color
    }

    private let profileMessageLabel = UILabel().then {
        $0.text = &quot;상태메시지는 여기에&quot;
        $0.font = UIFont(name: &quot;AppleSDGothicNeo-Regular&quot;, size: 11)
        $0.textColor = 0xA6A6A6.color
    }

    //MARK: - Life Cycle

    override init(reuseIdentifier: String?) {
        super.init(reuseIdentifier: reuseIdentifier)
        setupView()
        setupConstraints()
    }

    required init?(coder: NSCoder) {
        fatalError(&quot;init(coder:) has not been implemented&quot;)
    }

    //MARK: - Custom Method

    private func setupView() {
        contentView.backgroundColor = .white

        [profileImageView, profileNameLabel, profileMessageLabel].forEach {
            contentView.addSubview($0)
        }
    }

    private func setupConstraints() {
        profileImageView.snp.makeConstraints {
            $0.top.equalToSuperview().offset(7)
            $0.leading.equalToSuperview().offset(16)
            $0.width.equalTo(59)
            $0.height.equalTo(58)
        }

        profileNameLabel.snp.makeConstraints {
            $0.top.equalToSuperview().offset(19)
            $0.leading.equalTo(self.profileImageView.snp.trailing).offset(11)
        }

        profileMessageLabel.snp.makeConstraints {
            $0.top.equalTo(self.profileNameLabel.snp.bottom).offset(6)
            $0.leading.equalTo(self.profileNameLabel)
        }
    }
}
</code></pre>
<h3 id="5-2-테이블뷰-헤더-register함수로-등록해주기">5-2. 테이블뷰 헤더 register함수로 등록해주기!</h3>
<blockquote>
<p>테이블뷰에 헤더를 등록해야겠죠? </p>
</blockquote>
<ul>
<li>테이블뷰셀을 등록하는 것과 다르게 <strong>forHeaderFooterViewReuseIdentifier</strong> 을 통해서 등록하면 됩니다!</li>
<li>이때 우리가 셀에서 등록한 것처럼! <strong>헤더뷰의 본체와! identifier을 파라미터로 넣어주면 되겠죵</strong></li>
</ul>
<pre><code class="language-swift">private func register() {
        friendView.friendTableView.register(
            FriendTableViewCell.self, forCellReuseIdentifier: FriendTableViewCell.identifier)

        friendView.friendTableView.register(
            FriendHeaderView.self, forHeaderFooterViewReuseIdentifier: FriendHeaderView.identifier)
    }</code></pre>
<h3 id="5-3-테이블뷰-헤더-delegate로-커스텀하기">5-3. 테이블뷰 헤더 delegate로 커스텀하기!</h3>
<blockquote>
<p>테이블뷰에 등록된 셀이 어떤 친군지 알려주기 위해서 UITableViewDelegate와 UITableViewDataSource를 사용했자나요? 
테이블뷰 헤더뷰 또한 어떤 친군지 설명을 해줘야하는데요!
UITableViewDelegate를 통해서 이 친구의 높이와 어떤 뷰인지 설명해줄꺼에요!</p>
</blockquote>
<h4 id="heightforheaderinsection-헤더뷰의-높이를-알려주는-함수">heightForHeaderInSection: 헤더뷰의 높이를 알려주는 함수!</h4>
<ul>
<li>이걸 통해서 높이를 헤더뷰의 높이를 설정할 수 있겠죠?<h4 id="viewforheaderinsection-어떤-헤더뷰인지-설명하는-함수">viewForHeaderInSection: 어떤 헤더뷰인지 설명하는 함수!</h4>
</li>
<li>살짝 UITableViewDataSource의 cellForRowAt과 비슷한 느낌 (지극히 주관적)</li>
<li>guard let 구문으로 headerView를 지정하고 return 해주면 됩니다잉!</li>
<li><strong>dequeueReusableHeaderFooterView</strong> : 헤더뷰도 재사용 메커니즘을 사용한다! </li>
</ul>
<pre><code class="language-swift">extension FriendView: UITableViewDelegate {

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -&gt; CGFloat {
        return 73
    }

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -&gt; UIView? {
        guard let headerView = tableView.dequeueReusableHeaderFooterView(
            withIdentifier: FriendHeaderView.identifier)
                as? FriendHeaderView else { return UIView() }
        return headerView
    }
}</code></pre>
<p>전체코드
<a href="https://github.com/HELLOHIDI/AppJam-Laboratory2">https://github.com/HELLOHIDI/AppJam-Laboratory2</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[iOS] TableView (3) TableView 구현 - UITableViewDelegate, UITableViewDataSource]]></title>
            <link>https://velog.io/@hello_hidi/iOS-TableView-3-TableView-%EA%B5%AC%ED%98%84-UITableViewDelegate-UITableViewDataSource</link>
            <guid>https://velog.io/@hello_hidi/iOS-TableView-3-TableView-%EA%B5%AC%ED%98%84-UITableViewDelegate-UITableViewDataSource</guid>
            <pubDate>Thu, 22 Dec 2022 19:06:28 GMT</pubDate>
            <description><![CDATA[<h2 id="3-uitableviewdelegate">3. UITableViewDelegate</h2>
<p>테이블 뷰에서 section의 header, footer를 관리하고 셀을 삭제하거나 위치를 바꾸고 그 외의 다른 작업을 수행하기 위한 메서드를 제공한다.</p>
<blockquote>
<p>이 프로젝트에서는 많은 Delegate 메소드 중에서 3가지를 써볼 것이다. (2개는 헤더뷰 관련)</p>
</blockquote>
<h3 id="3-1-delegate-선언하기">3-1. delegate 선언하기</h3>
<blockquote>
<p><strong>UITableViewDelegate는 프로토콜이다!!</strong>
즉 <strong>테이블뷰가 해야하는 일을 UITableViewDelegate에게 위임</strong>해서 위에 정의한 기능들을 수행하는 것이다!</p>
</blockquote>
<pre><code class="language-swift">public lazy var friendTableView = UITableView(frame: .zero, style: .grouped).then {
        $0.backgroundColor = .clear
        $0.translatesAutoresizingMaskIntoConstraints = false
        $0.separatorStyle = .none
        $0.delegate = self //-&gt; 바로 이 코드로 위임을 하는거겠죠???
        $0.dataSource = self //-&gt; 이것도 똑같이 위임 (여기서 코드 보시고 아래서 설명할게용!)
    }</code></pre>
<h3 id="3-2-heightforrowat">3-2. heightForRowAt</h3>
<blockquote>
<p>UITableDelegate는 의무적으로 선언해야 되는 메소드가 없습니다. (DataSource는 아님)
많은 메소드가 있는데 그 중 한가지를 사용해 볼 생각입니다!</p>
</blockquote>
<p><strong>heightForRowAt</strong> : 셀 하나의 높이를 지정해주는 함수
아래 코드를 통해서 한 셀의 높이가 50이라는 것을 지정해줄 수 있겠죠?</p>
<pre><code class="language-swift">//MARK: - UITablViewDelegate

extension FriendView: UITableViewDelegate {
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -&gt; CGFloat {
        return 50
    }</code></pre>
<h2 id="4-uitableviewdatasource">4. UITableViewDataSource</h2>
<p>테이블 뷰는 데이터를 보여주기만 하는 것이지 자체적으로 데이터를 관리할 수 없기 때문에 
<strong>UITableViewDataSource 프로토콜</strong>을 사용해야 한다. </p>
<blockquote>
<p>테이블에서 데이터와 관련된 요청이 오면 응답하며 테이블의 데이터를 직접 관리하거나 앱의 다른 부분과 조정하여 해당 데이터를 관리한다. </p>
</blockquote>
<h3 id="4-1-datasourece-선언하기">4-1. dataSourece 선언하기</h3>
<blockquote>
<p><strong>UITableViewDataSourece도 프로토콜이다!</strong>
즉 delegate처럼 선언해주면 된다.</p>
</blockquote>
<h3 id="4-2-datasource-method">4-2. dataSource Method</h3>
<blockquote>
<p>UITableViewDataSource에서는 의무적으로 선언해줘야 되는 메소드 2개가 있는데 바로</p>
</blockquote>
<ul>
<li>몇 개의 셀인지? =&gt; <strong>numberOfRowsInSection</strong></li>
<li>셀이 어떻게 생겼지? -&gt; <strong>cellForRowAt</strong>
이렇게 2가지이다! 여기서도 이 두가지를 구현해보겠다!</li>
</ul>
<h4 id="numberforerowsinsection">numberForeRowsInSection</h4>
<blockquote>
<p>몇개의 셀인지 지정해주는 함수
우리는 더미데이터에 쌓여있는 사용자의 개수만큼을 사용할 예정이기 때문에 더미데이터의 개수를 리턴한다!</p>
</blockquote>
<pre><code class="language-swift">extension FriendView: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
        return friendDummyModel.count
    }</code></pre>
<h3 id="4-3-cellforrowat">4-3. cellForRowAt</h3>
<blockquote>
<p>어떤 데이터를 보여주는 셀인지 지정하는 함수! 중요하기 때문에 하나씩 뜯어보겠습니다.</p>
</blockquote>
<pre><code class="language-swift">func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -&gt; UITableViewCell {
        guard let friendCell = tableView.dequeueReusableCell(
            withIdentifier: FriendTableViewCell.identifier,
            for: indexPath)
                as? FriendTableViewCell else { return UITableViewCell() }

        friendCell.dataBind(model: friendDummyModel[indexPath.row])
        return friendCell
    }</code></pre>
<h4 id="1-dequeuereusablecell">1. dequeueReusableCell</h4>
<blockquote>
<p> 재사용 큐에서 필요한 cell을 dequeue 하기 위한 함수</p>
</blockquote>
<ul>
<li>widthIdentifier: 식별자로 재사용 큐 안의 셀들을 구분하기 때문에 <strong>식별자</strong>가 들어감!</li>
<li>for: indexPath: tableView의 행을 식별하기 위해 사용한다!
   indexPath.row(행) 과 indexPath.section(섹션)으로 구분된다!!!</li>
</ul>
<h4 id="2-databind">2. dataBind()</h4>
<blockquote>
<p>dataBind를 통해서 각 셀별로(indexPath.row) 순서에 맞는 값을 넣어준다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[iOS] TableView (2) TableView 구현 - TableViewCell 구현!]]></title>
            <link>https://velog.io/@hello_hidi/iOS-TableView-2-TableView-%EA%B5%AC%ED%98%84-TableViewCell-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@hello_hidi/iOS-TableView-2-TableView-%EA%B5%AC%ED%98%84-TableViewCell-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Thu, 22 Dec 2022 18:25:08 GMT</pubDate>
            <description><![CDATA[<p>저번 포스팅에서 개념을 배워봤으니 이제 적용을 해보장!
솝트 3차 세미나 과제 중 친구뷰를 통해서 실전 연습을 해보장!</p>
<h2 id="0-스케치">0. 스케치</h2>
<blockquote>
<ul>
<li>테이블뷰와 무관한 FriendTopView는 포스팅은 안하지만! 코드는 남겨둘게용가링</li>
</ul>
</blockquote>
<p><img src="https://velog.velcdn.com/images/hello_hidi/post/c9612919-5aad-48fb-97d0-ab80292cc3cd/image.jpg" alt=""></p>
<h2 id="1-model-구현하기">1. Model 구현하기</h2>
<blockquote>
<p><strong>모델에는 셀에서 반복되게 바뀌는 값을 구현하면 된다!</strong>
여기서는 프로필이미지, 프로필네임, 프로필메세지가 반복적으로 바뀜으로 구조체를 통해서 선언해줬다.
그리고 각각의 사용자를 리스트로 저장했다.</p>
</blockquote>
<pre><code class="language-swift">import Foundation
import UIKit

struct FriendModel {
    let profileImage: UIImage
    let profileName: String
    let profileMessage: String
}

var friendDummyModel: [FriendModel] = [
    FriendModel(profileImage: Image.friendProfileImage1, profileName: &quot;안솝트&quot;, profileMessage: &quot;피곤해요&quot;),
    FriendModel(profileImage: Image.friendProfileImage2, profileName: &quot;최솝트&quot;, profileMessage: &quot;살려해요&quot;),
    FriendModel(profileImage: Image.friendProfileImage3, profileName: &quot;정솝트&quot;, profileMessage: &quot;배고파요&quot;),
    FriendModel(profileImage: Image.friendProfileImage4, profileName: &quot;강솝트&quot;, profileMessage: &quot;햄볶아요&quot;),
    FriendModel(profileImage: Image.friendProfileImage5, profileName: &quot;오솝트&quot;, profileMessage: &quot;행복해요&quot;),
    FriendModel(profileImage: Image.friendProfileImage6, profileName: &quot;황솝트&quot;, profileMessage: &quot;기뻐해요&quot;),
    FriendModel(profileImage: Image.friendProfileImage7, profileName: &quot;최솝트&quot;, profileMessage: &quot;공부해요&quot;),
    FriendModel(profileImage: Image.friendProfileImage8, profileName: &quot;고솝트&quot;, profileMessage: &quot;슬퍼해요&quot;),
    FriendModel(profileImage: Image.friendProfileImage9, profileName: &quot;하솝트&quot;, profileMessage: &quot;조용해요&quot;)
]</code></pre>
<h2 id="2-tableviewcell-구현하기">2. TableViewCell 구현하기</h2>
<p>테이블뷰를 구성하는 셀들을 만들 차례이다. 중요하니 천천히 해보장
일단 셀을 구성하는 UI Components를 구성한다.</p>
<pre><code class="language-swift">//MARK: - UI Components

    private let profileImageView = UIImageView().then {
        $0.makeRounded(radius: 18)
    }

    private let profileNameLabel = UILabel().then {
        $0.font = UIFont(name: &quot;AppleSDGothicNeo-SemiBold&quot;, size: 12)
        $0.textColor = 0x191919.color
    }

    private let profileMessageLabel = UILabel().then {
        $0.font = UIFont(name: &quot;AppleSDGothicNeo-Regular&quot;, size: 11)
        $0.textColor = 0xA6A6A6.color
    }</code></pre>
<h3 id="2-1-identifial-선언하기">2-1. identifial 선언하기</h3>
<blockquote>
<p>저번 포스팅에서 TableView는 재사용 큐를 사용한다고 했죠?
재사용하기 위해서는 셀을 테이블뷰에 등록시키는 작업을 해야되요! =&gt; 어디서? <strong>⭐️뷰컨트롤러에서⭐️</strong>
그러면 어떻게 이게 맞는지 알 수 있을까요? 
이때 식별자인 identifier 값으로 어떤 Cell인지 구분하게 됩니다.</p>
</blockquote>
<pre><code class="language-swift">import Foundation
import UIKit

import SnapKit
import SwiftyColor
import Then

final class FriendTableViewCell: UITableViewCell {

    //MARK: - Properties

    static let identifier = &quot;FriendTableViewCell&quot;</code></pre>
<h3 id="2-2-초기화-함수">2-2. 초기화 함수</h3>
<blockquote>
<p>UITableViewCell을 스타일과 재사용 식별자로 테이블 셀을 초기화하고 호출자에게 반환합니다.
그리고 여기서 UI Component를 View에 보여주는 setUpView()랑 AutoLayout에서 setupConstraints()를 같이 초기화해줍니다!
초기화의 자세한 부분은 UICollcetionView 생명주기에서 다루겠습니다!</p>
</blockquote>
<pre><code class="language-swift">//MARK: - Life Cycles

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setupView()
        setupConstraints()
    }

    required init?(coder: NSCoder) {
        fatalError(&quot;init(coder:) has not been implemented&quot;)
    }</code></pre>
<h3 id="2-3-databind-함수-구현">2-3. dataBind() 함수 구현</h3>
<blockquote>
<p>dummyData에서 만들어준 초기값을 각 셀에 연결해주는 함수입니다!</p>
</blockquote>
<pre><code class="language-swift">func dataBind(model: FriendModel) {
        profileImageView.image = model.profileImage
        profileNameLabel.text = model.profileName
        profileMessageLabel.text = model.profileMessage
    }</code></pre>
<h3 id="2-4-register-함수-구현">2-4. register() 함수 구현</h3>
<blockquote>
<p>테이블뷰에서는 다양한 디자인에 대응하기 위해 커스텀 셀을 많이 만들게 되는데, 테이블뷰에서 해당 커스텀 셀을 사용하기 위해서는 UITableView.register() 함수를 사용합니다!</p>
</blockquote>
<ul>
<li>셀을 만드는 데 사용할 nib 파일을 지정하는 nib 객체와</li>
<li>어떤 셀인지 알 수 있는 식별자인 identifial을 보여준다.</li>
</ul>
<pre><code class="language-swift"> //MARK: - Custom Method

    private func register() {
        friendView.friendTableView.register(
            FriendTableViewCell.self, forCellReuseIdentifier: FriendTableViewCell.identifier) }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[iOS] TableView (1) TableView란?]]></title>
            <link>https://velog.io/@hello_hidi/iOS-TableView-1-TableView%EB%9E%80</link>
            <guid>https://velog.io/@hello_hidi/iOS-TableView-1-TableView%EB%9E%80</guid>
            <pubDate>Wed, 21 Dec 2022 11:43:07 GMT</pubDate>
            <description><![CDATA[<h1 id="tableview">TableView</h1>
<h2 id="tableview란">TableView란?</h2>
<h4 id="반복되는-뷰들을-메모리-차원에서-효율적으로-관리하고-적은-코스트로-개발할-수-있는-방법">반복되는 뷰들을 메모리 차원에서 효율적으로 관리하고 적은 코스트로 개발할 수 있는 방법!</h4>
<p>이 뷰를 AutoLayout으로 노래 한개씩 전부 만든다고 생각한다면.. 그리고 그 곡이 한 9만개가 된다면 음... 아마 아요 개발을 포기하게 될 것이다. 우리는 이 뷰를 테이블뷰를 통해서 구현해볼 것이다.
<img src="https://velog.velcdn.com/images/hello_hidi/post/a6fd4102-c03e-443a-b927-42457f3bea44/image.png" alt=""></p>
<h2 id="tableview의-특징">TableView의 특징</h2>
<ul>
<li>ScrollView를 상속한다.(direction: vertical)</li>
<li>목록 형태의 뷰를 구현하는데 용이하다.</li>
<li>재사용 큐를 활용하여 메모리 관리에 수월하다.</li>
<li>셀, Delegate, DataSource의 개념의 숙지가 필요하다.</li>
</ul>
<h2 id="tableview의-기본-형태">TableView의 기본 형태</h2>
<ul>
<li>하나의 열과 여러 줄의 행을 지닌다.</li>
<li>수직으로 스크롤이 가능하다.</li>
<li>각 행은 하나의 셀에 대응한다.</li>
<li>섹션을 이용해 행을 시각적으로 나눌 수 있다.</li>
<li>헤더와 푸터에 이미지나 텍스트를 추가해 추가 정보를 보여줄 수 있다.
<img src="https://velog.velcdn.com/images/hello_hidi/post/f67133c7-88f4-430a-98f5-67de6e05f95e/image.png" alt="">
<img src="https://velog.velcdn.com/images/hello_hidi/post/e7a38da6-3159-4bed-9777-db4e74df2efa/image.png" alt=""></li>
</ul>
<h2 id="tableviewcell이란">TableViewCell이란?</h2>
<p><strong>테이블뷰를 이루는 개별적 행으로, UITableViewCell 클래스를 상속받는다.</strong></p>
<h3 id="재사용큐">재사용큐</h3>
<blockquote>
<p>재사용 큐를 활용하여 메모리 관리에 수월하다? 이게 무슨 특징일까?</p>
</blockquote>
<ul>
<li>테이블 뷰가 출력해야할 데이터가 많을 경우, 이를 한꺼번에 셀로 만들어 처리하면 메모리 소모가 많아 스크롤이 버벅대는 현상이 생긴다. </li>
<li>그래서 메모리 절약을 위해서 화면에 보여줄 수 있는 딱 그만큼의 셀만 생성해서 출력해준다.
ex) Cell의 데이터가 100개가 있고, 화면에 표시되는 Cell 갯수가 10개</li>
<li><em>=&gt; 화면에 해당 Cell이 보일 때 그 셀에 알맞는 데이터만 넣어주면 된다!*</em></li>
<li>나머지 셀은 스크롤이 발생했을 때 생성해서 목록에 추가하며, 동시에 스크롤에 의해 화면에서 벗어난 셀은 목록에서 뺀다.</li>
<li><strong>이때 목록에서 제외된 셀을 지우지 않고 재활용해서 다시 사용할 수 있도록 처리한다!</strong></li>
</ul>
<h4 id="이-과정에서-목록에서-제외된-셀이-재사용되기-전까지-머무는-장소가-바로-재사용큐이다">이 과정에서 목록에서 제외된 셀이 재사용되기 전까지 머무는 장소가 바로 재사용큐이다!</h4>
<p>(내가 이해한 느낌은 살짝 모델 런웨이하는 느낌! 화면에 나오는 부분이 런웨이하는 공간이고, 재사용큐는 뒤에서 준비하는 공간, 거기서 각 셀들은 또 다른 옷을 입고 나올 준비를 하고 있다고 생각하면 되지 않을까?)
<img src="https://velog.velcdn.com/images/hello_hidi/post/d4625c39-477f-4e52-bc4c-596dcee4ab49/image.png" alt=""></p>
<p>코드적인 부분은 다음 블로그에서~!</p>
<h2 id="delegate--datasource">Delegate &amp; DataSource</h2>
<blockquote>
<p>UITableVIew 객체는 데이터 소스와 델리게이트가 없다면 정상적으로 동작하기 어려우므로 두 객체가 꼭 필요하다!</p>
</blockquote>
<p>&lt;MVC모델 기준으로 볼때 (모델, 뷰, 컨트롤러)&gt;</p>
<ul>
<li>DataSource -&gt; M</li>
<li>Delegate -&gt; C</li>
<li>TableView -&gt; V</li>
</ul>
<p><img src="https://velog.velcdn.com/images/hello_hidi/post/14b2407f-f01c-437c-9991-d72357510813/image.png" alt=""></p>
<h3 id="delegate">Delegate</h3>
<ul>
<li>테이블뷰 델리게이트 객체는 <strong>UITableViewDelegate</strong> 프로토콜을 채택한다.</li>
<li><strong>델리게이트는 테이블뷰의 시각적인 부분 수정, 행의 선택 관리, 액세서리뷰 지원그리고 테이블뷰의 개별행 편집을 돕는다.</strong></li>
<li>델리게이트 메서드를 활용한면 테이블뷰의 세세한 부분을 조정할 수 있다.</li>
</ul>
<h3 id="datasource">DataSource</h3>
<ul>
<li>테이블뷰 데이터 소스 객체는 <strong>UITableViewDataSource</strong> 프로토콜을 채택한다.</li>
<li>데이터 소스는 테이블 뷰를 생성하고 수정하는데 필요한 정보를 테이블뷰 객체에 제공한다.</li>
<li>데이터 소스는 데이터 모델의 델리게이트로, 테이블뷰의 시각적 모양에 대한 최소하느이 정보를 제공한다.</li>
<li><strong>UITableView 객체에 섹션의 수와 행의 수를 알려주며, 행의 삽입, 삭제 및 재정령하는 기능을 선택적으로 구현할 수 있다.</strong></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 4주차(4) 프로퍼티 옵저버]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-4%EC%A3%BC%EC%B0%A84-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0-%EC%98%B5%EC%A0%80%EB%B2%84</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-4%EC%A3%BC%EC%B0%A84-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0-%EC%98%B5%EC%A0%80%EB%B2%84</guid>
            <pubDate>Tue, 13 Dec 2022 12:18:48 GMT</pubDate>
            <description><![CDATA[<h1 id="property-observer">Property Observer</h1>
<blockquote>
<p>프로퍼티 값의 변화를 관찰하는 것으로, &quot;저장 프로퍼티&quot;에 추가할 수 있다
새 값의 속성이 현재 값과 동일하더라도 속성 값이 설정되면 호출된다!</p>
</blockquote>
<p>쉽게 말해서
** 내가 관찰하는 프로퍼티에 값을 설정하려고 할때 변경을 감지한다.**</p>
<h2 id="willset">willSet</h2>
<blockquote>
<p>값이 저장되기 직전에 새로 저장될 값이 파라미터로 전달된다!
이때 파라미터 이름은 지정할 수 있지만 파라미터 이름과 괄호를 따로 지정하지 않을 경우 newValue 사용</p>
</blockquote>
<pre><code class="language-swift">var name: String = &quot;Unknown&quot; {
    willSet(newName) {
        print(&quot;현재 이름 = \(name), 바뀔 이름 = \(newName)&quot;)
    }
}

var name: String = &quot;Unknown&quot; {
    willSet {
        print(&quot;현재 이름 = \(name), 바뀔 이름 = \(newValue)&quot;)
    }
}

name = &quot;Hidi&quot;
// 현재 이름 = Unknown, 바뀔 이름 = Hidi
// 값이 변경되기 &quot;직전&quot;에 호출되는 것이라
// 현재 이름(name)은 아직 이전 값인 Unknown임!!!!</code></pre>
<h2 id="didset">didSet</h2>
<blockquote>
<p>값이 저장된 &quot;직후&quot;에 이전 프로퍼티의 값이 &quot;파라미터&quot;로 전달된다!
이때 파라미터 이름은 지정할 수 있지만, 파라미터 이름과 괄호를 따로 지정하지 않을 경우 oldValue로 사용한다</p>
</blockquote>
<pre><code class="language-swift">var name: String = &quot;Unknown&quot; {
   didSet {
        print(&quot;현재 이름 = \(name), 바뀌기 전 이름 = \(oldValue)&quot;)
    }
}

var name: String = &quot;Unknown&quot; {
   didSet {
        print(&quot;현재 이름 = \(name), 바뀌기 전 이름 = \(oldValue)&quot;)
    }
}

name = &quot;Hidi&quot;
// 현재 이름 = Hidi, 바뀌기 전 이름 = Unknown
// 값이 변경된 &quot;직후&quot;에 호출되는 것이라
// 이전에 저장되어 있던 Unknown이 파라미터 oldValue로 넘어온 것</code></pre>
<h3 id="두개-같이-사용-가능">두개 같이 사용 가능?</h3>
<blockquote>
<p>A. 쌉가능</p>
</blockquote>
<ol>
<li>willSet이 먼저 실행</li>
<li>저장 프로퍼티 name의 값 변경</li>
<li>didSet 실행</li>
</ol>
<pre><code class="language-swift">var name: String = &quot;Unknown&quot; {
    willSet {
        print(&quot;현재 이름 = \(name), 바뀔 이름 = \(newValue)&quot;)
    }
    didSet {
        print(&quot;현재 이름 = \(name), 바뀌기 전 이름 = \(oldValue)&quot;)
    }
}

name = &quot;Sodeul&quot;</code></pre>
<h3 id="연산-프로퍼티--프로퍼티-옵저버-가능">연산 프로퍼티 + 프로퍼티 옵저버 가능?</h3>
<blockquote>
<p>가능하다. but 부모클래스의 연산 프로퍼티를 오버라이딩 할 경우에만!
why? setter을 통해 값 변경 감지가 가능한데 굳이..?</p>
</blockquote>
<pre><code class="language-swift">class Human {
    var name = &quot;Unknown&quot;
    var alias: String {
        get {
            return name + &quot; 바보&quot;
        }
        set {
            name = newValue + &quot;별명에서 붙여진 이름&quot;
        }
        willSet { }       // error! &#39;willSet&#39; cannot be provided together with a getter
        didSet  { }       // error! &#39;didSet&#39; cannot be provided together with a getter
    }
}


class Hidi: Human {
    override var alias: String {
        willSet {
            print(&quot;현재 alias = \(alias), 바뀔 alias = \(newValue)&quot;)
        }
        didSet {
            print(&quot;현재 alias = \(alias), 바뀌기 전 alias = \(oldValue)&quot;)
        }
    }
}
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 4주차(3) 타입 프로퍼티]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-4%EC%A3%BC%EC%B0%A83-%ED%83%80%EC%9E%85-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-4%EC%A3%BC%EC%B0%A83-%ED%83%80%EC%9E%85-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0</guid>
            <pubDate>Mon, 12 Dec 2022 15:47:00 GMT</pubDate>
            <description><![CDATA[<h1 id="타입-프로퍼티type-property">타입 프로퍼티(Type Property)</h1>
<blockquote>
<p>클래스, 구조체, 열거형에서 사용되며
저장 타입 프로퍼티와 연산 타입 프로퍼티가 존재하며
저장 타입 프로퍼티의 경우 선언할 당시 원하는 값으로 항상 초기화가 되어있어야 한다
&quot;static&quot;을 이용하여 선언하며, 자동으로 lazy로 작동한다.(lazy를 직접 붙일 필요 또한 없다.)</p>
</blockquote>
<p>정의는 진짜 쉽지 않다....
쉽게 말하자면</p>
<h4 id="저장연산-프로퍼티-앞에-static-키워드만-붙이면--그것은-저장-타입-프로퍼티--연산-타입-프로퍼티가-되는-것임">저장&amp;연산 프로퍼티 앞에 static 키워드만 붙이면 =&gt; 그것은 저장 타입 프로퍼티 &amp; 연산 타입 프로퍼티가 되는 것임</h4>
<h2 id="static의-초기화에-대해서">static의 초기화에 대해서...</h2>
<p>+) static으로 선언할 경우 초기값을 지정 or 연산 타입 프로퍼티을 만들어야됨
=&gt; 선언과 동시에 저장 타입 프로퍼티 초기화 불가능</p>
<pre><code class="language-swift">class Human {
    static let name: String = &quot;hidi&quot;
    static var nickName: String {
        return name + &quot;존잘&quot;
    }
}

// 만약 선언과 동시에 저장 타입 프로퍼티를 초기화해주면?
static let name: String //에러</code></pre>
<h3 id="why---static으로-선언되는-저장-타입-프로퍼티의-경우-초기화될-때-값을-할당하는-initializer가-없기-때문">why? -&gt; static으로 선언되는 저장 타입 프로퍼티의 경우 초기화될 때 값을 할당하는 initializer가 없기 때문</h3>
<p>Q. 클래스 인스턴스가 생성될 때 initializer에 의해 모든 프로퍼티가 초기화되지 않나여?
A <strong>타입 프로퍼티는 매번 생성되는 기존 프로퍼티와 다름!</strong></p>
<p>인스턴스가 생성된다고 매번 해당 인스턴스의 멤버로 매번 생성 되는게 아니라
<strong>=&gt; 언제 한번 누군가 불러서 메메뢰에 올라가면, 그 뒤로 생성되지 않으며 언제 어디서든 이 타입 프로퍼티에 접근할 수 있음 like 전역변수띠</strong></p>
<h4 id="따라서-타입-프로퍼티는--타입이름을-통해서만-접근이-가능">따라서 타입 프로퍼티는  타입이름을 통해서만 접근이 가능!!!</h4>
<pre><code class="language-swift">let hidi: Human = .init()
hidi.name // 아니구요

Human.name // 이렇게만 접근 가능!</code></pre>
<h3 id="자동으로-lazy">자동으로 lazy?</h3>
<blockquote>
<p>타입프로퍼티는 인스턴스 생성과는 전혀 관계가 없고, 누가 불러줬을 때 한번 메모리에 올라가고! 그 뒤로는 어디서든 해당 프로퍼티를 공유가능하다!</p>
</blockquote>
<p>여기서 주목할 부분 <strong>누가 불러줬을 때 메모리에 올라간다!</strong>
=&gt; lazy와 동일, 타입 프로퍼티의 경우 기존 속성이 lazy기 때문에 최초 호출 전까진, 초기화되지 않음!</p>
<h2 id="언제-사용하나">언제 사용하나?</h2>
<p>솔직히 지금까진 모르겠는데 블로그 포스팅을 보니까 싱글톤에서 사용한다고 합니당
보통 모든 타입이 공통적인 갑을 정의하는데 유용하다고 하네영!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 4주차(2) 연산 프로퍼티]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-4%EC%A3%BC%EC%B0%A82-%EC%97%B0%EC%82%B0-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-4%EC%A3%BC%EC%B0%A82-%EC%97%B0%EC%82%B0-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0</guid>
            <pubDate>Mon, 12 Dec 2022 15:15:53 GMT</pubDate>
            <description><![CDATA[<h1 id="연산-프로퍼티computed-property">연산 프로퍼티(Computed Property)</h1>
<blockquote>
<p>클래스, 구조체, 열거형에서 사용된다.
저장 프로퍼티와 달리 저장 공간을 갖지 않고, 다른 &quot;저장 프로퍼티&quot;의 값을 읽어 연산을 실행하거나, 프로퍼티로 전달받은 값을 다른 프로퍼티에 저장한다!
<strong>때문에 항상 var로 선언되어야 한다!</strong></p>
</blockquote>
<p>이게 뭐누... 맨날 정의만 보면 무슨 말이닞 모르겠음 여기서 중점은!
<strong>직접 값을 가지지는 않고, 다른 저장 프로퍼티랑 이러쿵 저러쿵 한단다 쿵따따</strong></p>
<h2 id="get-set">get, set</h2>
<p>1) <strong>getter</strong>: 어떤 저장 프로퍼티의 값을 연산해서 return할 것인지, return구문이 항상 존재해야 함!
2) <strong>setter</strong>: 파라미터로 받은 값을 어떤 저장 프로퍼티에 어떻게 설정할 것인지를 구현! </p>
<pre><code class="language-swift">var name: Type {
    get {
        statements
        return expr
    }
    set(name) {
        statements
    }
}</code></pre>
<p>이를 기준으로 연산 프로퍼티를 다시 정의하면</p>
<blockquote>
<p>실제 값을 저장하고 있는 것이 아니라 getter와 optional한 setter를 제공해 값을 탐색하고 간접적으로 다른 프로퍼티 값을 설정할 수 있는 방법을 제공하는 프로퍼티!</p>
</blockquote>
<h3 id="예시를-보자면">예시를 보자면</h3>
<pre><code class="language-swift">class Person {
    var nickName: String {
    get {
        return nickName
    }
    set (nickName) {
        self.nickName = nickName
    }
}</code></pre>
<p>이렇게 하면 완성~ 이 아니라 저렇게 하면 졸라 많은 오류메세지 발생
why?
<strong>연산 프로퍼티는 다른 저장 프로퍼티랑 쿵짜짜 쉘위댄스 해야됨</strong>
근데 위 코드에서는 get, set에서 nickname이란 연산 프로퍼티랑 놀고 있음....ㅠㅠ</p>
<blockquote>
<p>무조건 읽거나 쓸 수 있는 저장 프로퍼티가 먼저 존재하야 하고!
연선 프로퍼티에선 다른 저장 프로퍼티의 값을 읽거나 쓰는 작업을 해야한다!
+) 원한다면 다른 연산 작업들을 직접 추가해줄 수도 있다!</p>
</blockquote>
<pre><code class="language-swift">class Person {
    var name: String = &quot;hidi&quot;

    var nickName: String {
    get {
        return name
        //or
        return self.name + &quot;기여미😚😚&quot; //+)point

    }
    set (name) {
        self.name = name
        //or
        self.name = name + &quot;❤️&quot; //+)point
    }
}</code></pre>
<h3 id="연산-프로퍼티-사용-방법">연산 프로퍼티 사용 방법</h3>
<h4 id="1-저장-프로퍼티처럼-사용하기">1. 저장 프로퍼티처럼 사용하기</h4>
<blockquote>
<p>우리가 아무렇지 않게 사용하던 저장 프로퍼티처럼 사용하면 된다!</p>
</blockquote>
<pre><code class="language-swift">let hidi: Person = .init()
// get에 접근
print(hidi.nickName) // hidi기여미😚😚

// set에 접근
hidi.nickName = &quot;유서린 남친&quot;
print(hidi.nickName) // 유서린 남친❤️
</code></pre>
<h4 id="2-newvalue---set의-파라미터는-생략이-가능하다">2. newValue -&gt; set의 파라미터는 생략이 가능하다!!</h4>
<p>Q. 우리가 정의에서 optional setter라 한 이유는 무엇일까?
A. <strong>이미 연산 프로퍼티를 선언할 때 Type을 반드시 명시해줬기 때문이다.</strong></p>
<blockquote>
<p>set의 파라미터는 단 하나만 존재하고, 파라미터의 이름은 name 말고 다른것도 가능</p>
</blockquote>
<pre><code class="language-swift">set(cute) {
    self.name = cute + &quot;❤️&quot;</code></pre>
<p>만약! set의 파라미터의 이름을 짓기 힘든새럼? =&gt; get처럼 파라미터 받는 부분을 날리고
<strong>New Value</strong>라는 이름을 접근</p>
<pre><code class="language-swift">set {
    self.name = newValue + &quot;❤️&quot;
}</code></pre>
<h4 id="3-get-only">3. get-only</h4>
<blockquote>
<p>연산 프로퍼티에서 setter가 필요 없다면, getter만 선언해줄 수 있음!
get만쓰면 get 구문 자체를 없앨 수 있음!</p>
</blockquote>
<pre><code class="language-swift">class Person {
    var name: String = &quot;hidi&quot;

    var nickName: String {
        return self.name + &quot;기여미😚😚&quot; //+)point   
    }
}</code></pre>
<h4 id="4-set-only-❌">4. set-only ❌</h4>
<blockquote>
<p>연산 프로퍼티는 반드시 get + set or get-only만 가능하다!</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 4주차(1) 저장 프로퍼티]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-4%EC%A3%BC%EC%B0%A81-%EC%A0%80%EC%9E%A5-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-4%EC%A3%BC%EC%B0%A81-%EC%A0%80%EC%9E%A5-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0</guid>
            <pubDate>Mon, 12 Dec 2022 14:31:50 GMT</pubDate>
            <description><![CDATA[<h1 id="프로퍼티">프로퍼티</h1>
<blockquote>
<p>클래스, 구조체, 열거형과 관련한 값
Swift에서는 3가지 형태로 존재하는데 바로 저장 프로퍼티, 연산 프로퍼티, 타입 프로퍼티로 구성됨</p>
</blockquote>
<h2 id="저장-프로퍼티">저장 프로퍼티</h2>
<blockquote>
<p>클래스와 구조체에서만 사용할 수 있고, 값을 저장하기 위해 선언되는 상수/ 변수
우리가 지금까지 흔히 본 케이스로 let, var을 통해서 선언 가능함!
<strong>열거형에서 사용불가❌</strong></p>
</blockquote>
<pre><code class="language-swift">class Human {
    let name: String = &quot;hidi&quot;
    var age: Int = 23
}
struct Person {
    let name: String = &quot;hidi&quot;
    var age: Int = 23
}</code></pre>
<h3 id="클래스-인스턴스를-letvar로-선언하면">클래스 인스턴스를 let/var로 선언하면!</h3>
<h4 id="1-클래스-인스턴스를-let상수로-선언할-때">1) 클래스 인스턴스를 let(상수)로 선언할 때</h4>
<p>Q. 인스턴스를 let으로 선언했는데 왜.. age가 var로 선언되어도 변경가능한지?
A. 스택에 있는 hidi은 힙 영역에 있는 인스턴스를 참조하고 있는 형태 (다들 알죠?)
스택에는 only 힙에 할당된 인스턴스의 주소값밖에 없다..</p>
<pre><code class="language-swift">let hidi: Human? = .init()
hidi?.name = &quot;hidi&quot; // 에러
hidi?.age = 24 // 가능!

//따라서 인스턴스 값 자체에 nil이 들어가는 건 안됨
hidi = nil // error</code></pre>
<h4 id="2-클래스-인스턴스를-var변수로-선언할-때">2) 클래스 인스턴스를 var(변수)로 선언할 때</h4>
<p>A. 다 가능 ㅋㅋ nil도 가능하고, 다른 Instance 대입도 되고
단. 상수로 선언된 프로퍼티 변경은 불가능하겠죠?</p>
<h3 id="구조체-인스턴스를-letvar로-선언하면">구조체 인스턴스를 let/var로 선언하면!</h3>
<h4 id="1-구조체-인스턴스를-let상수로-선언할-때">1) 구조체 인스턴스를 let(상수)로 선언할 때</h4>
<p>Q. 왜.. age가 var로 선언되어도 변경이 안되죠...?
A. 구조체는 값타입!! 그렇기 때문에 모든 프로퍼티가 스택에 저장됨
따라서 구조체 인스턴스를 let으로 선언한 순간 구조체의 모든 멤버는 변경불가!</p>
<pre><code class="language-swift">let hidi: Human? = .init()
hidi?.name = &quot;hidi&quot; // 에러!
hidi?.age = 24 // 에러!

//당연히 인스턴스 값 자체에 nil이 들어가는 건 안됨
hidi = nil // error</code></pre>
<h4 id="2-구조체-인스턴스를-var변수로-선언할-때">2) 구조체 인스턴스를 var(변수)로 선언할 때</h4>
<p>A. 다 가능 ㅋㅋ nil도 가능하고, 다른 Instance 대입도 되고
단. 상수로 선언된 프로퍼티 변경은 불가능하겠죠?</p>
<h2 id="지연-저장-프로퍼티">지연 저장 프로퍼티</h2>
<blockquote>
<p>프로퍼티가 호출되기 전까지는 선언만 될 뿐 초기화되지 않고 있다가, 프로퍼티가 호출되는 순간에 초기화되는 저장 프로퍼티
<strong>프로퍼티 앞에 lazy 키워드를 붙여서 사용한다!</strong></p>
</blockquote>
<h3 id="이게-뭔-소리야">이게 뭔 소리야...</h3>
<p>자 우리가 기존에 알고있던 초기화의 상식은..
초기화 구문이 불리는 순간 모든 프로퍼티가 초기화가 되어야 했다!!! (저번주꺼 참고<del>)
그래서 초기화 구문 바로 실행띠</del>!</p>
<pre><code class="language-swift">class Sopt {
    var part: String = &quot;&quot;
    var generation: String = &quot;&quot;

    init() { print(&quot;안녕 난 Sopt인&quot;) }
}

class Human {
    var name: String = &quot;unKnown&quot;
    var sopt: Sopt = .init()

// 클래스 인스턴스를 초기화를 하면
let hidi: Human = .init()

// 결과로
&quot;안녕 난 SOPT인&quot;</code></pre>
<p>but lazy 키워드를 붙여서 선언을 한다면...
선안만 될 뿐, 변수 자체가 초기화되지 않아서 변수에 처음으로 접근할 때 
초기화 구문 발동~!</p>
<pre><code class="language-swift">class Sopt {
    var part: String = &quot;&quot;
    var generation: String = &quot;&quot;

    init() { print(&quot;안녕 난 SOPT인&quot;) }
}

class Human {
    var name: String = &quot;unKnown&quot;
    lazy var sopt: Sopt = .init()

// 클래스 인스턴스를 초기화를 하면
let hidi: Human = .init()

// 결과로 암것도 안나옴 =&gt; lazy로 인한 지연

// 따라서 contacts란 변수에 처음으로 접근하고자 할때
hidi.contacts.part = &quot;iOS&quot;
// 결과로
&quot;안녕 난 SOPT인&quot;</code></pre>
<h3 id="지연-저장-프로퍼티의-특징">지연 저장 프로퍼티의 특징</h3>
<blockquote>
<ul>
<li>인스턴스 초기화와 상관없이, 처음 사용될 때 개별적으로 초기화 된다! (위에서 본 내용)</li>
</ul>
</blockquote>
<ul>
<li><strong>따라서 항상 var(변수)로 선언되어야 한다!</strong>
why? let으로 서언되면 우리가 필요한 시점에 초기화를 진행할 수 없기 때문!</li>
</ul>
<h3 id="언제-사용되나요">언제 사용되나요?</h3>
<blockquote>
<ol>
<li>특정 요소에 의존적이어서 그 요소가 끝나기 전에 적절한 값을 알지 못하는 경우에 유용합니다.</li>
<li>복잡한 계산이나 부하가 많이 걸리는 작업 =&gt; 실제 사용되기 전에는 실행되지 않아서 인스턴스의 초기화 시점에 복잡한 계산을 피할 수 있습니다.</li>
</ol>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 3주차(3) Initializer Delegation]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-3%EC%A3%BC%EC%B0%A83-Initializer-Delegation</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-3%EC%A3%BC%EC%B0%A83-Initializer-Delegation</guid>
            <pubDate>Tue, 29 Nov 2022 03:41:56 GMT</pubDate>
            <description><![CDATA[<h1 id="initializer-delegation">Initializer Delegation</h1>
<blockquote>
<p>생성자에서 또 다른 생성자를 호출하여 초기화 코드의 중복을 최대한 제거하고, 모든 프로퍼티를 효율적으로 초기화 하기위해 사용하는 것! 값타입과 참조타입을 나눠서 설명하겠당!</p>
</blockquote>
<h2 id="delegation을-안한-예시">Delegation을 안한 예시</h2>
<blockquote>
<p>아래 코드는 모든 프로퍼티 x, y값을 초기화 하는 코드를 두 곳 모두에서 작성하고 있으니 
=&gt; 중복된 코드 =&gt; Initializer Delegation을 따르고 있지 않음!
물론 이렇게 작성해도 이상할거 하나 없지만 중복을 줄이면서 유지보수가 좋은 방향으로 코드를 구현하는것이 또 개발자의 낭만 아니겠습니까<del>?</del>?</p>
</blockquote>
<pre><code class="language-swift">struct Position {
    var X: Int
    var Y: Int

    init(xPos: Int, yPos: Int) {
        x = xPos
        y = yPos
    }

    init(pos: Int) {
        x = pos
        y = pos
    }
}</code></pre>
<h2 id="값-타입의-initializer-delegation">값 타입의 Initializer Delegation</h2>
<p><strong>생성자에서 또 다른 생성자를 호출하여 초기화 코드의 중복을 최대한 제거!</strong>
코드로 보면 바로 아~ 할것임</p>
<ul>
<li><p>모든 프로퍼티를 초기화 하는 Initializer를 먼저 하나 만들고</p>
</li>
<li><p>다른 Initializer가 이 Initializer를 사용하게 만든다! (self.init)</p>
<pre><code class="language-swift">struct Position {
  var X: Int
  var Y: Int

  init(xPos: Int, yPos: Int) {
      x = xPos
      y = yPos
  }

  init(pos: Int) {
      self.init(xPos: pos, yPos: pos)
  }
}</code></pre>
</li>
</ul>
<h2 id="참조-타입의-initializer-delegation">참조 타입의 Initializer Delegation</h2>
<p><strong>값 타입과 똑같지만! 3가지 규칙을 지켜야 한다!</strong>
하지만 앞에서 다 배운것들이야! 걱정하지마!</p>
<h3 id="designated-convenience-initializers">Designated, Convenience Initializers</h3>
<h4 id="designated-initializers">Designated Initializers</h4>
<blockquote>
<ul>
<li>init 함수가 끝나기 전에 모든 프로퍼티의 값이 초기화 되어있어야 한다!</li>
</ul>
</blockquote>
<ul>
<li>서브 클래스인 경우, super 클래스의 init 메서드를 반드시 호출 해줘야 한다!</li>
</ul>
<h4 id="convenience-initializers">Convenience Initializers</h4>
<blockquote>
<ul>
<li>Designated Initializers의 초기화를 보조해주는 역할</li>
</ul>
</blockquote>
<ul>
<li>파라미터 중 일부를 기본값으로 설정해서 호출할 수 있따!</li>
<li>반드시 같은 클래스 계층 내에 있는 Designated Initializers가 호출되어야 한다!</li>
</ul>
<h3 id="규칙-1-delegate-up">규칙 1) Delegate Up</h3>
<blockquote>
<p>Designated Initializer는 반드시 슈퍼클래스의 Designated Initializer를 호출해야 한다!
<img src="https://velog.velcdn.com/images/hello_hidi/post/49110c4d-fe65-483c-a103-cdb33889bf2a/image.png" alt=""></p>
</blockquote>
<h3 id="규칙-2-delegate-across1">규칙 2) Delegate Across(1)</h3>
<blockquote>
<p>Convenience Initializer는 반드시 동일한 계층의 initailizer를 호출해야 한다! </p>
</blockquote>
<h3 id="규칙-3-delegate-across2">규칙 3) Delegate Across(2)</h3>
<blockquote>
<p>Convenience Initializer는 최종적으로 동일한 계층의 Designated initialize를 호출해야 한다!</p>
</blockquote>
<pre><code class="language-swift">class Figure {
  let name: String

  init(name: String) {
    self.name = name 
  }

  // Delegate Across
  convenience init() {
    self.init(name: &quot;unknown&quot;)
  }
}

class Rectangle: Figure {
  var width = 0.0
  var height = 0.0

  // Delegate Up
  init(n: String, w:Double, h: DOuble){
    weidth = w
    height = h
    super.init(name: n)
  }

  // Delegate Across
  convenience init(value: Double) {
    self. init(n: &quot;rect&quot;, w: value, h: value) // initialize Delegate
  }
}

class square: Rectangle {
  convenience init(value: Double) {
    self.init(m: &quot;square&quot;, w: value, h: value)
  }

  convenience init() {
    self.init(value: 0.0)
  }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 3주차(2) 클래스 초기화]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-3%EC%A3%BC%EC%B0%A82-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%B4%88%EA%B8%B0%ED%99%94</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-3%EC%A3%BC%EC%B0%A82-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%B4%88%EA%B8%B0%ED%99%94</guid>
            <pubDate>Tue, 29 Nov 2022 02:13:20 GMT</pubDate>
            <description><![CDATA[<h1 id="초기화">초기화</h1>
<p><strong>구조체 / 열거형 / 클래스의 인스턴스를 생성하는 것</strong></p>
<blockquote>
<p><strong>초기화의 역할은 모든 프로퍼티를 기본값으로 초기화 하는 것이다.</strong>
인스턴스 내 기본값이 존재하지 않는 프로퍼티가 있을 경우 초기화에 실패하고 인스턴스는 생성되지 않는다!</p>
</blockquote>
<h2 id="왜-초기화를-해야-되나">왜 초기화를 해야 되나?</h2>
<blockquote>
<p>스위프트는 에러에 대한 안전을 최우선시 한다.
빈 메모리에 접근하게 된다면 예기치 못한 에러가 발생할 수 있다.
타입 내부에 프로퍼티가 있다면 해당 프로퍼티에는 무조건 값이 있다는 것을 보장해야 한다.</p>
</blockquote>
<h2 id="클래스-초기화-방법">클래스 초기화 방법</h2>
<h3 id="1-선언과-동시에-프로퍼티에-기본값-넣어주기">1) 선언과 동시에 프로퍼티에 기본값 넣어주기</h3>
<pre><code class="language-swift">class Human {
    let name : String = &quot;희재&quot;
    let age : Int = 23
}

let ryu = Human()
dump(ryu)

// - name : &quot;희재&quot;
// - age : 23</code></pre>
<h3 id="2-프로퍼티의-타입을-옵셔널-타입으로-설정하기">2) 프로퍼티의 타입을 옵셔널 타입으로 설정하기</h3>
<p>값이 있을지 없을지 모르는 경우 옵셔널 타입으로 선언, 그러면 초기화할 때 옵셔널 타입인 name, age는 자동으로 nil로 초기화
<strong>=&gt; 옵셔널 타입으로 선언하지 않으면 nil값을 받지 못함</strong>
<strong>var로 선언해야한다!</strong></p>
<pre><code class="language-swift">class Human {
    var name : String?
    var age : Int?
}

let ryu = Human()
dump(ryu)
//  - name: nil
//  - age: nil</code></pre>
<h3 id="3-init-함수에서-값-설정해주기">3) init 함수에서 값 설정해주기</h3>
<p>초기화를 진행 하는 함수인 init함수 즉 생성자를 사용하여 생성자 안에서 해당 프로퍼티들을 초기화 시킬 수 있음.</p>
<ul>
<li><p>다양하게 선언할 수 있다.</p>
</li>
<li><p><strong>중요한건 init함수가 종료되기 전까진 모든 프로퍼티가 기본 값을 가져야한다!!!</strong></p>
<pre><code class="language-swift">class Human {
  var name : String?
  let age : Int
  let nickName : String = &quot;hidi&quot;

  init(name: String) {
      self.age = 23
  }
}
</code></pre>
</li>
</ul>
<p>//but.. init함수 종료 전까지 모든 프로퍼티가 기본값을 가져야함
let ryu = Human(name : &quot;ryu&quot;)
dump(ryu)
// - name: nil
//  - age: 23
//  - nickName: &quot;hidi&quot;</p>
<pre><code>
### Q. 클래스도 구조체처럼 암것도 초기화 안해도 에러 안나나요?
A. 아니요. 나요 무조건 나요! 그 이유는 Memberwise Initializers를 제공하지 않기 때문!

&gt; why? &#39;자동화된 초기화가 존재할 경우 상속의 상황에서 발생할 수 있는 오류를 개발자가 직접 변경하는 작업이 더 번거롭기 때문에&#39;라고 정의할 수 있습니다. 자세한건  &lt;a href=&quot;https://aisi1004.tistory.com/954&quot;&gt;여기서&lt;/a&gt;

## 클래스의 Initializers

### 1) Desigated Initializers (지정 생성자)
**클래스의 모든 프로퍼티를 초기화 하는 생성자**
우리가 지금까지 쓰고 있던 ini함수가 바로 지정 생성자이다!!!
두가지의 특징을 설명하자면!

&gt;#### 1. 해당 생성자 메서드가 종료되기 전까지, 생성자 안에 모든 프로퍼티는 &quot;초기값&quot;을 지니고 있어야 한다!
옵셔널 변수로 안되거나, 기본 값을 갖지 않는 프로퍼티가 있을 경우엔 생성자를 추가하여 초기값을 지정해줘야 한다!
#### 2. 반드시 super 클래스의 생성자를 호출해야 한다!
만약 부모 클래스의 프로퍼티 중 초기값을 가지지 않는다면 초기화가 안되겠죠?
![](https://velog.velcdn.com/images/hello_hidi/post/f7f33d9b-4981-4aa7-974b-38080dcf3d8e/image.png)

```swift
class Human {
    var name : String
    var age : Int

    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }
}

class Ryu: Human {
    var nickName : String

    init(nickName: String){
        self.nickName = nickName
        super.init(name: &quot;희재&quot;, age: 23)
    }
}

var ryu = Ryu(nickName: &quot;hidi&quot;)
dump(ryu)</code></pre><h3 id="2-convenience-initializers">2) Convenience Initializers</h3>
<p><strong>모든 프로퍼티를 초기화 할 필요 없는 생성자로, 반드시 다른 초기화를 호출시켜야 한다.</strong>
** 이때 슈퍼 클래스의 생성자는 호출 시킬 순 없고, 같은 클래스 내에 Conveninece Initializers나 Designated Initializers를 호출 시켜야 한다**
<strong>최종ㅈ거으로 같은 클래스 내의 Designated Initializers가 호출되어야 한다</strong></p>
<p><img src="https://velog.velcdn.com/images/hello_hidi/post/dcb65cde-a55b-4fe3-b69f-0fb86103a0d1/image.png" alt=""></p>
<h4 id="한-마디로-말해서-designated-initializers를-도와주는-역할이다">한 마디로 말해서!!! Designated Initializers를 도와주는 역할이다!</h4>
<p>같은 클래스에 있는 다른 초기화 놈을 또 호출 시키는 것!!!
따라서 최종적으로 같은 클래스 내에 Designated Initializers를 도와준다!</p>
<pre><code class="language-swift">class Human {
    var name : String
    var nickName : String

    init(name: String, nickName : String) {
        self.name = name
        self.nickName = nickName
    }

    convenience init(name: String) {
        self.init(name: name, nickName: &quot;unknown&quot;)
    }

    convenience init() {
        self.init(name: &quot;unknown&quot;)
    }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/hello_hidi/post/6e4a3ee6-9159-4beb-8949-3426e20b25ac/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 3주차(1) 구조체 초기화]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-3%EC%A3%BC%EC%B0%A81-%EA%B5%AC%EC%A1%B0%EC%B2%B4-%EC%B4%88%EA%B8%B0%ED%99%94</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-3%EC%A3%BC%EC%B0%A81-%EA%B5%AC%EC%A1%B0%EC%B2%B4-%EC%B4%88%EA%B8%B0%ED%99%94</guid>
            <pubDate>Mon, 28 Nov 2022 10:39:56 GMT</pubDate>
            <description><![CDATA[<h1 id="초기화">초기화</h1>
<p><strong>구조체 / 열거형 / 클래스의 인스턴스를 생성하는 것</strong></p>
<blockquote>
<p><strong>초기화의 역할은 모든 프로퍼티를 기본값으로 초기화 하는 것이다.</strong>
인스턴스 내 기본값이 존재하지 않는 프로퍼티가 있을 경우 초기화에 실패하고 인스턴스는 생성되지 않는다!</p>
</blockquote>
<h2 id="왜-초기화를-해야-되나">왜 초기화를 해야 되나?</h2>
<blockquote>
<p>스위프트는 에러에 대한 안전을 최우선시 한다.
빈 메모리에 접근하게 된다면 예기치 못한 에러가 발생할 수 있다.
타입 내부에 프로퍼티가 있다면 해당 프로퍼티에는 무조건 값이 있다는 것을 보장해야 한다.</p>
</blockquote>
<h2 id="구조체-초기화-방법">구조체 초기화 방법</h2>
<h3 id="1-선언과-동시에-프로퍼티에-기본값-넣어주기">1) 선언과 동시에 프로퍼티에 기본값 넣어주기</h3>
<pre><code class="language-swift">struct Human {
    let name : String = &quot;희재&quot;
    let age : Int = 23
}

let ryu = Human()
dump(ryu)

// - name : &quot;희재&quot;
// - age : 23</code></pre>
<h3 id="2-프로퍼티의-타입을-옵셔널-타입으로-설정하기">2) 프로퍼티의 타입을 옵셔널 타입으로 설정하기</h3>
<p>값이 있을지 없을지 모르는 경우 옵셔널 타입으로 선언, 그러면 초기화할 때 옵셔널 타입인 name, age는 자동으로 nil로 초기화
<strong>=&gt; 옵셔널 타입으로 선언하지 않으면 nil값을 받지 못함</strong>
<strong>var로 선언해야한다!</strong></p>
<pre><code class="language-swift">struct Human {
    var name :  String?
    var age : Int?
}

let ryu = Human()

let ryu2 = Human(nil, nil) 
dump(ryu2)
// - name : nil
// - age : nil</code></pre>
<h3 id="3-init-함수에서-값-설정해주기">3) init 함수에서 값 설정해주기</h3>
<p>초기화를 진행 하는 함수인 init함수 즉 생성자를 사용하여 생성자 안에서 해당 프로퍼티들을 초기화 시킬 수 있음.</p>
<ul>
<li><p>다양하게 선언할 수 있다.</p>
</li>
<li><p><strong>중요한건 init함수가 종료되기 전까진 모든 프로퍼티가 기본 값을 가져야한다!!!</strong></p>
<pre><code class="language-swift">struct Human {
  let name: String
  let age: Int

  // 다양하게 선언할 수 있다!
  init(name:String) {
      self.name = name
      self.age = 23
  }

  init(name:String, age: Int) {
      self.name = name
      self.age = age
  }
}
</code></pre>
</li>
</ul>
<p>//but.. init함수 종료 전까지 모든 프로퍼티가 기본값을 가져야함
let ryu = Human(age:23) // error :  Incorrect argument label in call    </p>
<pre><code>
## Memberwise Initializers
&gt;아래 코드처럼 구조체를 선언했다면 무조건 에러가 나야된다 왜?
**1,2,3번에 해당하는 어떠한 초기화도 안해줬기 때문**
but. 에러가 안난다.... why?
```swift
struct Human {
    let name : String
    let age : Int
}</code></pre><h3 id="memberwise-생성자">Memberwise 생성자</h3>
<p>구조체가 자동으로 제공하는 생성자로, 파라미터를 통해 모든 프로퍼티의 초기화를 가능하게 한다.
<strong>즉. 프로퍼티의 초기화를 따로 지정하지 않을경우, 초기화되지 않은 프로퍼티를 초기화할 수 있는init함수를 자동 제공해준다!!!!</strong></p>
<p><img src="https://velog.velcdn.com/images/hello_hidi/post/e4943824-92ae-467f-9b5d-d18217775a67/image.png" alt=""></p>
<pre><code class="language-swift">struct Human {
    let name : String
    let age : Int
}

let ryu = Human.init(&quot;희재&quot;,23)
</code></pre>
<h3 id="memberwise-생성자-성질">Memberwise 생성자 성질</h3>
<h3 id="1-memberwise-initializers로-제공되는-생성자의-파라미터는-프로퍼티가-선언된-순서와ㅗ-갯수에-맞추어-생성된다">1) memberwise initializers로 제공되는 생성자의 파라미터는, 프로퍼티가 선언된 순서와ㅗ 갯수에 맞추어 생성된다!</h3>
<pre><code class="language-swift">Human.init(name: &quot;희재&quot;, age : 23)
Human.init( age : 23, name: &quot;희재&quot;) // error
Human.init(name: &quot;희재&quot;) // error</code></pre>
<h3 id="2-프로퍼티가-let으로-선언되어-있고-이미-초기화가-되어있으면-생성자-목록에서-제외된다">2) 프로퍼티가 let으로 선언되어 있고, 이미 초기화가 되어있으면 생성자 목록에서 제외된다.</h3>
<p>why? 어차피 초기화해줘도 값이 수정이 안되기 때문!</p>
<pre><code class="language-swift">struct Human {
    let name : String = &quot;희재&quot;
    let age : Int
}

Human.init(age: 23)
Human.init(name: &quot;희재&quot;, age: 23) // error : Extra argument &#39;name&#39; in call
</code></pre>
<h3 id="3-프로퍼티가-var-선언되어-있고-이미-초기화가-된-상태면-해당-프로퍼티를-초기화-하는-생성자와-제외된-생성자-두개를-제공한다">3) 프로퍼티가 var 선언되어 있고, 이미 초기화가 된 상태면 해당 프로퍼티를 초기화 하는 생성자와 제외된 생성자 두개를 제공한다.</h3>
<p>why? 2번이랑은 다르게 var로 선언되면 값이 수정될 가능성이 생기게 된다!
따라서 var로 선언되어 초기화가 된 프로퍼티가 포함된 생성자와 아닌 생성자 두가지를 각각 제공해준다</p>
<pre><code class="language-swift">struct Human {
    var name : String = &quot;희재&quot;
    let age : Int
}

Human.init(age: 23) // name이 제외된 생성자
Human.init(name: &quot;서린&quot;, age: 23)  // name이 포함된 생성자
</code></pre>
<h3 id="4-생성자를-직접-생성한-경우-memberwise-initializers는-더이상-제공되지-않는다">4) 생성자를 직접 생성한 경우, memberwise initializers는 더이상 제공되지 않는다.</h3>
<p>즉. 구조체 안에 init 함수를 직접 구현하지 않는 경우에만 제공됨</p>
<pre><code class="language-swift">struct Human {
    var name : String = &quot;희재&quot;
    let age : Int

    init(name: String){
        self.name = name
        self.age = 23
    }
}

Human.init(age: 23)</code></pre>
<h3 id="5-둘다-사용하고-싶다면-extension">5) 둘다 사용하고 싶다면 extension</h3>
<p>응 그럼 구조체 안에만 없으면 되는건가? 정답
이니셜라이저의 복잡성을 낮추고 이니셜라이저가 의도치 않게 사용되는 것을 방지하기 위함</p>
<pre><code class="language-swift">struct Human {
    var name: String
    var age: Int
}

extension Human {
    init(name: String) {
        self.name = name
        self.age = 23
    }
}
Human.init(name: &quot;희재&quot;) // 구조체 init 함수를 활용한 초기화
Human.init(name: &quot;희재&quot;, age: 23) // memberwise initialize에서 제공한 생성자</code></pre>
<h3 id="6-프로퍼티-중-하나라도-private라면-memberwise-initializers는-제공되지-않는다">6) 프로퍼티 중 하나라도 private라면 memberwise initializers는 제공되지 않는다.</h3>
<pre><code class="language-swift">struct Human {
    private var name: String
    var age: Int
}

Human.init // No completions 아무것도 제공하지 않는다.</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 2주차(6) 클래스]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-2%EC%A3%BC%EC%B0%A86-%ED%81%B4%EB%9E%98%EC%8A%A4</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-2%EC%A3%BC%EC%B0%A86-%ED%81%B4%EB%9E%98%EC%8A%A4</guid>
            <pubDate>Mon, 28 Nov 2022 03:31:30 GMT</pubDate>
            <description><![CDATA[<h1 id="클래스">클래스</h1>
<p>** 인스턴스의 값(프로퍼티)을 저장하거나 기능(메소드)을 제공하고 이를 캡슐화할 수 있는 스위프트가 제공하는 타입(named type)**</p>
<h2 id="정의-선언">정의, 선언</h2>
<p>간단하게 class 키워드로 정의할 수 있다.</p>
<pre><code class="language-swift">class SomeStructure {
    // structure definition goes here
}</code></pre>
<h2 id="인스턴스">인스턴스</h2>
<p>클래스는 새로운 인스턴스를 위해 초기화 구문을 사용한다. 
초기화 구문의 가장 간단한 형태는 클래스 타입 이름 뒤에 빈 소괄호를 붙여 사용하는 것입니다. 
이렇게 하면 모든 프로퍼티가 기본값으로 초기화되는 구조체의 새로운 인스턴스를 생성합니다. </p>
<pre><code class="language-swift">let someResolution = Resolution()</code></pre>
<h2 id="프로퍼티-접근">프로퍼티 접근</h2>
<p>점 구문 (dot syntax) 을 사용하여 인스턴스의 프로퍼티에 접근할 수 있습니다. </p>
<pre><code class="language-swift">print(&quot;The width of someResolution is \(someResolution.width)&quot;)</code></pre>
<h2 id="참조-타입">참조 타입</h2>
<p>클레스가 대표적은 참조타임이라는 것은 이전 포스팅을 참고하면 좋을거 같다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 2주차(5) 구조체]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-2%EC%A3%BC%EC%B0%A85-%EA%B5%AC%EC%A1%B0%EC%B2%B4</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-2%EC%A3%BC%EC%B0%A85-%EA%B5%AC%EC%A1%B0%EC%B2%B4</guid>
            <pubDate>Mon, 28 Nov 2022 03:28:11 GMT</pubDate>
            <description><![CDATA[<h1 id="구조체">구조체</h1>
<p>** 인스턴스의 값(프로퍼티)을 저장하거나 기능(메소드)을 제공하고 이를 캡슐화할 수 있는 스위프트가 제공하는 타입(named type)**</p>
<h4 id="-named-type">+) named type?</h4>
<blockquote>
<p>Swift에서는 타입을 두가지로 나눌 수 있다. 바로 named Type과 compound Type인데
named Type: 클래스, 구조체, 열거형과 프로토콜 등 이름이 있는 타입
compound Type: 튜플과 함수 등과 같이 이름이 없는 타입으로, 다양한 데이터 묶음에 대해서 새롭게 정의하여 사용할 수 있는 타입</p>
</blockquote>
<h2 id="정의-선언">정의, 선언</h2>
<p>간단하게 struct 키워드로 정의할 수 있다.</p>
<pre><code class="language-swift">struct SomeStructure {
    // structure definition goes here
}</code></pre>
<h2 id="인스턴스">인스턴스</h2>
<p>구조체는 새로운 인스턴스를 위해 초기화 구문을 사용한다. 
초기화 구문의 가장 간단한 형태는 구조체 타입 이름 뒤에 빈 소괄호를 붙여 사용하는 것입니다. 
이렇게 하면 모든 프로퍼티가 기본값으로 초기화되는 구조체의 새로운 인스턴스를 생성합니다. </p>
<pre><code class="language-swift">let someResolution = Resolution()</code></pre>
<h2 id="프로퍼티-접근">프로퍼티 접근</h2>
<p>점 구문 (dot syntax) 을 사용하여 인스턴스의 프로퍼티에 접근할 수 있습니다. </p>
<pre><code class="language-swift">print(&quot;The width of someResolution is \(someResolution.width)&quot;)</code></pre>
<h2 id="값-타입">값 타입</h2>
<p>구조체가 대표적은 값타임이라는 것은 이전 포스팅을 참고하면 좋을거 같다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 2주차(4) strong, weak, unowned, 순환참조]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-2%EC%A3%BC%EC%B0%A84-strong-weak-unowned-%EC%88%9C%ED%99%98%EC%B0%B8%EC%A1%B0</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-2%EC%A3%BC%EC%B0%A84-strong-weak-unowned-%EC%88%9C%ED%99%98%EC%B0%B8%EC%A1%B0</guid>
            <pubDate>Tue, 22 Nov 2022 06:39:16 GMT</pubDate>
            <description><![CDATA[<p>ARC의 단점 중 하나는 순환 참조가 발생 시 영구적으로 메모리가 해제되지 않을 수 있다. 아니 근데 저기요 순환 참조가 뭐죠? 그걸 알아보러 가보자잉~</p>
<h2 id="강한참조">강한참조</h2>
<p><strong>우리가 지금까지 했던 힙의 할당하는 방식이 강한 참조 방식이다!</strong></p>
<blockquote>
<p>즉 인스턴스의 주소값이 변수에 할당될 때, RC가 증가하면 강한 참조!
애초에 default 값이 strong~
하지만 strong에 문제는 바로 순.환.참.조</p>
</blockquote>
<h2 id="순환참조">순환참조</h2>
<p>예시를 들어보자! 요즘 내가 킹받고 있는 꽃보다 남자로 예시를 들어보겠다. 먼저 준표랑 잔디를 등장시켜보겠다</p>
<pre><code class="language-swift">class Man {
    var name: String
    var girlfriend: Woman?

    init(name: String) {
        self.name = name
    }
    deinit { print(&quot;맨킬뎃쉿스껄!&quot;) }
}

class Woman {
    var name: String?
    var boyfriend: Man?

    init(name: String) {
        self.name = name
    }
    deinit { print(&quot;우맨킬뎃쉿스껄!&quot;) }
}


var junpyo: Man? = .init(name: &quot;준표&quot;)
var zandi: Woman? = .init(name: &quot;잔디&quot;)</code></pre>
<p>그리고 이 둘은 서로가 서로의 남친 여친임을 표시해준다.
메모리에서 볼 때 둘의 관계는 아래 그림과 같다.</p>
<pre><code class="language-swift">junpyo?.girlfriend = zandi
zandi?.boyfriend = junpyo</code></pre>
<p>그러면서 이 둘의 RC도 하나씩 증가했다.
<img src="https://velog.velcdn.com/images/hello_hidi/post/43dcd9d4-e5ef-4e42-8d0b-6b23c7dce098/image.jpeg" alt=""></p>
<h3 id="순환참조의-문제점">순환참조의 문제점</h3>
<p>자~ 이제 순환참조의 문제점에 대해 알아보자! 이 메모리의 주인이 나는 둘의 사이가 너무 킹받아서 죽여버리기로 결심을 했따. 물론 메모리 상에서만 ㅎㅎ</p>
<pre><code class="language-swift">junpyo = nil
zandi = nil</code></pre>
<p>이렇게 하면 나의 예상대로 메모리가 깔끔하게 사라져야 되는데 현실은 RC의 값이 둘다 1임으로 메모리 상에 살아서 아직도 나를 킹받게 하는 것이다...</p>
<p><img src="https://velog.velcdn.com/images/hello_hidi/post/22c55e0f-3000-415f-a77a-427e0026eedf/image.jpeg" alt=""></p>
<p><strong>즉 strong으로 선언된 변수들이 순환참조 됐을 시 큰 문제는</strong></p>
<blockquote>
<ul>
<li>서로가 서로를 참조하고 있어서 RC가 0이 되지 못한다는 것이다! </li>
</ul>
</blockquote>
<ul>
<li>또한 해당 인스턴스를 가리키던 변수도 nil로 지정했기 때문에 인스턴스 접근도 할 수 없어 메모리 해제도 못하는 최악의 상황이 펼쳐진다.</li>
</ul>
<p>이것들을 해결하기 위해서 우리는 weak과 unowned를 알아야 한다.</p>
<h2 id="weak">weak</h2>
<p><strong>weak 약한참조, 즉 인스턴스를 참조할 시, RC를 증가시키지 않는다.</strong></p>
<blockquote>
<ul>
<li>참조하던 인스턴스가 메모리에서 해제된 경우, 자동으로 nil이 할당되어 메모리가 해제된다!</li>
</ul>
</blockquote>
<ul>
<li>weak은 프로퍼티를 선언한 이후, 나중에 nildㅣ 할당된다는 관점에서 </li>
<li><em>무조건 옵셔널 타입의 변수*</em></li>
<li>둘 중에 수명이 더 짧은 인스턴스를 가리키는 애를 약한 참조로 선언함.</li>
</ul>
<pre><code class="language-swift">class Man {
    var name: String
    weak var girlfriend: Woman?

    init(name: String) {
        self.name = name
    }
    deinit { print(&quot;맨킬뎃쉿스껄!&quot;) }
}

class Woman {
    var name: String?
    var boyfriend: Man?

    init(name: String) {
        self.name = name
    }
    deinit { print(&quot;우맨킬뎃쉿스껄!&quot;) }
}


var junpyo: Man? = .init(name: &quot;준표&quot;)
var zandi: Woman? = .init(name: &quot;잔디&quot;)

junpyo?.girlfriend = zandi
zandi?.boyfriend = junpyo</code></pre>
<p><img src="https://velog.velcdn.com/images/hello_hidi/post/6824b330-04fa-486f-b9d9-3d49acc852dc/image.jpeg" alt=""></p>
<blockquote>
<p>여기서 준표랑 잔디를 죽이면</p>
</blockquote>
<p>1) zandi, junpyo가 스택에서 가리키는 인스턴스 RC 둘다 1
2) 잔디의 RC가 0이 되면서 kill
3) 준표의 여자친구 속성이 0이 되면서 RC 0되면서 킬
4) 메모리 깨-끗&gt;</p>
<h2 id="unowned">unowned</h2>
<p>weak과 비슷하게 RC값을 증가시키지 않아서 강한 순환 참조를 해결하지만,
<strong>인스턴스를 참조하는 도중에 해당 인스턴스가 메모리에서 사라질 일이 없다고 확신하는게 핵심임!</strong></p>
<blockquote>
<ul>
<li>참조하던 인스턴스가 만약 메모리에서 해제된 경우에도 <strong>nil을 할당받지 못하고, 해제된 메모리 주소값을 계속 들고 있음</strong></li>
</ul>
</blockquote>
<ul>
<li>둘 중에 수명이 더 긴 인스턴스를 가리키는 애를 unowned 선언해야됨!</li>
</ul>
<pre><code class="language-swift">//week으로 선언될 경우
junpyo?.girlfriend / 결과값 : nil
//unowned으로 선언될 경우
junpyo?.girlfriend / 결과값 : error: Execution was interrupted 
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 2주차(3) ARC]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-2%EC%A3%BC%EC%B0%A83-ARC</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-2%EC%A3%BC%EC%B0%A83-ARC</guid>
            <pubDate>Tue, 22 Nov 2022 05:44:48 GMT</pubDate>
            <description><![CDATA[<p>드디어 ARC이다!!!! </p>
<h3 id="참조타입과-heap">참조타입과 Heap</h3>
<p>ARC를 제대로 배울라면 저번주차에서 다뤘던 참조타입과 메모리 구조에서 배운 Heap에 대한 이해가 있어야 된다!
간략하 설명하자면 </p>
<blockquote>
<ul>
<li>Swift의 클래스와 클로저는 Heap영역에 저장되는 참조타입이다. </li>
</ul>
</blockquote>
<ul>
<li>참조타입의 특징은 지역변수는 단지 스택에 저장되어 인스턴스의 주소값을 가지고 있고</li>
<li>스택의 지역변수가 힙 영역의 실제 인스턴스를 참조하는 형태이다.
<img src="https://velog.velcdn.com/images/hello_hidi/post/1a733fa6-d646-45d5-a46f-f4b6f6447269/image.png" alt="https://velog.velcdn.com/images/hello_hidi/post/1a733fa6-d646-45d5-a46f-f4b6f6447269/image.png"></li>
</ul>
<h3 id="메모리-해제">메모리 해제</h3>
<p>우리는 지금까지 걍 마음대로 클래스 만들어서 인스턴스 퐉퐈고파ㅗ가퐈 찍어내고 마음껏 사용했음. but Heap에 특징! 사용하고 난 후 반드시 메모리 해제를 해줘야 한다! 근데 한 사람????
<img src="https://velog.velcdn.com/images/hello_hidi/post/8a019bce-2ad1-45d1-b2cb-db0a0f6f4d50/image.png" alt=""></p>
<p>아무도 없을것이다! 왜냐? 바로 ARC가 해주기 때문이다!</p>
<h2 id="arc">ARC</h2>
<p><strong>Automatic Reference Counting의 약자로, 클래스 인스턴스가 더 이상 필요하지 않을 경우 메모리를 자동으로 해제해주는 것이 주기능이다!</strong></p>
<h3 id="arc-작동원리">ARC 작동원리</h3>
<blockquote>
<ol>
<li>ARC는 인스턴스에 대한 정보를 저장하기 위해 메모리의 청크에 할당합니다. <ul>
<li>메모리 청크: malloc()으로 할당 받는 영역과 header를 포함한 영역
<img src="https://velog.velcdn.com/images/hello_hidi/post/5f455f0a-1460-48a5-8847-e3896774bc39/image.png" alt=""></li>
</ul>
</li>
</ol>
</blockquote>
<blockquote>
<ol start="2">
<li>컴파일 시점에 언제 참조되고 해제되는지 결정되어  retain, release를 삽입을 한다!<ol start="3">
<li>런타임 때 결정되어 그대로 실행한다
<img src="https://velog.velcdn.com/images/hello_hidi/post/25b17636-ee4d-4b97-b683-ee78987709fa/image.png" alt=""></li>
</ol>
</li>
</ol>
</blockquote>
<h2 id="arc에서-rc-다루기">ARC에서 RC 다루기</h2>
<h3 id="i-rc값이-증가하는-경우">i) RC값이 증가하는 경우</h3>
<blockquote>
<ul>
<li>인스턴스를 새로 생성할 때</li>
</ul>
</blockquote>
<ul>
<li>기존 인스턴스를 다른 변수에 대입할 때</li>
</ul>
<h3 id="ii-rc값이-감소하는-경우">ii) RC값이 감소하는 경우</h3>
<blockquote>
<ul>
<li>인스턴스를 가리키던 변수가 메모리에서 해제되었을 때</li>
</ul>
</blockquote>
<ul>
<li>nil이 지정되었을 때</li>
<li>변수에 다른 값을 대입한 경우</li>
<li>프로퍼티의 경우, 속해있는 클래스 인스턴스가 메모리에서 해제될 때</li>
</ul>
<h3 id="예시-코드">예시 코드</h3>
<pre><code class="language-swift">class Ayomi {
    var name: String?
    var age: Int?

    init(name: String? = nil, age: Int? = nil) {
        self.name = name
        self.age = age
    }

    deinit {print(&quot;당신의 아요미 인생은 여기까지~&quot;)}
}


var hidi: Ayomi? = .init(name: &quot;hidi&quot;, age: 23) // hidi Instance RC: 1
var hidiclone = hidi // hidi Instance RC: 2, hidiclone Instance RC: 2

hidiclone = nil // hidi Instance RC: 1
hidi = nil // hidi Instance RC: 0

var min: Ayomi? = .init(name: &quot;min&quot;, age: 76) // min Instanc RC: 1
var minClone: Ayomi? = .init(name: &quot;minClone&quot;, age: 5) // minClone Instance RC: 1

min = minClone // min Instance RC: 0, minClone Instance RC: 2


class Ayo {
    var level: Int?
    var ayomi: Ayomi? = .init(name: &quot;ayomi&quot;, age: 20)

    init(level: Int? = nil) {
        self.level = level
    }
}

var ayo: Ayo? = .init(level: 31)
ayo = nil
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 2주차(2) MRC]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-2%EC%A3%BC%EC%B0%A82-MRC</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-2%EC%A3%BC%EC%B0%A82-MRC</guid>
            <pubDate>Tue, 22 Nov 2022 04:40:30 GMT</pubDate>
            <description><![CDATA[<p>자 저번에 메모리 기초를 봤는데 일단 ARC를 보기 전에 옵제씨 사용 틀딱 시절엔 힙 영역에 어케 할당하고 해제했는지를 먼저 보려고 한다. 그 이유는 ARC를 왜? 써야 되는지를 알려면 불편함을 느껴야 되기 때문! 그럼 MRC에 대해 알아보장~</p>
<h2 id="mrc">MRC</h2>
<p><strong>Manual Retain Counter의 준말로 수동으로 RC를 계산하는 기법이다!</strong></p>
<h3 id="i-rc란">i) RC란?</h3>
<p><strong>RC는 Retain Counter(MRC에서) 에 준말이며, 참조횟수이다!</strong></p>
<blockquote>
<p>Swift에는 값타입과 참조타입이 있으면 참조타입이 이해가 안된다면, 저번에 작성한 블로그를 참고하면 될 거 같다잉~</p>
</blockquote>
<h3 id="ii-retiancount">ii) retianCount</h3>
<p>MRC에 경우 개발자가 직접 count를 해서인지 인스턴스에 대한 RC에 접근할 수 있다! <strong>.retainCount는 인스턴스의 RC에 접근할 수 있는 프로퍼티이다!</strong></p>
<h2 id="mrr로-rc-다루기">MRR로 RC 다루기</h2>
<h3 id="1-인스턴스를-새로-생성할-때">1) 인스턴스를 새로 생성할 때</h3>
<p>Objective-C에서 인스턴스를 새로 생성하는 방법에 아래와 같은 메서드들이 있다.</p>
<blockquote>
<ul>
<li>alloc</li>
</ul>
</blockquote>
<ul>
<li>new</li>
<li>copy</li>
<li>mutableCopy<pre><code class="language-swift">//아래와 같은 방식으로 인스턴스를 새로 생성할 수 있다.
TestClass *test = [[TestClass alloc] init];</code></pre>
</li>
</ul>
<p>여기서 인스턴스를 새로 생성하면 자동으로 RC가 +1이 된다. 어 그럼 자동으로 되는거자나? 왜 구라깜? 이제 수동적으로 증가시키는 걸 보여줄게용</p>
<h3 id="2-retain-메소드를-사용할-때">2) retain 메소드를 사용할 때</h3>
<p><strong>retain 메서드를 사용해서 우린 RC를 수동적으로 증가시킬 수 있다</strong></p>
<blockquote>
<p>Q. 그럼 언제 쓰냐?
A. 절대로 남발해서는 안된다. 사실 RC값이 늘어나는 경우는 정해져있다. 새로 인스턴스를 생성했을때랑 기존 인스턴스를 참조했을 때. 그러나 새로 인스턴스를 생성할 땐 자동으로 생성해주니까
<strong>=&gt; 기존의 인스턴스를 참조할 때 retain 메소드를 사용해 RC값을 사용한다</strong></p>
</blockquote>
<pre><code class="language-swift">TestClass *test = [[TestClass alloc] init];
TestClass *test2 = test; // 기존 인스턴스 참조
[test retain]; // test RC +1</code></pre>
<h3 id="3-release-메소드를-사용할-때">3) release 메소드를 사용할 때</h3>
<p><strong>release 메서드를 사용해서 우린 RC를 수동적으로 감소시킬 수 있다</strong></p>
<blockquote>
<pre><code class="language-swift">[test release];
test2 = nil;</code></pre>
</blockquote>
<pre><code>
### 결론
그냥 할당할때마다 옵제씨 시절에는 할당,해제를 주구장창~~~~~~~ 수동으로 해줘야했다. 벌써 불편하자나 그래서 우린 드디어 ARC를 배우러 간다.

MRC결론 : 후 너네는 이런거 하지마라~
![](https://velog.velcdn.com/images/hello_hidi/post/1cf38828-8915-4352-a12f-07b964fff5bf/image.png)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 2주차(1) 메모리 기초]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-2%EC%A3%BC%EC%B0%A81-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-2%EC%A3%BC%EC%B0%A81-%EB%A9%94%EB%AA%A8%EB%A6%AC-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Tue, 22 Nov 2022 04:06:36 GMT</pubDate>
            <description><![CDATA[<p>오늘 배울 주제인 ARC를 다뤄보기 전 메모리구조를 한번 알아보고 가보자이</p>
<h2 id="메모리-구조">메모리 구조</h2>
<p>운영체제에서는 메모리에 프로그램을 위한 공간을 할당해줍니다!
그 공간을 총 4가지로 나눌 수 있는데욥</p>
<p><img src="https://velog.velcdn.com/images/hello_hidi/post/c16bd056-4b5b-42d0-a307-5ab27d0840f2/image.png" alt=""></p>
<h3 id="i-code-data-영역">i) code, data 영역</h3>
<blockquote>
<p><strong>code영역</strong>: 실행할 프로그램의 코드가 저장되는 영역으로 텍스트 영역이라고도 부릅니다. CPU는 코드 영역에 저장된 명령어를 하나씩 가져가서 처리하게 됩니다.
-&gt; 간단히 우리가 작성한 소스 코드가 기계어 형태로 저장됨!</p>
</blockquote>
<blockquote>
<p><strong>data영역</strong>: 프로그램의 전역 변수와 정적(static) 변수가 저장되는 영역입니다.
데이터 영역은 프로그램의 시작과 함께 할당되며, 프로그램이 종료되면 소멸합니다.</p>
</blockquote>
<h3 id="ii-heap-영역">ii) heap 영역</h3>
<blockquote>
<p><strong>사용자에 의해 메모리 공간이 동적으로 할당되고 해제되는 영역</strong></p>
</blockquote>
<ul>
<li>사용하고 난 후에는 반드시 메모리 해제를 해줘야 한다. 그렇지 않으면 memory leak이 발생한다.</li>
<li>유일하게 런타임 시에 결정되기 때문에 데이터의 크기가 확실하지 않을 때 사용<ul>
<li>메모리의 낮은 주소에서 높은 주소의 방향으로 할당됩니다.</li>
<li>Swift에서는 closure, class 등 참조타입의 값이 힙에 자동 할당됨!</li>
</ul>
</li>
</ul>
<h3 id="iii-stack-영역">iii) stack 영역</h3>
<blockquote>
<p><strong>함수의 호출과 관계되는 지역 변수와 매개변수가 저장되는 영역</strong></p>
</blockquote>
<ul>
<li>함수의 호출과 함께 할당되며, 함수의 호출이 완료되면 소멸합니다.</li>
<li>컴파일 타임에 결정되기 때문에 무한히 할당할 수 없다.</li>
<li>프로그램이 자동으로 사용하는 임시 메모리 영역이다.</li>
</ul>
<h2 id="heap-vs-stack">Heap vs Stack</h2>
<h3 id="각각의-장단점">각각의 장단점</h3>
<table>
<thead>
<tr>
<th></th>
<th>stack</th>
<th>heap</th>
</tr>
</thead>
<tbody><tr>
<td>장점</td>
<td>CPU가 스택 메모리를 효율적으로 구성하기 때문에<br>속도가 굉장히 빠르다</td>
<td>메모리 크기에 대한 제한이 없다</td>
</tr>
<tr>
<td>단점</td>
<td>메모리 크기에 대한 제한이 있음</td>
<td>할당, 해제 작업으로 인한 속도 저하</td>
</tr>
</tbody></table>
<h3 id="q-언제-힙을-쓰고-언제-스택을-쓰나용">Q. 언제 힙을 쓰고, 언제 스택을 쓰나용?</h3>
<p><strong>데이터의 크기를 모르거나, 스택에 저장하기에 너무 큰 데이터인 경우 힙에 할당</strong></p>
<blockquote>
<p>물론 위에 경우는 클로저와 인스턴스처럼 자동으로 힙에 할당하는 것 외에 직접 할당 경우이당~
만약에 너무 많은 메모리를 스택에 할당하면 우리에게 다른 의미로 익숙한
<img src="https://velog.velcdn.com/images/hello_hidi/post/7377365e-0933-415d-b376-c4b82cc6355d/image.png" alt="">
스택 오버 플로우: 너무 많은 메모리 할당으로 스택 영역을 초과한 경우
힙 오버 플로우: 힙도 자신의 영역 외로 확장하면 오버 플로우 발생한다~</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 1주차(7) Hash Value]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-1%EC%A3%BC%EC%B0%A87-Hash-Value</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-1%EC%A3%BC%EC%B0%A87-Hash-Value</guid>
            <pubDate>Tue, 15 Nov 2022 02:30:36 GMT</pubDate>
            <description><![CDATA[<h1 id="hash-value">Hash Value</h1>
<h2 id="hash와-hash-table">Hash와 Hash Table</h2>
<blockquote>
<p>해쉬값을 이해하기 위해선 Hash와 Hash Table에 대한 이해가 먼저 필요하다</p>
</blockquote>
<h3 id="hash-table">Hash Table</h3>
<blockquote>
<p><strong>Key라는 것을 해시 함수를 이용해 해시 주소값(해시 테이블의 index)으로 바꾸고,해시 주소값(해시 테이블의 index)를 통해 해시 테이블에 접근하여 값을 가져오거나 저장하는 형태임</strong></p>
</blockquote>
<p>이게 뭔 소리야?</p>
<ul>
<li>만약 아래 그림에서 희재 - 0, 석우 - 1, 서린 - 2 이런식으로 저장되면 이건 그냥 일반 배열과 다름이 없겠지?
<img src="https://velog.velcdn.com/images/hello_hidi/post/34272ef5-724b-405f-870d-6026e77a307e/image.jpg" alt=""></li>
<li>Key를 통해 해시 테이블의 index를 알 수 있어야만, 해당 Value에 접근이 가능하다</li>
<li>해당 Key에 상응하는 index는 항상 동일하게 나와야함</li>
<li>해시함수는 Key에 대한 산술 연산을 이용하여 해시 주소값(해시 테이블의 index)으로 만들어주는 것!</li>
</ul>
<h3 id="why-hash">why hash?</h3>
<blockquote>
<p>해시는 값의 검색 속도가 빠르다. 원래는 처음부터 순서대로 값을 찾아야 한다. 반면, 해쉬 테이블에서는 해쉬값을 index로 사용하여 원하는 값의 위치를 한 번에 알 수 있다.</p>
</blockquote>
<blockquote>
<p>하지만 충돌 문제를 해결하기 위해 저장공간을 넓게 잡아서 공간 복잡도는 커진다..</p>
</blockquote>
<table>
<thead>
<tr>
<th>장점</th>
<th>단점</th>
</tr>
</thead>
<tbody><tr>
<td>1. 데이터 저장, 읽기 속도가 빠르다</td>
<td>1. 일반적으로 저장공간이 많이 필요하다</td>
</tr>
<tr>
<td>2. 키에 대한 데이터 중복 확인이 쉽다</td>
<td>2. 충돌이 발생 시 해결하기 위한 별도의 자료구조가 필요하다</td>
</tr>
</tbody></table>
<p><strong>그래서 해시는 저장, 검색, 삭제 등 탐색을 많이 하는 경우나 캐쉬를 구현하는 경우 많이 사용된다.</strong></p>
<h2 id="hash-value해쉬값-">Hash Value(해쉬값) ?</h2>
<p><strong>원본 데이터를 특정 규칙에 따라 처리하여 간단한 숫자로 만드는 것</strong></p>
<blockquote>
<ul>
<li>정확히 원본 데이터 (객체)를 해쉬 함수를 사용하여 64bit의 Int 값으로 변환한것</li>
</ul>
</blockquote>
<ul>
<li>2개의 데이터를 비교할 때, 데이터가 동일하면 각 데이터의 해쉬값도 동일</li>
<li>하지만 데이터가 조금이라도 다르면, 완전히 다른 해쉬값</li>
<li>코드를 컴파일 및 실행할 때마다 모든 해쉬값이 변경됨!</li>
</ul>
<pre><code class="language-swift">let hi: String = &quot;히디 안녕?&quot;
let hello: String = &quot;히디 안녕?&quot;
let hihello: String = &quot;잘생긴 히디 안녕?&quot;

print(hi.hashValue) // 2897129375192192 (예시)
print(hello.hashValue) // 2897129375192192 (예시)
print(hihello.hashValue) // 1239591329282384</code></pre>
<h2 id="hashable">Hashable?</h2>
<p>이게 뭔 소리져...?</p>
<blockquote>
<p>Set에 어떤 값을 저장하고 싶다면, &quot;해당 값의 타입은 Hashable 해야한다&quot;</p>
</blockquote>
<p><strong>- Hashable 해야 한다는 것은 Hashable Protocol을 준수한다는 의미이다!</strong>
<strong>- Hashable 한 타입의 데이터는 해쉬값을 구할 수 있다!</strong>
<strong>- Hashable은 Equatable의 상속을 받으므로 연산자 &#39;==&#39; 사용 가능</strong></p>
<pre><code class="language-swift">struct Sopt: Hashable {
    let name: String
    let part: String
    let appJam: Bool
}

struct Soap: Hashable {
    let string1: String
    let string2: String
    let random: Bool
}

let hidi = Sopt(name: &quot;hidi&quot;, part: &quot;iOS&quot;, appJam: true)
let partJang = Sopt(name: &quot;hansol&quot;, part: &quot;iOS&quot;, appJam: true)

// 구조체가 Hashable Protocol을 준수하므로 == 연산자로 비교 가능
if hidi == partJang {
    print(&quot;영광입니다~!&quot;)
} else {
    print(&quot;아직 부족합니다 ㅠ&quot;)
}

let soap = Soap(string1: &quot;hidi&quot;, string2: &quot;iOS&quot;, random: true)

// 다른 객체이지만, 동일한 해쉬값을 가진다! (해쉬값 충돌)
print(hidi.hashValue) 
print(soap.hashValue)

if hidi == soap // 컴파일 에러: 객체의 타입이 다르므로 연산자 사용 불가</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[야우쓰] 1주차(6) 클로저 심화]]></title>
            <link>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-1%EC%A3%BC%EC%B0%A84-%ED%81%B4%EB%A1%9C%EC%A0%80-%EC%8B%AC%ED%99%94-ifdyq2i0</link>
            <guid>https://velog.io/@hello_hidi/%EC%95%BC%EC%9A%B0%EC%93%B0-1%EC%A3%BC%EC%B0%A84-%ED%81%B4%EB%A1%9C%EC%A0%80-%EC%8B%AC%ED%99%94-ifdyq2i0</guid>
            <pubDate>Mon, 14 Nov 2022 13:21:25 GMT</pubDate>
            <description><![CDATA[<h1 id="클로저-심화">클로저 심화</h1>
<h2 id="autoclosure">@autoclosure</h2>
<blockquote>
<p>** 파라미터로 전달된 일반 구문 &amp; 함수를 클로저로 래핑하는 것**</p>
</blockquote>
<p><strong>즉 실제 클로저를 전달받지 않지만, 클로저처럼 사용이 가능해진다~!
다만 실제 클로저를 전달하는 것이 아니기 때문에 파라미터로 값을 넘기는 것처럼 
()를 통해 구문을 넘겨줄 수가 있음!</strong></p>
<pre><code class="language-swift">func doSomething(closure: @autoclosure() -&gt; () {
}</code></pre>
<h2 id="escaping">@escaping</h2>
<h3 id="non-escaping-closure">non-escaping Closure</h3>
<blockquote>
<p><strong>지금까지 우리가 봤던 건 모두 non-escaping closure였다</strong>
함수 내부에서 직접 실행하기 위해서만 사용한다.
따라서 i) 파라미터로 받은 클로저를 변수나 상수에 대입할 수 없고,
ii) 중첩 함수에서 클로저를 사용할 경우, 중첩함수를 리턴할 수 없다.</p>
</blockquote>
<p><strong>함수의 실행 흐름을 탈출하지 않아, 함수가 종료되기 전에 무조건 실행되어야 한다.</strong></p>
<pre><code class="language-swift">// i)
func doSomething(closure: () -&gt; ()) {
    let f: () -&gt; () = closure // error
}
// ii)
func outer(closure: () -&gt; ()) -&gt; () -&gt; () {
    func inner() {
        closer()
    }
    return inner // error
}</code></pre>
<h3 id="escaping-1">@escaping</h3>
<p>즉 우리는 지금까지 클로저가 탈출하려면 바깥에 정의된 변수에 저장하는 방법 뿐이었다.
<strong>So, 함수 실행을 벗어나서 함수가 끝난 후에도 클로저를 실행하거나,
중첩함수에서 실행 후 중첩 함수를 리턴하고 싶거나, 변수 상수에 대입하고 싶은 경우!!! 사용!!!</strong></p>
<pre><code class="language-swift">func doSomething(closure: @escaping () -&gt; ()) {
}

// 변수나 상수에 파라미터로 받은 클로저를 대입할 수 있다.
func doSomething(closure: @escaping () -&gt; ()) {
    let f: () -&gt; () = closure
}</code></pre>
<p><strong>BUT. escaping 클로저를 사용할 경우 주의해야할 점이 있는데 바로 메모리 관련!</strong></p>
<blockquote>
<p>만약 함수가 종료된 후 클로저를 실행하는데, 이때 클로저가 함수 내부 값을 사용하면 함수는 이미 종료 되었는데, 클로저는 함수 내부 값을 어떻게 사용할까? (뒤에서 봅시다)</p>
</blockquote>
<h2 id="reference-capture">Reference Capture</h2>
<p><strong>클로저는 값을 캡쳐할 때 Value/Reference 타입에 관계 없이 Reference Capture을 한다.</strong></p>
<p>아래 코드에서 num은 Int 타입의 구조체 형식이고, 이는 곧 Value 타입이기 때문에,
값을 복사해서 들고 저장해야 되는 것이 일반적임</p>
<blockquote>
<p>But 클로저는 Value/ Reference 타입에 관계없이 캡쳐하는 값들을 참조함!
이것을 <strong>Reference Capture</strong>라고 한다.</p>
</blockquote>
<pre><code class="language-swift">func doSomething() {
    var message = &quot;Hi i am hidi!&quot;

    // 클로저 범위 시작
    var num  = 10
    let closure = { print(num)}

    // 클로저 범위 끝

    print(message)
}</code></pre>
<p>어떻게 되는거냐.. 한번 살펴보자!</p>
<pre><code class="language-swift">func doSomething() {
    var num: Int = 0
    print(&quot;num check #1 = \(num)&quot;)

    let closure = {
        print(&quot;num check #3 = \(num)&quot;)
    }

    num = 20
    print(&quot;num check #2 = \(num)&quot;)
    closure()

    /*
    실행결과
    num check #1 = 0
    num check #2 = 20
    num check #3 = 20

    */</code></pre>
<ul>
<li>먼저 closure은 외부 변수를 클로저 내부에서 사용하기 때문에 num 캡쳐
이때 Referecne Capture로 num이란 변수를 참조</li>
<li>따라서 closure을 실행하기 전 num이란 값을 외부에서 변경하면 클로저 내부에서 사용하는 num 또한 바뀐다!</li>
</ul>
<h2 id="클로저의-캡쳐-리스트">클로저의 캡쳐 리스트</h2>
<p>근데 난... Value Type으로 Capture를 하고 싶은걸.....ㅠㅠ
<strong>이때 사용하는게 바로 캡쳐 리스트이다!</strong></p>
<blockquote>
<p>Value Type의 경우, Value Capture 하고 싶은 변수를 리스트로 명시!!!</p>
</blockquote>
<ul>
<li>클로저의 시작인 { 의 바로 옆에 []을 이용해 캡쳐할 멤버를 나열한다.</li>
<li>이때 in 키워드도 꼭 함께 작성한다.
ex) let closure = { [num, num2] in ...}</li>
</ul>
<pre><code class="language-swift">func doSomething() {
    var num: Int = 0
    print(&quot;num check #1 = \(num)&quot;)

    let closure = { [num] in
        print(&quot;num check #3 = \(num)&quot;)
    }

    num = 20
    print(&quot;num check #2 = \(num)&quot;)
    closure()

    /*
    실행결과
    num check #1 = 0
    num check #2 = 20
    num check #3 = 0

    */</code></pre>
<p>이때 주의해야할 점은!
Closure을 선언할 당시의 num의 값을 <strong>Const Value Type</strong> 즉 상수로 캡쳐
<strong>따라서 closure 내부에서 Value Capture 된 값을 변경할 수 없음!</strong> </p>
<pre><code class="language-swift">let closure = { [num] in
    num = 20 // error: Cannot assign to value (immutable capture)
    print(&quot;num check #3 = \(num)&quot;)
}</code></pre>
<h3 id="reference-type의-값을-캡쳐-리스트로-하면">Reference Type의 값을 캡쳐 리스트로 하면?</h3>
<blockquote>
<p>Q. Reference 타입의 값도 Capture Lists에 작성하면, Value Capture가 될까?
A. 응 안돼~ 캡쳐 리스트를 작성한다고 해도,Reference Type은 Referce Capture을 한다.</p>
</blockquote>
<blockquote>
<p>Q. 그러면 Reference 타입은 Closer Capture List 필요 없겠네 ㅋㅋㅋ
A. 그건 또 아닌데.... (그럼 뭔데, 근데 이건 내가 아직 ARC를 몰라서 난중에 보자고!)</p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>