<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>..</title>
    <link>https://gorani95.tistory.com/</link>
    <description>~~</description>
    <language>ko</language>
    <pubDate>Sun, 5 Jul 2026 20:40:05 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>할루루</managingEditor>
    <item>
      <title>정리하는 곳 이동</title>
      <link>https://gorani95.tistory.com/notice/262</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-size: 18pt;&quot;&gt;&lt;a href=&quot;https://github.com/presto95/Study&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;https://github.com/presto95/Study&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <author>할루루</author>
      <guid isPermaLink="true">https://gorani95.tistory.com/notice/262</guid>
      <pubDate>Sat, 20 Oct 2018 15:21:56 +0900</pubDate>
    </item>
    <item>
      <title>정리하는 곳 이동</title>
      <link>https://gorani95.tistory.com/261</link>
      <description>&lt;p&gt;&lt;span style=&quot;font-size: 14pt;&quot;&gt;&lt;a href=&quot;https://github.com/presto95/Study&quot; target=&quot;_blank&quot; class=&quot;tx-link&quot;&gt;https://github.com/presto95/Study&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <author>할루루</author>
      <guid isPermaLink="true">https://gorani95.tistory.com/261</guid>
      <comments>https://gorani95.tistory.com/261#entry261comment</comments>
      <pubDate>Sat, 20 Oct 2018 15:21:22 +0900</pubDate>
    </item>
    <item>
      <title>2회독 정리</title>
      <link>https://gorani95.tistory.com/260</link>
      <description>&lt;article class=&quot;markdown-body&quot;&gt;
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset='UTF-8'&gt;&lt;meta name='viewport' content='width=device-width initial-scale=1'&gt;
&lt;title&gt;2회독&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;&lt;h2&gt;연산자&lt;/h2&gt;
&lt;h3&gt;사용자 정의 연산자&lt;/h3&gt;
&lt;p&gt;토큰으로 사용되는 &lt;code&gt;=, -&amp;gt;, //, /*, */&lt;/code&gt; 등과 전위 연산자 &lt;code&gt;&amp;lt;, &amp;amp;, ?&lt;/code&gt;, 중위 연산자 &lt;code&gt;?&lt;/code&gt;, 후위 연산자 &lt;code&gt;&amp;gt;, !, ?&lt;/code&gt; 등은 Swift에서 예약한 상태이므로 재정의할 수 없으며 사용자 정의 연산자로 사용될 수 앖다.&lt;/p&gt;
&lt;h3&gt;전위 연산자 정의와 구현&lt;/h3&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;prefix operator **
prefix func **(value: Int) -&amp;gt; Int {
    return value * value
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;후위 연산자 정의와 구현&lt;/h3&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;postfix operator **
postfix func **(value: Int) -&amp;gt; Int {
    return value * value
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;중위 연산자 정의와 구현&lt;/h3&gt;
&lt;p&gt;중위 연산자는 우선순위 그룹&lt;em&gt;precedenceGroup&lt;/em&gt;을 명시해줄 수 있음&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;precedenceGroup 우선순위_그룹_이름 {
    higherThan: 더_낮은_우선순위_그룹_이름
    lowerThan: 더_높은_우선순위_그룹_이름
    associativity: 결합방향(left / right / none)
    assignment: 할당방향_사용(true / false)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Swift에 정의된 우선순위 그룹이 있음.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;infix operator **: MultiplicationPrecedence
func **(lhs: String, rhs: String) -&amp;gt; Bool {
    return lhs.contains(rhs)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;함수&lt;/h2&gt;
&lt;h3&gt;종료되지 않는 함수&lt;/h3&gt;
&lt;p&gt;비반환 함수(메소드)는 반환 타입을 &lt;code&gt;Never&lt;/code&gt;로 명시해준다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;func crash() -&amp;gt; Never {
    fatalError(&amp;quot;CRASH!&amp;quot;)
}
crash()	// 프로세스 종료 후 오류 보고
&lt;/code&gt;&lt;/pre&gt;
&lt;hr /&gt;
&lt;h2&gt;옵셔널&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;옵셔널은 열거형으로 구현되어 있음!&lt;/strong&gt; 그러므로 &lt;code&gt;switch&lt;/code&gt;문으로 &lt;code&gt;some&lt;/code&gt;과 &lt;code&gt;none&lt;/code&gt;인 케이스에 접근할 수 있으나 일반적을 옵셔널 바인딩 등의 방법을 활용한다.&lt;/li&gt;
&lt;li&gt;함수의 매개 변수 타입이 옵셔널이면, 매개 변수 기본값이 &lt;code&gt;nil&lt;/code&gt;이 아니어도 함수 호출 시 그 부분에 아무런 값을 주지 않아도 &lt;code&gt;nil&lt;/code&gt;이 들어올 것임을 알아야 한다.&lt;/li&gt;

&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;구조체와 클래스&lt;/h2&gt;
&lt;h3&gt;구조체를 사용해야 하나? 클래스를 사용해야 하나?&lt;/h3&gt;
&lt;p&gt;다음의 조건 중 하나 이상에 해당된다면 구조체를 사용하는 것을 권장한다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;연관된 간단한 값의 집합을 캡슐화하는 것만이 목적일 때&lt;/li&gt;
&lt;li&gt;캡슐화한 값을 참조하는 것보다 복사하는 것이 합당할 때&lt;/li&gt;
&lt;li&gt;구조체에 저장된 프로퍼티가 값 타입이며 참조하는 것보다 복사하는 것이 합당할 때&lt;/li&gt;
&lt;li&gt;다른 타입으로부터 상속받거나 자신을 상속할 필요가 없을 때&lt;/li&gt;

&lt;/ul&gt;
&lt;hr /&gt;
&lt;h2&gt;프로퍼티와 메소드&lt;/h2&gt;
&lt;h3&gt;지연 저장 프로퍼티&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;지연 저장 프로퍼티&lt;em&gt;lazy stored property&lt;/em&gt;는 호출이 있어야 값을 초기화하며, 주로 복잡한 클래스나 구조체를 구현할 때 많이 사용된다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;다중 스레드 환경에서 지연 저장 프로퍼티에 동시다발적으로 접근할 때 한 번만 초기화된다는 보장이 없다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h3&gt;키 경로&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;키 경로&lt;em&gt;keyPath&lt;/em&gt;를 활용하여 어떤 프로퍼티의 위치만 참조할 수 있도록 할 수 있다. 키 경로를 사용하여 간접적으로 특정 타입의 어떤 프로퍼티 값을 가리켜야 할지 미리 지정해두고 사용할 수 있다.&lt;/li&gt;

&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;각 인스턴스의 &lt;code&gt;KeyPath&lt;/code&gt; 서브스크립트 메소드에 키 경로를 전달하여 프로퍼티에 접근할 수 있다.&lt;/li&gt;
&lt;li&gt;키 경로를 잘 활용하면 타입 간의 의존성을 낮추는 데 많은 도움을 준다.&lt;/li&gt;
&lt;li&gt;키 경로는 타입 외부로 공개된 &lt;strong&gt;인스턴스 프로퍼티&lt;/strong&gt;에 한하여 표현할 수 있다.&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;class Person {
    var name: String
    init(name: String) {
        self.name = name
    }
}
let person = Person(name: &amp;quot;presto&amp;quot;)
let keyPath = \Person.name
person[keyPath: keyPath]	// Presto
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;self 프로퍼티&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;인스턴스 메소드에서는 &lt;code&gt;self&lt;/code&gt;가 인스턴스를 가리키지만, 타입 메소드에서는 &lt;code&gt;self&lt;/code&gt;가 타입 그 자체를 가리킨다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;self&lt;/code&gt; 프로퍼티를 활용하여 값 타입 인스턴스 자체의 값을 치환할 수 있다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;클래스의 인스턴스는 참조 타입이므로 &lt;code&gt;self&lt;/code&gt; 프로퍼티에 다른 참조를 할당할 수 없다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;struct Level {
    var level: Int = 0
    mutating func levelUp() {
        level += 1
    }
    mutating func reset() {
        self = Level()
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;타입 메소드&lt;/h3&gt;
&lt;p&gt;&lt;code&gt;static&lt;/code&gt; 키워드를 사용하여 정의할 수 있으며, 상속 후 메소드 정의를 가능하게 하려면 &lt;code&gt;class&lt;/code&gt; 키워드를 사용하여 정의한다.&lt;/p&gt;
&lt;h2&gt;접근 제어&lt;/h2&gt;
&lt;p&gt;설정자만 더 낮은 접근 수준을 갖도록 제한할 수 있다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;public struct SomeType {
    // 저장 프로퍼티의 접근 수준 다르게 하기. 설정자는 비공개 접근수준, 접근자는 공개 접근수준.
    public private(set) var property: Int = 0
    // 서브스크립트의 접근 수준 다르게 하기. 설정자는 내부 접근수준, 접근자는 공개 접근수준.
    public internal(set) subscript(some: Int) -&amp;gt; Int {
        get { return property }
        set { property += some }
    }
    // 저장 프로퍼티도 같은 방법으로 구현할 수 있다.
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;클로저&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;클로저는 참조 타입&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;자동 클로저&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;자동 클로저는 전달 인자를 갖지 않는다.&lt;/li&gt;
&lt;li&gt;자동 클로저는 호출되었을 때 자신이 감싸고 있는 코드의 결과값을 반환한다.&lt;/li&gt;
&lt;li&gt;자동 클로저는 클로저가 호출되기 전까지 클로저 내부의 코드가 동작하지 않으므로 연산을 지연시킬 수 있다.&lt;/li&gt;
&lt;li&gt;자동 클로저 속성을 부여한 매개변수는 클로저 대신에 실행 결과를 전달인자로 받게 되며, 이것이 자동 클로저 매개변수에 전달되면 매개변수가 없는 결과 값의 타입을 반환하는 클로저로 변환해준다.&lt;/li&gt;

&lt;/ul&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;var strings = [&amp;quot;a&amp;quot;, &amp;quot;b&amp;quot;, &amp;quot;c&amp;quot;]
func first(_ function: @autoclosure () -&amp;gt; String) {
    function()
}
first(strings.removeFirst())
// strigns.removeFirst()의 결과인 a가 전달인자로 들어가며, String 값을 반환하는 매개변수가 없는 클로저로 변환해준다.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;옵셔널 체이닝과 빠른종료&lt;/h2&gt;
&lt;h3&gt;빠른종료&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;guard&lt;/code&gt;문의 조건에는 &lt;code&gt;Bool&lt;/code&gt; 타입이 오므로, 옵셔널 바인딩의 역할을 하지 않을 때도 빠른 종료를 위해 사용할 수 있다.&lt;/li&gt;
&lt;li&gt;쉼표를 사용하여 추가 조건을 나열할 수 있으므로, AND 연산과 같은 결과를 낸다.&lt;/li&gt;
&lt;li&gt;제어문 전환 명령어를 사용해야 하므로 특정 블록 내부에 위치하지 않는다면 사용이 제한된다.&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;/article&gt;</description>
      <category>Swift/야곰의 스위프트</category>
      <author>할루루</author>
      <guid isPermaLink="true">https://gorani95.tistory.com/260</guid>
      <comments>https://gorani95.tistory.com/260#entry260comment</comments>
      <pubDate>Wed, 3 Oct 2018 17:22:23 +0900</pubDate>
    </item>
    <item>
      <title>Swift API Design Guidelines</title>
      <link>https://gorani95.tistory.com/259</link>
      <description>&lt;article class=&quot;markdown-body&quot;&gt;
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset='UTF-8'&gt;&lt;meta name='viewport' content='width=device-width initial-scale=1'&gt;
&lt;title&gt;Swift API Guideline&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;&lt;h1&gt;&lt;a href='https://swift.org/documentation/api-design-guidelines/'&gt;Swift API Design Guidelines&lt;/a&gt;&lt;/h1&gt;
&lt;h2&gt;기초&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;사용 시점에서의 명백함&lt;/strong&gt;은 가장 중요한 목표입니다. 메소드나 프로퍼티 같은 엔티티는 오직 한 번만 선언되지만 반복적으로 &lt;em&gt;사용됩니다&lt;/em&gt;. 이것들을 분명하고 간결하게 사용할 수 있도록 API를 디자인하십시오. 디자인을 평가할 때, 선언을 읽는 것은 충분하지 않습니다. 그것이 문맥 안에서 분명한지 확실히 하기 위해 항상 실제 사용 경우를 시험하십시오.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;뚜렷함은 간결함보다 훨씬 더 중요합니다.&lt;/strong&gt; 스위프트 코드가 간결해질 수 있더라도, 가장 적은 문자들로 가장 작은 실행 가능한 코드를 작성할 수 있는 것은 우리의 목표가 아닙니다. 스위프트 코드에서의 간결함은 강타입 시스템에서의 부작용이며, 자연스럽게 상용문을 줄이는 기능입니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;모든 선언에 &lt;strong&gt;문서 주석을 작성하십시오.&lt;/strong&gt; 문서화하면서 얻는 인사이트는 당신의 디자인에 해박한 영향을 줄 수 있으므로, 회피하려 하지 마십시오.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;당신이 작성한 API의 기능을 간단한 용어로 묘사하는 데 어려움을 겪는다면, 잘못된 API를 디자인한 것일 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href='https://developer.apple.com/library/prerelease/mac/documentation/Xcode/Reference/xcode_markup_formatting_ref/'&gt;스위프트에 특화된 마크다운&lt;/a&gt;을 사용하십시오.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;선언된 엔티티를 묘사하는 &lt;strong&gt;요약으로 시작하십시오.&lt;/strong&gt; 종종 API는 그 선언과 요약으로부터 완벽하게 이해될 수 있습니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Returns&lt;/strong&gt; a &amp;quot;view&amp;quot; of &lt;code&gt;self&lt;/code&gt; containing the same elements in reverse order.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;요약에 집중하십시오.&lt;/strong&gt; 이것이 가장 중요한 부분입니다. 많은 훌륭한 문서화 주석들은 훌륭한 주석 이상 말고는 어떠한 것도 포함하고 있지 않습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;가능하다면 마침표로 맺어지는 &lt;strong&gt;간단한 한 문장의 단편을 사용하십시오&lt;/strong&gt;. 완전한 문장을 사용하지 마십시오.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;합니다. (x) 함. (o)&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;함수나 메소드가 무슨 일을 하고 무엇을 반환하는지 묘사하십시오.&lt;/strong&gt; null 효과 및 &lt;code&gt;Void&lt;/code&gt; 반환은 생략하십시오.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Inserts&lt;/strong&gt; &lt;code&gt;newHead&lt;/code&gt; at the beginning of &lt;code&gt;self&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Returns&lt;/strong&gt; a &lt;code&gt;List&lt;/code&gt; containning &lt;code&gt;head&lt;/code&gt; followed by the elemtns of &lt;code&gt;self&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Removes and returns&lt;/strong&gt; the first element of &lt;code&gt;self&lt;/code&gt; if non-empty; returns &lt;code&gt;nil&lt;/code&gt; otherwise.&lt;/p&gt;
&lt;p&gt;드문 경우에, 요약은 세미콜론으로 분리된 여러 개의 문장 단편들로 구성될 수 있습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;서브스크립트가 접근하는 것을 묘사하십시오.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Accesses&lt;/strong&gt; the &lt;code&gt;index&lt;/code&gt;th element.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;생성자가 생성하는 것을 묘사하십시오.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;Creates&lt;/strong&gt; an instance containing &lt;code&gt;n&lt;/code&gt; repititions of &lt;code&gt;x&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;모든 다른 선언에서, &lt;strong&gt;선언된 엔티티가 무엇을 하는지 묘사하십시오.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;A collection that&lt;/strong&gt; supports equally efficient insertion/removal at any position.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The element at the beginning&lt;/strong&gt; of &lt;code&gt;self&lt;/code&gt;, or &lt;code&gt;nil&lt;/code&gt; if self is empty.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;선택 사항으로&lt;/strong&gt;, 하나 이상의 단락과 글머리 기호 항목을 사용하여 &lt;strong&gt;문장을 이어나가십시오&lt;/strong&gt;. 단락은 빈 줄로 구분되고 완전한 문장을 사용합니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;요약 / 빈 줄 / 추가적인 설명(완전한 문장으로)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;적절할 때마다 요약을 넘어선 정보를 추가하기 위해 &lt;strong&gt;&lt;a href='https://developer.apple.com/library/archive/documentation/Xcode/Reference/xcode_markup_formatting_ref/SymbolDocumentation.html#//apple_ref/doc/uid/TP40016497-CH51-SW1'&gt;인식된 기호 문서화 마크업 요소&lt;/a&gt;를 사용하십시오.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;description / parameters / throws / returns 등&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;&lt;a href='https://developer.apple.com/library/archive/documentation/Xcode/Reference/xcode_markup_formatting_ref/SymbolDocumentation.html#//apple_ref/doc/uid/TP40016497-CH51-SW1'&gt;기호 명령 구문&lt;/a&gt;으로 인식된 글머리 기호 항목을 알고 사용하십시오.&lt;/strong&gt; Xcode와 같은 인기 있는 개발 도구는 다음과 같은 키워드로 시작하는 글머리 기호들에 특별한 처리를 합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Attention / Author / Authors / Bug / Complexity / Copyright / Date / Experiment / Important / Invariant / Note / Parameter / Parameters / Postcondition / Precondition / Remark / Requires / Returns / SeeAlso / Since / Throws / ToDo / Version / Warning&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h2&gt;네이밍&lt;/h2&gt;
&lt;h3&gt;명백한 사용 촉진하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;코드를 읽는 사람이 그 이름이 사용된 곳에서 &lt;strong&gt;모호함을 피하기 위해 필요한 모든 단어들을 포함하십시오.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;예를 들어, 컬렉션 내에서 주어진 위치에 있는 요소를 삭제하는 메소드를 생각해 봅시다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;public mutating func remove(at position: Index) -&amp;gt; Element&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;메소드 시그니쳐에서 &lt;code&gt;at&lt;/code&gt; 을 빠뜨린다면, 읽는 사람들은 그 메소드가 &lt;code&gt;x&lt;/code&gt; 를 삭제할 요소의 위치를 가리키는 것으로 사용한다고 이해하기보다는, &lt;code&gt;x&lt;/code&gt; 와 같은 요소를 찾아서 삭제한다고 이해할 가능성이 있습니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;employees.remove(x)&lt;/code&gt; : x를 삭제하려고 하는 것인가?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;필요 없는 단어들을 빼십시오.&lt;/strong&gt; 이름에 사용된 모든 단어는 사용 사이트에서 중요한 정보를 전달해야 합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;더 많은 단어들은 의도를 명백하게 하거나 의미를 모호하지 않게 하는 데 필요할 수 있으나, 읽는 사람이 이미 알아챈 정보에 대해 중복된 것들은 생략되어야 합니다. 특히, &lt;em&gt;단순히&lt;/em&gt; 타입 정보를 반복하는 단어는 생략하십시오.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;나쁜 예 : &lt;code&gt;public mutating func removeElement(_ member: Element) -&amp;gt; Element?&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;이 경우에, &lt;code&gt;Element&lt;/code&gt; 라는 단어는 호출부에서 두드러진 부분을 추가하지 않습니다. 다음의 API가 더 나아 보입니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;좋은 예 : &lt;code&gt;public mutating func remove(_ member: Element) -&amp;gt; Element?&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;때때로, 타입 정보를 반복하는 것은 모호함을 피하기 위해 필수적이나, 일반적으로 그것의 타입 대신에 매개변수의 &lt;em&gt;역할&lt;/em&gt; 을 묘사하는 단어를 사용하는 것이 더 좋습니다. 다음 내용에서 세부적인 부분을 확인하십시오.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;타입 제약사항보다는, &lt;strong&gt;역할에 따라서 변수, 매개변수, 연관 타입의 이름을 지으십시오.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;나쁜 예 : &lt;code&gt;var string = &amp;quot;Hello&amp;quot;&lt;/code&gt; / &lt;code&gt;associatedType ViewType: View&lt;/code&gt; &lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;위와 같은 방식으로 타입 이름을 다시 모으는 것은 뚜렷함과 표현력을 최적화하지 못합니다. 대신에, 엔티티의 &lt;em&gt;역할&lt;/em&gt; 을 표현하는 이름을 선택하기 위해 노력하십시오.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;좋은 예 : &lt;code&gt;var greeting = &amp;quot;Hello&amp;quot;&lt;/code&gt; / &lt;code&gt;associatedType ContentView: View&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;만약 연관 타입이 프로토콜 제약사항에 매우 단단하게 묶여있어서 프로토콜의 이름 자체가 그 역할이라면, 연관 타입의 이름에 &lt;code&gt;Type&lt;/code&gt; 을 붙여서 충돌을 피하십시오.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;associatedType IteratorType: Iterator&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;매개변수의 역할을 명확히 하기 위해 &lt;strong&gt;약한 타입 정보를 보상합니다.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;특히 매개변수의 타입이 &lt;code&gt;NSObject&lt;/code&gt;, &lt;code&gt;Any&lt;/code&gt;, &lt;code&gt;AnyObject&lt;/code&gt; 이거나, &lt;code&gt;Int&lt;/code&gt; 나 &lt;code&gt;String&lt;/code&gt; 같은 기본 타입일 때, 사용 시점에서 타입 정보와 문맥은 완벽하게 의도를 전달하지 못할 수 있습니다. 아래의 예제에서, 선언은 명백하나, 사용 사이트가 모호합니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;//나쁜 예
func add(_ observer: NSObject, for keyPath: String)
grid.add(self, for: graphics)
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;명백함을 되찾기 위해, &lt;strong&gt;각각의 약한 타입을 가진 매개변수의 앞에 그 역할을 묘사하는 명사를 붙이십시오.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;//좋은 예
func addObserver(_ observer: NSObject, forKeyPath: String)
grid.addObserver(self, forKeyPath: graphics)
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h3&gt;유창한 사용을 위해 노력하기&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;사용 사이트가 문법적인 영어 구&lt;em&gt;phrase&lt;/em&gt;를 형성하게끔 메소드와 함수의 이름을 짓도록 하십시오.&lt;/strong&gt;&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;//좋은 예
x.insert(y, at: z) //x, z에 y를 삽입
x.subViews(havingColor: y) //x, y 색을 갖는 서브뷰
//나쁜 예
x.insert(y, position: z)
x.subViews(color: y)
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;첫 번째 또는 두 번째 매개변수 후로 유창성이 저하되는 것은 이 매개변수들이 호출의 의미의 중심에 있지 않을 때 받아들여질 수 있습니다.&lt;/li&gt;

&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;AudioUnit.instantiate(with: description, options: [.inProcess], completionHandler: stopProgressBar)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;팩토리 메소드의 이름의 시작을 make로 하십시오.&lt;/strong&gt; ex) &lt;code&gt;x.makeIterator()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;생성자와 &lt;a href='https://en.wikipedia.org/wiki/Factory_method_pattern'&gt;팩토리 메소드&lt;/a&gt; 호출&lt;/strong&gt;의 첫 번째 인자는 기본 이름으로 시작하는 구문을 형성하지 않아야 합니다. ex) &lt;code&gt;x.makeWidget(cogCount: 47)&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;예를 들어서, 아래의 호출들의 첫 번째 인자들은 기본 이름과 동일한 구문의 일부로 읽히지 않습니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;//좋은 예
let foreground = Color(red: 32, green: 64, blue: 128)
let newPart = factory.makeWidget(gears: 42, spindles: 14)
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;이어서, API 작성자는 첫 번째 인자로 문법적 연속성을 만드려고 했습니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;//나쁜 예
let foreground = Color(havingRGBValuesRed: 32, green: 64, andBlue: 128)
let newPart = factory.makeWidget(havingGearCount: 42, andSpindleCount: 14)
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;실제로, &lt;a href='https://swift.org/documentation/api-design-guidelines/#argument-labels'&gt;전달인자 레이블&lt;/a&gt;에 관한 것과 함께 이 가이드라인은 &lt;a href='https://swift.org/documentation/api-design-guidelines/#type-conversion'&gt;값을 보존하는 타입 변환&lt;/a&gt;을 수행하는 호출이 아니라면 첫 번째 인자는 레이블을 가질 것임을 의미합니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;code class='language-swfit' lang='swfit'&gt;let rgbForeground = RGBColor(cmykForeground)
&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;사이드 이펙트에 따라 함수와 메소드의 이름을 지으십시오.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;사이드 이펙트가 없는 것들은 명사 구문으로 읽혀야 합니다. ex) &lt;code&gt;x.distance(to: y)&lt;/code&gt; / &lt;code&gt;i.successor()&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;사이드 이펙트가 있는 것들은 명령형 동사 구문으로 읽혀야 합니다. ex) &lt;code&gt;print(x)&lt;/code&gt; / &lt;code&gt;x.sort()&lt;/code&gt; / &lt;code&gt;x.append(y)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;mutating 메소드와 nonmutating 메소드 쌍의 이름을 일관되게 지으십시오.&lt;/strong&gt; mutating 메소드는 종종 비슷한 의미론을 갖는 nomutating 메소드를 갖지만, nonmutating 메소드는 현재 위치에서 인스턴스를 갱신하기보다는 새로운 값을 반환합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;동작이 &lt;strong&gt;순수하게 동사로 묘사&lt;/strong&gt;될 때, mutating 메소드에는 동사의 명령형을 사용하고, 그것에 상응하는 nonmutating 메소드에는 &lt;code&gt;ed&lt;/code&gt; 나 &lt;code&gt;ing&lt;/code&gt; 같은 접미사를 붙여 이름 지으십시오.&lt;/p&gt;
&lt;figure&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Mutating&lt;/th&gt;&lt;th&gt;Nonmutating&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;x.sort()&lt;/td&gt;&lt;td&gt;z = x.sorted()&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;x.append(y)&lt;/td&gt;&lt;td&gt;z = x.appending(y)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;
&lt;/table&gt;&lt;/figure&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;동사의 과거분사형을 사용하여 nonmutating 메소드의 이름을 짓도록 하십시오. (보통 &lt;code&gt;ed&lt;/code&gt; 를 붙임)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;동사가 직접적인 객체라서 &lt;code&gt;ed&lt;/code&gt; 를 붙이는 것이 문법적으로 맞지 않을 때, &lt;code&gt;ing&lt;/code&gt; 를 붙여 동사의 현재분사형을 사용하여 nonmutating 메소드의 이름을 지으십시오.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;동작이 &lt;strong&gt;순수하게 명사로 묘사&lt;/strong&gt;될 때, nonmutating 메소드의 이름에 명사를 사용하고 이에 상응하는 mutating 메소드에는 접두사로 &lt;code&gt;form&lt;/code&gt; 을 붙여 이름 지으십시오.&lt;/p&gt;
&lt;figure&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Mutating&lt;/th&gt;&lt;th&gt;Nonmutating&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;y.formUnion(z)&lt;/td&gt;&lt;td&gt;x = y.union(z)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;c.formSuccessor(&amp;amp;i)&lt;/td&gt;&lt;td&gt;j = c.successor(i)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;
&lt;/table&gt;&lt;/figure&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;그 사용이 nonmutating 할 때, &lt;strong&gt;불리언 메소드와 프로퍼티들은 리시버에 대한 주장&lt;em&gt;assertions about the receiver&lt;/em&gt; 으로 읽혀져야 합니다.&lt;/strong&gt; Ex) &lt;code&gt;x.isEmpty&lt;/code&gt; / &lt;code&gt;line1.intersects(line2)&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;어떤 것이 무엇인지&lt;/strong&gt;를 묘사하는 프로토콜은 명사로 읽혀져야 합니다. ex) &lt;code&gt;Collection&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;능력&lt;/strong&gt;을 묘사하는 프로토콜은 &lt;code&gt;able&lt;/code&gt;, &lt;code&gt;ible&lt;/code&gt; 또는 &lt;code&gt;ing&lt;/code&gt; 같은 접미사가 붙은 이름을 사용해야 합니다. ex) &lt;code&gt;Equatable&lt;/code&gt; / &lt;code&gt;ProgressReporting&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;다른 &lt;strong&gt;타입, 프로퍼티, 변수 그리고 상수의 이름은 명사로 읽혀져야 합니다.&lt;/strong&gt;&lt;/li&gt;

&lt;/ul&gt;
&lt;h3&gt;용어를 잘 사용하기&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Term of Art&lt;/strong&gt; : 명사. 특정 필드나 직업 내에서 정확한, 전문화된 의미를 갖는 단어나 구절. &lt;em&gt;이하 전문용어.&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;보다 일반적인 단어가 또한 의미를 잘 전달하는 경우에는 &lt;strong&gt;모호한 용어는 피하십시오.&lt;/strong&gt; &lt;code&gt;skin&lt;/code&gt; 이 당신의 목적을 잘 제공한다면 &lt;code&gt;epidermis&lt;/code&gt; 라고 말하지 마십시오. 전문용어는 필수적인 의사 소통 도구이지만, 그것을 사용하지 않았을 때 잃어버릴 수 있는 중요한 의미를 포착할 때에만 사용해야 합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;전문용어를 사용한다면 &lt;strong&gt;확립된 의미에 충실하십시오.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;보다 일반적인 단어 대신 기술적인 용어를 사용하는 유일한 이유는 다른 단어를 사용했을 때 모호하고 명백하지 않을 어떤 것을 정확하게 표현하기 위함입니다. 그러므로, API는 허용된 의미에 따라 용어를 엄격히 사용해야 합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;전문가를 놀라게 하지 마십시오.&lt;/strong&gt; 이미 그 용어에 친숙해져 있는 사람들은 우리가 그것에 새로운 의미를 고안해 넣은 것 같아 보인다면 놀라거나 언짢아할 수 있을 것입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;초심자를 혼란스럽게 하지 마십시오.&lt;/strong&gt; 그 용어를 배우려고 하는 사람들은 인터넷 검색을 하고 그것의 전통적인 의미를 찾을 수 있습니다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;축약형을 사용하는 것을 피하십시오.&lt;/strong&gt; 특히 비표준 축약형은 효과적인 전문용어가 됩니다. 그것을 이해하는 것은 축약형이 아닌 형태로 올바르게 변환하는 데 달려있기 때문입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;당신이 사용하는 어떠한 축약형이 의도하는 의미는 인터넷 검색을 통해 쉽게 찾을 수 있어야 합니다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;선례를 포용하십시오.&lt;/strong&gt; 기존 문화에 대한 적합성을 희생하면서 용어를 초보자를 위해 최적화하지 마십시오.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;연속적인 자료구조에 &lt;code&gt;List&lt;/code&gt; 같은 쉬운 용어를 사용하는 것보다 &lt;code&gt;Array&lt;/code&gt; 라과 이름짓는 것이 나은데, 초심자가 &lt;code&gt;List&lt;/code&gt; 의 의미를 더 쉽게 이해할 수 있을지라도 그렇습니다. 배열은 현대 컴퓨팅에서 기본적인 것이고, 모든 프로그래머가 알고 있거나 곧 배열이 무엇인지 배울 것입니다. 대부분의 프로그래머에게 친숙하고, 인터넷 검색과 질문에서 답을 얻기 쉬운 용어를 사용하십시오.&lt;/li&gt;
&lt;li&gt;수학과 같은 특정한 프로그래밍 도메인에서, &lt;code&gt;sin(x)&lt;/code&gt; 와 같은 널리 선행된 용어는 &lt;code&gt;verticalPositionOnUnitCircleAtOriginOfEndOfRadiusWithAngle(x)&lt;/code&gt; 같은 설명 구절보다 선호됩니다. 이 경우에, &lt;code&gt;sine&lt;/code&gt; 이라는 완전한 단어가 있을지라도 &lt;code&gt;sin(x)&lt;/code&gt; 는 수십 년간 프로그래머들 사이에서, 몇 세기동안 수학자들 사이에서 흔하게 사용되었으므로, 선례는 축약형을 피하라는 가이드라인의 중요도보다 높습니다. &lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h2&gt;컨벤션&lt;/h2&gt;
&lt;h3&gt;일반적인 컨벤션&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;O(1)의 시간복잡도를 갖지 않는 계산 프로퍼티에 대해서 문서화하십시오.&lt;/strong&gt; 사람들은 그 프로퍼티에 접근하는 것이 중요한 연산을 포함하지 않을 것이라고 가정할 것인데, 그것들은 정신적 모델&lt;em&gt;mental model&lt;/em&gt;로 저장 프로퍼티를 가지고 있기 때문입니다. 가정이 위반될 때 경고하는 것을 확실히 해야 합니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;자유 함수&lt;em&gt;free function&lt;/em&gt;보다는 메소드와 프로퍼티를 선호하십시오.&lt;/strong&gt; 자유 함수는 특별한 경우에서만 사용됩니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;명백한 &lt;code&gt;self&lt;/code&gt; 가 없을 때&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;min(x, y, z)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;함수가 제약 없는 제네릭일 때&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;print(x)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;함수 구문이 확립된 영역의 표기법의 일부일 때&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;sin(x)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;대소문자 컨벤션을 따르십시오.&lt;/strong&gt; 타입과 프로토콜의 이름은 대문자 카멜케이스를 사용합니다. 다른 모든 것들은 소문자 카멜케이스를 사용합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;흔히 미국식 영어에서 모두 대문자로 되어 있는 &lt;a href='https://en.wikipedia.org/wiki/Acronym'&gt;약어와 단어의 앞글자를 따서 만들어진 단어&lt;/a&gt;는 대소문자 컨벤션에 의해 균일하게 대문자 또는 소문자로 이루어져야 합니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;var utf8Bytes: [UTF8.CodeUnit]&lt;/code&gt; : UTF8&lt;/p&gt;
&lt;p&gt;&lt;code&gt;var isRepresentableAsASCII = true&lt;/code&gt; : ASCII&lt;/p&gt;
&lt;p&gt;&lt;code&gt;var userSMTPServer: SecureSMTPServer&lt;/code&gt; : SMTP&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;다른 약어들은 일반적인 단어처럼 취급되어야 합니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;var radarDetector: RadarScanner&lt;/code&gt; : Radar&lt;/p&gt;
&lt;p&gt;&lt;code&gt;var enjoysScubaDiving = true&lt;/code&gt; : Scuba&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;같은 기본 의미를 공유하거나 특정 영역에서 동작할 때 &lt;strong&gt;메소드들은 기본 이름을 공유할 수 있습니다.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;아래의 예시는 권장되는데, 메소드들이 본질적으로 같은 것을 하기 때문입니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;//좋은 예시
extension Shape {
    func contains(_ other: Point) -&amp;gt; Bool {...}
	func contains(_ other: Shape) -&amp;gt; Bool {...}
	func contains(_ other: LineSegment) -&amp;gt; Bool {...}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;그리고 기하학적 타입과 컬렉션이 분리된 영역에 있기 때문에, 같은 프로그램에서도 또한 괜찮습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;//좋은 예시
extension Collection where Element: Equatable {
    func contains(_ sought: Element) -&amp;gt; Bool {...}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;하지만 아래의 &lt;code&gt;index&lt;/code&gt; 메소드들은 다른 의미를 가지고 있고, 다르게 이름 지어져야 합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;//나쁜 예시
extension Database {
    func index() {...}
    func index(_ n: Int, inTable: TableID) -&amp;gt; TableRow {...}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;마지막으로, 타입 추론에 모호함을 초래하기 때문에 반환 형식을 오버로딩하는 것을 피하십시오.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;//나쁜 예시
extension Box {
    func value() -&amp;gt; Int? {...}
 	func value() -&amp;gt; String? {...}   
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h3&gt;매개변수&lt;/h3&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;func move(from start: Point, to end: Point)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;문서화된 것을 제공할 수 있는 매개변수 이름을 선택하십시오.&lt;/strong&gt; 매개변수 이름이 함수나 메소드의 사용 시점에 보이지 않는다 하더라도, 그것들은 중요한 설명의 역할을 수행합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;문서화된 것을 읽기 쉽게 하는 이름을 선택하십시오. 예를 들어, 이러한 이름들은 문서를 자연스럽게 읽도록 합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;/// Return an `Array` containing the elements of `self` that satisfy `predicate`.
func filter(_ predicate: (Element) -&amp;gt; Bool) -&amp;gt; [Generator.Element]
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;그러나, 아래와 같은 것들은 문서를 어색하고 문법적으로 맞지 않게 합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;/// Return an `Array` containing the elements of `self` that satisfy `includedInResult`.
func filter(_ includedInResult: (Element) -&amp;gt; Bool) -&amp;gt; [Generator.Element]
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;일반적인 사용을 단순화할 때 &lt;strong&gt;기본 매개변수의 이점을 취하십시오.&lt;/strong&gt; 하나의 공통적으로 사용되는 값을 취하는 어떤 매개변수는 기본값을 갖는 매개변수의 후보가 됩니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;기본 인자는 관련 없는 정보를 숨김으로써 가독성을 향상시킵니다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;let order = lastName.compare(royalFamilyName, options: [], range: nil, locale: nil)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;위의 코드는 다음처럼 훨씬 간단해질 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;let order = lastName.compare(royalFamilyName)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;기본 인자는 일반적으로 메소드 패밀리의 사용에서 선호되는데, API를 이해하려는 사람들에게 인지적 부담을 적게 주기 때문입니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;extension String {
    public func compare(_ other: String, options: CompareOptions = [], range: Range? = nil, locale: Locale? = nil) -&amp;gt; Ordering
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;위의 코드는 간단해보이지 않을 수 있지만, 아래보다는 훨씬 간단합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;extension String {
    public func compare(_ other: String) -&amp;gt; Ordering
    public func compare(_ other: String, options: CompareOptions) -&amp;gt; Ordering
    public func compare(_ other: String, options: CompareOptions, range: Range) -&amp;gt; Ordering
    public func compare(_ other: String, options: CompareOptions, range: Range, locale: Locale) -&amp;gt; Ordering
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;메소드 패밀리의 모든 멤버들은 사용자들에 의해 분리되어 문서화되고 이해될 필요가 있습니다. 그것들 사이를 결정하기 위해, 사용자는 그것들 모두를 이해할 필요가 있고, 때때로 그 관계에 대해 놀랍니다. 예를 들어, &lt;code&gt;foo(bar: nil)&lt;/code&gt; 과 &lt;code&gt;foo()&lt;/code&gt; 는 항상 동의어인 것은 아닙니다.  ,,,,,,,,,&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;기본값이 있는 매개변수를 매개변수 리스트의 끝에 위치시키도록 하십시오.&lt;/strong&gt; 기본값이 없는 매개변수는 보통 메소드의 의미에 있어서 더 본질적이고, 메소드가 호출되는 곳에서 안정된 생성 패턴을 제공합니다.&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h3&gt;전달인자 레이블&lt;/h3&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;func move(from start: Point, to end: Point)&lt;/code&gt; / &lt;code&gt;x.move(from: x, to: y)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;인자가 유용하게 구별되지 않는다면 모든 레이블을 생략하십시오.&lt;/strong&gt; ex)&lt;code&gt;min(number1, number2)&lt;/code&gt; / &lt;code&gt;zip(sequence1, sequence2)&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;값 보존 타입 변환을 수행하는 생성자에서는 첫 번째 전달인자 레이블을 생략하십시오.&lt;/strong&gt; ex) &lt;code&gt;Int64(someUInt32)&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;첫 번째 인자는 항상 변환의 근원이 되어야 합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;extension String {
    init(_ x: BigInt, radix: Int = 10)	// x를 10진수 숫자로 변환
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;그럼에도 불구하고, &amp;quot;유형을 좁히는&amp;quot; 형식 전환에서는 유형을 좁히는 레이블을 묘사하는 것을 추천합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;extension UInt32 {
    init(truncating source: UInt64)	//source의 아래 32비트를 갖는 인스턴스 생성
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt;값을 보존하는 타입 변환은 단일성&lt;em&gt;monomorphism&lt;/em&gt;입니다. 즉, 근원 값의 모든 차이는 결과 값의 차이를 초래합니다. 예를 들어, Int8에서 Int64로의 변환은 값을 보존하는데, 모든 고유 Int8 값이 고유 Int64 값으로 변환되기 때문입니다. 그러나, 다른 방향으로의 변환은 값 보존을 할 수 없습니다. Int64는 Int8에서 표현할 수 있는 값보다 더 많은 값을 가질 수 있기 때문입니다.&lt;/p&gt;
&lt;p&gt;즉, 기존 값을 되찾는 능력은 변환이 값 보존인지 여부에 영향을 주지 않습니다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;첫 번째 인자가 전치사구의 일부를 형성할 때, 그것을 전달인자 레이블로 지정하십시오.&lt;/strong&gt; 전달인자 레이블은 일반적으로 전치사에서 시작해야 합니다. ex) &lt;code&gt;x.removeBoxes(havingLength: 12)&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;첫 두 개의 인자가 단일 추상화의 일부를 나타낼 때 예외가 발생합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;//나쁜 예
a.move(toX: b, y: c)
a.fade(fromRed: b, green: c, blue: d)
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;이러한 경우, 전달인자 레이블을 전치사 &lt;em&gt;다음에&lt;/em&gt; 붙이십시오. 추상화를 명백하게 하기 위해서입니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;//좋은 예
a.moveTo(x: b, y: c)
a.fadeFrom(red: b, green: c, blue: d)
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;그렇지 않다면, 첫 번째 인수가 문법적 구문의 일부를 형성한다면, 이전에 위치하는 단어를 기본 이름에 추가하여 레이블을 생략합니다.&lt;/strong&gt; ex) &lt;code&gt;x.addSubview(y)&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;이 가이드라인은 첫 번째 인자가 문법적 구문의 일부를 형성하지 &lt;em&gt;않는다면&lt;/em&gt;, 레이블을 가져야 한다는 것을 암시합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;view.dismiss(animated: false)
let text = words.split(maxSplits: 12)
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;구문이 올바른 의미를 전달하는 것은 중요합니다. 아래의 코드는 문법적으로 올바르지만 잘못된 것을 표현할 지도 모릅니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;view.dismiss(false)	//dismiss하지 않는 것인가? Bool을 dismiss하는가?
words.split(12)		//12라는 숫자를 split하는 것인가?
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;또한 기본값을 가진 인자들도 생략될 수 있으며, 이러한 경우 문법적 구문의 일부를 형성하지 않고, 그러므로 항상 레이블을 가져야 함을 알아두십시오.&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;모든 다른 인자에 레이블을 붙이십시오.&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h2&gt;특별 지침&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;튜플 멤버에 레이블을 붙이고 클로저 매개변수에 이름을 붙이십시오.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;이러한 이름들은 설명력을 가지며, 문서 주석으로부터 참조될 수 있고, 튜플 멤버들에 대한 표현적인 접근을 제공합니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;mutating func ensureUniqueStorage(minimumCapacity requestedCapacity: Int, allocate: (_ byteCount: Int) -&amp;gt; UnsafePointer&amp;lt;Void&amp;gt;) -&amp;gt; (reallocated: Bool, capacityChanged: Bool)
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;클로저 매개변수에 사용되는 이름들은 최상위 수준 함수의 매개변수 이름과 같이 선택되어야 합니다. 호출 사이트에서 나타나는 클로저 인자를 위한 레이블은 지원되지 않습니다.&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;오버로딩 집합들에서 모호함을 피하기 위해 &lt;strong&gt;제약 없는 다형성에 더 주의를 기울이십시오.&lt;/strong&gt; ex) &lt;code&gt;Any&lt;/code&gt; / &lt;code&gt;AnyObject&lt;/code&gt; / 제약 없는 제네릭 매개변수들&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;예를 들어, 다음과 같은 오버로딩 집합을 고려하십시오.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;struct Array {
    public mutating func append(_ newElement: Element)
    public mutating func append(_ newElement: S) where S.Generator.Element == Element
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;이 메소드들은 의미론적으로 가족을 형성하고, 인수 유형은 처음에는 날카롭게 구분되는 것처럼 보입니다. 그러나, &lt;code&gt;Element&lt;/code&gt; 가 &lt;code&gt;Any&lt;/code&gt; 일 때, 단일 요소는 요소들의 시퀀스처럼 같은 타입을 가질 수 있습니다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;모호함을 없애기 위해, 두 번째 오버로딩을 더 명확하게 이름 지으십시오.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;struct Array {
    public mutating func append(_ newElement: Element)
    public mutating func append(contentsOf newElement: S) where S.Generator.Element == Element
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;새로운 이름이 문서 주석에 어떻게 더 잘 들어맞는지 확인하십시오. 이 경우에, 문서화 주석을 작성하는 행위는 실제로 API 저자의 주의에 이슈를 불러일으킬 것입니다.&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;/article&gt;</description>
      <category>iOS</category>
      <author>할루루</author>
      <guid isPermaLink="true">https://gorani95.tistory.com/259</guid>
      <comments>https://gorani95.tistory.com/259#entry259comment</comments>
      <pubDate>Sat, 22 Sep 2018 23:21:04 +0900</pubDate>
    </item>
    <item>
      <title>Memory Profiling</title>
      <link>https://gorani95.tistory.com/258</link>
      <description>&lt;article class=&quot;markdown-body&quot;&gt;



&lt;meta charset=&quot;UTF-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width initial-scale=1&quot;&gt;
&lt;title&gt;RespectU Memory Profiling&lt;/title&gt;
&lt;h1&gt;시작&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;https://www.appcoda.com/memory-management-swift/?utm_source=drip&amp;amp;utm_medium=email&amp;amp;utm_campaign=design-pattern-memory-management&quot;&gt;Memory Management in Swift: Understanding Strong, Weak and Unowned References&lt;/a&gt; 글을 읽으면서 ARC에 대한 개념을 다시 한번 살피고 있었는데, 글 말미에 메모리 누수 추적에 관한 문장이 짤막하게 나왔다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;For example, if you want to detect memory leaks, you can go up to the menu and select Product &amp;gt; Profile &amp;gt; Leaks.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;내 앱이 여기에 자유로운지 확인해보고 싶어졌다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;프로파일링 과정&lt;/h1&gt;
&lt;p&gt;앱 실행 과정은 다음과 같다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;앱 실행 &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;닉네임과 버전을 받아오는 네트워킹을 수행한다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;가이드 부분으로 넘어가기&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;내비게이션 컨트롤러를 이용해서 다음 화면으로 이동한다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;음악 화면 띄우기&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;앱 내의 데이터를 보여주는데, 모든 탭을 로드하게 했고, 가장 많은 데이터를 로드하게 된다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;미션 화면 띄우기 / 트로피 화면 띄우기 / 도전과제 화면 띄우기&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;앱 내의 데이터를 가져다가 뿌려준다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;다운로드 화면 띄우기&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;서버에서 성과 정보를 받아오는 네트워킹을 수행하고, 내부 데이터베이스를 갱신하는 작업을 수행한다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;프로파일링 전&lt;/h1&gt;&lt;div&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/9923A8495B9FB1EC1B&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F9923A8495B9FB1EC1B&quot; width=&quot;820&quot; height=&quot;312&quot; filename=&quot;1.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/990E4A495B9FB1EC1D&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F990E4A495B9FB1EC1D&quot; width=&quot;820&quot; height=&quot;151&quot; filename=&quot;2.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;시작 : 18.83MB ~ 22MB&lt;/p&gt;&lt;p&gt;최고 : 51MB&lt;/p&gt;&lt;p&gt;끝 : 31.79MB&lt;/p&gt;&lt;p&gt;최고 메모리 점유율은 음악 화면에서 모든 탭을 로드했을때 일어났다. 하지만 별다른 메모리 누수는 일어나지 않은 것 같다.&lt;/p&gt;&lt;p&gt;&lt;code&gt;CFNetwork&lt;/code&gt; 클래스에서 엄청 잡아먹는다. 구글링을 해보았다. &lt;/p&gt;&lt;p&gt;세션을 명시적으로 종료해주지 않아서 일어나는 문제라고 한다.&lt;/p&gt;&lt;p&gt;&lt;code&gt;finishTasksAndInvalidate&lt;/code&gt; 메소드를 각 핸들러에 추가해 주었다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;프로파일링 후 &lt;/h1&gt;&lt;div&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/991A604D5B9FB1FB2D&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F991A604D5B9FB1FB2D&quot; width=&quot;820&quot; height=&quot;300&quot; filename=&quot;3.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p style=&quot;text-align: center; clear: none; float: none;&quot;&gt;&lt;span class=&quot;imageblock&quot; style=&quot;display: inline-block; width: 820px;  height: auto; max-width: 100%;&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/cfile/tistory/994CB14D5B9FB1FB29&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Ft1.daumcdn.net%2Fcfile%2Ftistory%2F994CB14D5B9FB1FB29&quot; width=&quot;820&quot; height=&quot;147&quot; filename=&quot;4.png&quot; filemime=&quot;image/jpeg&quot; style=&quot;&quot;/&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;/div&gt;
&lt;p&gt;시작 : 13.16MB ~ 24MB&lt;/p&gt;&lt;p&gt;최고 : 43MB&lt;/p&gt;&lt;p&gt;끝 : 26.53MB&lt;/p&gt;&lt;p&gt;메모리 점유율을 약 5MB 감소시켰다!&lt;/p&gt;&lt;p&gt;메모리 누수가 일어나는 곳도 확연히 줄어 단 한군데밖에 나오지 않았다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;마무리&lt;/h1&gt;
&lt;p&gt;신기했다. Instruments를 다각도에서 활용해 보아야겠다는 생각이 들었다.&lt;/p&gt;&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;참고한 링크&lt;/h1&gt;
&lt;p&gt;&lt;a href=&quot;http://kka7.tistory.com/56?category=904185&quot;&gt;URLSSession 사용시 참고&lt;/a&gt;&lt;/p&gt;&lt;p&gt;&lt;a href=&quot;http://appmaid.tistory.com/33&quot;&gt;CFNetwork 에서의 XTubeManager 관련 메모리 누수&lt;/a&gt;&lt;/p&gt;


&lt;/article&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;</description>
      <category>iOS</category>
      <author>할루루</author>
      <guid isPermaLink="true">https://gorani95.tistory.com/258</guid>
      <comments>https://gorani95.tistory.com/258#entry258comment</comments>
      <pubDate>Mon, 17 Sep 2018 22:54:08 +0900</pubDate>
    </item>
    <item>
      <title>UIBezierPath 클래스로 도형 그리기</title>
      <link>https://gorani95.tistory.com/257</link>
      <description>&lt;article class=&quot;markdown-body&quot;&gt;



&lt;meta charset=&quot;UTF-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width initial-scale=1&quot;&gt;
&lt;title&gt;Bezier Path&lt;/title&gt;
&lt;h2&gt;시작&lt;/h2&gt;
&lt;p&gt;애플리케이션을 개발하는 과정은 UI를 만드는 것과 스크린에 보여지는 그것의 간단하거나 복잡한 뷰를 만드는 것들을 포함합니다. 애플리케이션의 간단한 '스크린'을 그리는 데에는 다른 방법들과 다른 접근법들이 있습니다: 디자이너에 의해 이미 만들어진 그래픽을 사용, 코드로 UI를 구현, 인터페이스 빌더 사용, 이것들을 조합하여 사용하기, 등등. 그러나, 당신은 프로그래밍적으로 사용자 정의 형태를 만들 필요가 있을 때가 항상 있을 것이고, 어떻게 하는지 모른다면, 그 때에 문제가 되기 시작합니다.&lt;/p&gt;
&lt;p&gt;하지만 이러한 문제들은 &lt;a href=&quot;https://developer.apple.com/library/archive/documentation/2DDrawing/Conceptual/DrawingPrintingiOS/BezierPaths/BezierPaths.html&quot;&gt;문서&lt;/a&gt;에 따르면 벡터 기반 경로를 만드는 데 필요한 &lt;code&gt;UIBezierPath&lt;/code&gt; 클래스를 사용하여 해결할 수 있습니다. 간단하게 말해서, 이 클래스를 사용하여 어떠한 형태를 묘사하는 사용자 정의 경로를 정의할 수 있고, 당신이 원하는 어떠한 사용자 정의 결과를 달성하기 위해 그 경로들을 사용할 수 있습니다. 직사각형, 정사각형, 타원, 원 같은 간단한 형태에서부터, 매우 복잡한 형태도 점 집합 사이에 직선과 곡선을 더하여 경로에 선을 더함으로써 만들 수 있습니다.&lt;/p&gt;
&lt;p&gt;위의 클래스에 의해 만들어지는 베지어 경로는 그 자신 홀로 설 수 없습니다. 그것은 그것이 렌더링되는 곳에서 Core Graphics 컨텍스트를 필요로 합니다. 컨텍스트를 얻는 세 가지 방법이 있습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;CGContext&lt;/code&gt; 컨텍스트를 사용합니다.&lt;/li&gt;
&lt;li&gt;사용자 정의 형태를 그리고 싶은 클래스를 &lt;code&gt;UIView&lt;/code&gt; 를 상속받게 하고, 기본으로 제공되는 &lt;code&gt;draw(_:)&lt;/code&gt; 메소드를 사용합니다. 그러면 필요한 컨텍스트는 자동으로 주어집니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;CAShapeLayer&lt;/code&gt; 오브젝트라고 불리는 특별한 레이어를 만듭니다.&lt;/li&gt;

&lt;/ol&gt;
&lt;p&gt;세 가지 선택지 모두 이 튜토리얼의 마지막 두 가지를 만족시키므로, Core Graphics 프로그래밍 세부 정보가 포함된 스코프를 놓치지 않습니다.&lt;/p&gt;
&lt;p&gt;방금 언급한 &lt;code&gt;CAShapeLayer&lt;/code&gt; 클래스 또한 이 포스트의 주제이며, 우리는 그것에 대해서 몇 가지를 볼 것입니다. 이 클래스는 &lt;code&gt;CALayer&lt;/code&gt; 로부터 상속받았고, 그것의 객체는 모든 뷰가 가지고 있는 기본 레이어로 사용됩니다. 대부분의 경우 형태 레이어 객체는 기본 레이어 객체의 최상단에 추가적은 레이어로서 추가되지만, 마스크로서도 사용될 수 있습니다. 나중에 두 가지의 경우에 대해서 논의할 것입니다. 추가적으로, 형태 레이어 객체의 몇 가지 가장 중요한 프로퍼티들에 대해, 그리고 그것들의 의미에 대해 논의할 것입니다.&lt;/p&gt;
&lt;p&gt;이 튜토리얼에서 나의 목표는 당신에게 베지어 경로를 만들고 그것들을 따라 형태 레이어 객체를 사용하는 방법에 대해 실용적인 가이드라인을 제공하는 것입니다. 우리는 일련의 과정을 작지만 직설적인 예제를 만날 것입니다. 그러므로 당신이 이 튜토리얼을 완료했을 때 두 가지 개념의 기초에 대해 익숙해져 있을 것이고, 스스로 좀더 복잡한 경우에 대해 생각할 수 있게 될 것입니다. 이미 베지어 경로와 형태 레이어에 대해 몇 가지 지식을 가지고 있다면, 이 튜토리얼은 그 지식에 새로운 무언가를 추가해 줄 것입니다. 이러한 것을 처음 접해본다면, iOS 개발에서 정말로 흥미로운 부분을 배우게 될 것입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;프로젝트 준비하기&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;Single View Application&lt;/code&gt; 프로젝트를 생성하고, &lt;code&gt;UIView&lt;/code&gt; 를 상속받는 클래스 파일을 하나 만들어 줍니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;ViewController.swift&lt;/code&gt; , &lt;code&gt;DemoView.Swift&lt;/code&gt; 파일에 원문에 등장하는 코드 작성하기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;준비는 끝났고, 첫 번째 베지어 경로를 만들기 위해 가봅시다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;경로와 형태 만들기&lt;/h2&gt;
&lt;p&gt;수영을 배우는 가장 좋은 방법은 물로 뛰어드는 것이라고 사람들은 말합니다. 그리고 나는 같은 원리가 베지어 경로와 함께 작업하는 것에도 적용된다고 믿습니다. 그러므로, 많이 말할 것 없이 어떻게 &lt;code&gt;UIBezierPath&lt;/code&gt; 객체가 만들어지고, 구성되고, 사용될 수 있는지 명백하게 할 수 있을 특정 예제를 봐봅시다. 사실, 우리는 여러 개의 경로를 만들 것인데, 각각은 다른 종류의 형태의 결과물일 것입니다. 준비하고, 숨을 크게 들이쉬고, &lt;code&gt;DemoView.swift&lt;/code&gt; 파일을 여십시오. 모든 구현은 이 클래스 안에서 이루어질 것입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;직사각형&lt;/h2&gt;
&lt;p&gt;간단하지만, 꽤 유익한 것으로 시작할 것입니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;본문에 등장하는 코드를 &lt;code&gt;DemoView.swift&lt;/code&gt; 에 작성하기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;위의 것은 뷰의 주위를 감싸는 직사각형을 만듭니다. 하지만 우리가 그것이 렌더링될 경로에 대해 컨텍스트를 제공하지 않았기 때문에 여전히 아무런 효과도 없습니다. 나중에 해볼 것입니다.&lt;/p&gt;
&lt;p&gt;먼저, 모든 코드 줄이 무슨 일을 하는지 자세하게 살펴봅시다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;path = UIBezierPath()&lt;/code&gt; &lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;먼저, &lt;code&gt;UIBezierPath&lt;/code&gt; 객체를 초기화합니다. 이 클래스가 제공하는 다양한 생성자들이 있고 서로 다른 매개변수의 숫자와 종류를 갖지만, 지금은 간단한 것이 우리가 필요로 하는 것입니다. &lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;path.move(to: CGPoint(x: 0.0, y: 0.0))&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;경로 객체가 준비되면, 우리가 항상 해야 하는 첫 번째 일은 형태가 그려지기 시작할 포인트를 정의하는 것입니다. 포인트는 &lt;code&gt;CGPoint&lt;/code&gt; 값으로 표현되며, &lt;code&gt;move(to:)&lt;/code&gt; 메소드는 경로에게 그 포인트에 대해 알려줍니다. 우리의 샘플 코드에서, (0.0, 0.0) 좌표는 우리 뷰의 좌측 상단 모서리를 의미합니다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;path.addLine(to: CGPoint(x: 0.0, y: self.frame.size.height))&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;우리가 원하는 다음 것은 시작점과 우리가 특정해야 하는 또다른 포인트 사이에 선을 긋는 것입니다. 우리는 그 포인트를 제공하고, 같은 시간에 &lt;code&gt;addLine(to:)&lt;/code&gt; 메소드를 사용하여 시스템에게 선을 그리라고 일러줍니다. 이전에 한 것처럼, 이 메소드 또한 매개변수로 &lt;code&gt;CGPoint&lt;/code&gt; 값에 접근하는데, 이것은 명백하게 첫 번째 포인트와 선을 사용하여 연결하기 원하는 두 번째 포인트입니다. 그 선은 뷰의 좌측 상단 모서리에서 시작하여 &lt;del&gt;우측&lt;/del&gt;좌측 하단 모서리에서 끝납니다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;path.addLine(to: CGPoint(x: self.frame.size.width, y: self.frame.size.height))&lt;/code&gt; / &lt;code&gt;path.addLine(to: CGPoint(x: self.frame.size.width, y: 0))&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이어지는 두 개의 명령은 이전의 것처럼 같은 로직이고, 선을 사용하여 포인트들을 연결합니다. 네 번째 줄에서, 우리는 뷰의 좌측 하단 모서리에서 우측 하단 모서리까지 연결하는 선을 경로에 추가합니다. 다섯 번째 줄에서, 새로운 선을 우측 하단에서 우측 상단까지 그립니다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;path.close()&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;여기까지, 우리는 직사각형의 네 개의 선 중 세 개를 그렸습니다. 이성적으로 기대해 보았을 때, 우리는 형태를 만들기 위해 선을 하나 더 추가해야 합니다. 하지만, 그럴 필요가 없습니다. &lt;code&gt;close()&lt;/code&gt; 메소드를 호출하여, 우리는 경로의 끝을 선언하고, 시스템은 자동으로 우리를 위해 없는 선을 그려 줄 것입니다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;쉽네요. 맞나요? 우리가 한 모든 것은 점들을 연결하고 포인트 사이에 선을 만들어 준 것입니다. 이제, 위의 메소드는 사용되어야 하고, 그것을 할 위치는 &lt;code&gt;DemoView&lt;/code&gt; 클래스의 &lt;code&gt;draw(_:)&lt;/code&gt; 메소드입니다. 그것은 경로에 컨텍스트를 제공할 것입니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;draw(_:)&lt;/code&gt; 메소드를 재정의하여 &lt;code&gt;createRectangle()&lt;/code&gt; 메소드 호출하는 코드 작성하기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;지금까지 했던 것을 테스트하기 전에, 배경 및 선 색상(a fill and a stroke colour)을 설정하여 더 흥미롭게 해봅시다. 배경색은 우리가 선택한 색상으로 형태의 전체를 덮는 반면에, 테두리색은 형태의 경계선을 칠합니다. 몇 가지 코드를 더 작성해 봅시다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;배경색과 테두리색을 설정하는 코드를 &lt;code&gt;draw(_:)&lt;/code&gt; 메소드 안에 작성하기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이것들은 정말로 간단합니다. 그래서 실행하여 베지어 경로 경로의 결과를 확인할 수 있습니다.&lt;/p&gt;
&lt;p&gt;축하합니다. 이것이 당신의 첫 번째 베지어 경로입니다! 하지만, 뷰의 배경 색상을 설정하고 레이어에 경계를 추가하여 동일한 결과를 얻을 수 있으므로, 뷰의 프레임을 정확하게 따라 형태를 그리는 것은 다소 무의미합니다. 하지만 문제될 것은 없습니다. 우리가 여기서 한 것은 가장 좋은 시작을 위한 것입니다! 이제 우리는 기초를 알고, 더 진보된 경우를 보기 위해 갈 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;삼각형&lt;/h2&gt;
&lt;p&gt;당신이 추측하는 것처럼, 경로에 선을 추가하여 만들어지는 어떠한 형태를 만들기 위해 적절한 포인트를 명시하는 것이 중요합니다. 경로에 주어지는 점이 적절한 것이라면, 단일 형태에서 폴리곤까지도 만들 수 있습니다. 이러한 정신에서, 이번에는 삼각형을 만들어 봅시다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;삼각형 만드는 함수 정의하기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;여기에서 시작점은 뷰의 상단 중앙 지점입니다. 위의 코드는 &lt;code&gt;createRectangle&lt;/code&gt; 메소드 안에 있는 이전의 것과 비슷해 보입니다. 우리는 단지 포인트와 만들 선의 수를 바꾸었을 뿐입니다.&lt;/p&gt;
&lt;p&gt;메소드를 &lt;code&gt;draw(_:)&lt;/code&gt; 에서 호출하는 것을 잊지 마십시오.&lt;/p&gt;
&lt;p&gt;시작점을 바꾸고 선을 추가해 보십시오. 다른 매개변수는 다른 결과를 이끌어 냅니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;타원과 원&lt;/h2&gt;
&lt;p&gt;타원을 만드는 것은 쉽고, 우리가 정말로 필요로 하는 것은 간단한 &lt;code&gt;UIBezierPath()&lt;/code&gt; 이 아닌 경로를 위한 다른 생성자를 사용하는 것입니다. 다음의 간단한 예제를 보십시오. 우리는 다른 생성자를 사용하고 있으며 형태를 위한 프레임으로 우리의 뷰의 바운드를 제공하고 있습니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;타원형 경로 만드는 코드 작성하기. &lt;code&gt;UIBezierPath(ovalIn:)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;프레임을 변화시키는 것으로, 우리는 경로의 결과에 영향을 미치고, 어떠한 크기의 타원형을 그릴 수 있습니다. 명백하게, 당신은 항상 뷰의 바운드를 매개변수 값으로 사용할 필요는 없습니다. 뷰의 일부분의 프레임을 제공할 수 있습니다.&lt;/p&gt;
&lt;p&gt;흥미로운 경우는 타원형을 원형으로 바꾸는 방법에 대한 것입니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;원 만드는 코드 작성하기. &lt;code&gt;UIBezierPath(ovalIn:)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;새로운 타원형의 너비와 높이가 같아졌고 (이 경우에 뷰의 높이와 같음), 이것은 형태를 원의 형태로 만들어 줍니다. 또한, 원의 중점이 뷰의 중점과 갖다는 것을 주목할 알아두십시오.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;둥근 모서리가 있는 직사각형&lt;/h2&gt;
&lt;p&gt;모든 iOS 개발자가 알고 있는 가장 기본적인 것 중 하나는 다음과 같은 명령을 사용하여 뷰에 둥근 모서리를 적용하는 방법입니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot; lang=&quot;swift&quot;&gt;view.layer.cornerRadius = 15.0
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;그것은 모서리를 둥글게 하는 가장 쉬운 방법이지만, 불운하게도 뷰의 최상단에 베지어 경로를 만들었다면 아무런 효과도 일어나지 않을 것입니다. 그러나 그 해결책이 있습니다. 필요한 모든 것은 아래와 같이 둥근 직사각형처럼 경로를 만드는 것입니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;둥근 모서리를 갖는 경로 만드는 코드 작성하기. &lt;code&gt;UIBezierPath(roundedRect:cornerRadius:)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;위의 생성자는 새로운 직사각형 경로를 만들고, 그것은 두 번째 매개변수에 특정한 값에 따라 모서리를 둥글게 합니다.&lt;/p&gt;
&lt;p&gt;우리가 지금 본 것은 유용하지만, 단지 직사각형의 모서리 중 몇 개만 둥글게 하고 싶어 할 때는 흥미롭지 않습니다. 종종 하나 또는 그 이상, 하지만 전체는 아닌 모서리가 둥글게 되어 있는 사용자 정의 뷰를 만드는 것을 요구받을 때가 있고, 베지어 경로는 이 일을 쉽게 하기 위해 여기에 있습니다. 오직 뷰의 좌측 상단과 우측 하단 모서리만 둥글게 하는 방법을 보기 위해 예제를 사용합시다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;몇 개의 모서리만 둥글게 하는 경로를 만드는 코드 작성하기. &lt;code&gt;UIBezierPath(roundedRect:byRoundingCorners:cornerRadii)&lt;/code&gt; (radii는 radius의 복수명사)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;이 새로운 생성자는 세 개의 매개변수를 받습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;만들어질 직사각형의 프레임&lt;/li&gt;
&lt;li&gt;둥글게 될 모서리. 하나의 모서리만 원한다면, 배열을 정의하는 문법을 사용할 필요는 없습니다. 하지만 더 많은 것을 원한다면, 위와 같이 하는 것을 필요로 합니다. 이 매개변수에서 주어진 값은 &lt;code&gt;UIRectCorner&lt;/code&gt; 구조체의 프로퍼티들이며, &lt;a href=&quot;https://developer.apple.com/documentation/uikit/uirectcorner&quot;&gt;여기&lt;/a&gt;에서 더 많은 정보를 찾을 수 있습니다.&lt;/li&gt;
&lt;li&gt;모서리 반지름 값. 이 매개변수는 &lt;code&gt;CGSize&lt;/code&gt; 값을 기대하지만 사실은 너비만 고려됩니다. 높이는 무시됩니다.&lt;/li&gt;

&lt;/ol&gt;
&lt;p&gt;나쁘지 않습니다. 우리는 단지 객체를 생성하였고 일부 모서리만을 둥글게 했습니다!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;호(Arc) 만들기&lt;/h2&gt;
&lt;p&gt;많은 개발자들에게, 호 형태의 베지어 경로를 만드는 것은 지금까지 만나왔던 이전의 다른 경우들보다 훨씬 복잡해 보일 것입니다. 그리고 맞습니다. 그것은 훨씬 복잡합니다. 당신이 이것이 어떻게 작동하는지 이해하지 않는다면 말이죠! 나를 믿으십시오. 쉽습니다.&lt;/p&gt;
&lt;p&gt;먼저 예제를 봅시다. 그러면 단계적으로 모든 것들을 해나갈 수 있습니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;호를 그리는 코드 작성하기. &lt;code&gt;UIBezierPath(arcCenter:radius:startAngle:endAngle:clockwise)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;하나씩 매개변수 목록을 살펴봅시다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;arcCenter&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;호는 항상 원의 일부분입니다. 그러므로 원의 없어진 부분을 시각화하고 그것을 당신의 마음 속에서 완전히 그린다면, 그것의 중점을 볼 수 있을 것입니다. 상상 속 원의 중점은 또한 호의 중점입니다. 위의 예제에서 우리는 상상 속 원이 뷰의 프레임 안에 포함되는 것을 원하고, 그것의 중점은 또한 뷰의 중점이 되어야 합니다. 매개변수 값은 항상 &lt;code&gt;CGPoint&lt;/code&gt; 값이어야 합니다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;radius&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;원의 반지름입니다. 상상 속 원의 지름이 뷰의 높이와 같기 대문에, 그것의 절반이 반지름입니다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;startAngle&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;이것은 당신이 그리고 있는 호의 '시작점'을 의미합니다. 우리는 이것과 다음에 나올 &lt;code&gt;endAngle&lt;/code&gt; 매개변수에 대해 더 자세하게 알아볼 것이지만, 지금은 단순히 호가 시작하는 상상 속 원의 둘레 위의 포인트라고 생각하십시오. 기대되는 값은 라디안(호도법)으로 표현되는 각도이며, 육십분법으로 표현되는 각도가 아닙니다. 나중에 더 자세하게 설명할 것이고, 특히 위의 코드에서 보는 것에 대해 더 설명할 것입니다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;endAngle&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;그려지는 호의 '끝점'을 의미합니다. &lt;code&gt;startAngle&lt;/code&gt; 에서 말했던 것과 비슷하게, 호가 끝나는 상상 속 원의 둘레 위에 있는 포인트라고 생각하십시오.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;clockWise&lt;/code&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;호가 시계 방향으로 그려지는지, 아니면 그 반대 방향인지 알리는 불리언 값입니다. 이것과 이전 두 개의 매개변수의 적절한 조합이 당신의 그리기 원하는 적절한 원으로 이끌 것입니다.&lt;/li&gt;

&lt;/ul&gt;
&lt;/li&gt;

&lt;/ol&gt;
&lt;p&gt;이제 &lt;code&gt;startAngle&lt;/code&gt; 과 &lt;code&gt;endAngle&lt;/code&gt; 값에 대해 조금 더 자세하게 이야기해 봅시다. 호의 시작점과 끝점을 각각 어떻게 표현하는지 적절하게 이해하기 위해, 당신이 학교 다닐 적의 수학과 책에서의 원의 각도를 기억해 봅시다.&lt;/p&gt;
&lt;p&gt;당신의 젊을 적을 회상하면서, 위의 이미지를 보고 있을 것입니다. 원은 0도에서 시작하고, 360도를 만들고 완벽한 형태를 만들 때까지 반시계방향을 따라갑니다. 우리가 위에서 보는 것에 기초하여, 호를 그리는 것은 어렵지 않습니다. 어떤 A도에서 시작하여, B도로 간 후, 끝납니다. 동의하나요? 나도 그렇습니다. 하지만 당신이 쉽게 호를 그릴 수 있는 비밀이 있습니다. 모든 것을 잊어버리세요!&lt;/p&gt;
&lt;p&gt;iOS에서 많은 것들은 일반적인 수학에서 우리가 아는 것과 비교했을 때 정반대로 되어 있습니다. 좌표계를 예로 들어봅시다. iOS에서 수직 아래로 향할 때 Y값이 증가하는 반면에, 데카르트 좌표계에서는 감소합니다. 같은 일이 위에서 보는 원의 각도에서도 일어납니다. iOS에서 원은 0도에서 시작하지만, 360도를 그릴 때까지 시계 방향으로 움직인다는 것을 고려해야 합니다.&lt;/p&gt;
&lt;p&gt;이미지를 보면서, 우리의 예제에서 호가 180도에서 시작하여 0도에서 끝난 후 시계 방향으로 따라갔음을 고려한다면, 마지막 스크린샷에 만들어진 호가 어떻게 만들어졌는지는 명백해집니다.&lt;/p&gt;
&lt;p&gt;더욱 명백하게 하기 위해, 다음의 호를 만들어 보세요. (왼쪽 반원)&lt;/p&gt;
&lt;p&gt;이것을 성취하기 위한 두 가지 방법이 있습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;위에 보여지는 원의 각도에 의하여 90도에서 시작하여 270도로, 시계 방향으로 가는 것&lt;/li&gt;
&lt;li&gt;또는 270도에서 시작하여 90도로 가고, 반시계 방향으로 따라가는 것&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;두 번째 경우를 선택하여, 반시계 방향으로 움직여 봅시다.&lt;/p&gt;
&lt;p&gt;마지막 예는 이를 완전히 이해했는지 확인하는 것입니다. (반원에서 조금 더 차 있는 모양)&lt;/p&gt;
&lt;p&gt;그리고 시작 각도와 끝 각도에 대해 몇 마디 더 하겠습니다. 우리 모드는 각도가 육십분법(각도) 또는 호도법(라디안)으로 표현되는 것을 알고 있습니다. 위의 생성자에 있는 두 개의 매개변수는 각각 라디안 값을 기대하지만, 사람은 육십분법을 생각해내는 것이 더 쉽습니다. 이러한 이유로, 각도를 라디안으로 바꾸는 것을 행하는 &lt;code&gt;CGFloat&lt;/code&gt; 익스텐션을 제공하고, 마지막 세 개의 예제에서 사용할 것입니다.&lt;/p&gt;
&lt;p&gt;이 익스텐션으로, 육십분법으로 나타내어진 각도를 표현하는 어떠한 &lt;code&gt;CGFloat&lt;/code&gt; 숫자를 각각 라디안 값으로 쉽게 바꿀 수 있는데, 이전 예제의 시작 각도와 끝 각도 매개변수 값에서 보여지는 것과 비슷합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;베지어 경로와 &lt;code&gt;CAShapeLayer&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;이전의 예제에서 봤듯이, &lt;code&gt;UIView&lt;/code&gt; 의 서브클래스에 있는 &lt;code&gt;draw(_:)&lt;/code&gt; 메소드는 그려질 베지어 경로를 위한 컨텍스트를 제공합니다. 그러나, 사용자 정의 그림을 그리는 것을 수행할 때 그 메소드를 항상 재정의해야하는 것은 아니며, 사실 가능하면 그것을 피해야 하는데, 성능에 영향을 줄 수 있기 때문입니다. 좋은 대안은 &lt;code&gt;CAShapeLayer&lt;/code&gt; 객체를 사용하는 것인데, 그것들을 사용함으로써 훨씬 더 빠르게 렌더링되고 부가적인 유연함을 얻을 수 있습니다.&lt;/p&gt;
&lt;p&gt;이 포스트의 시작에서 말했듯이, &lt;code&gt;CAShapeLayer&lt;/code&gt; 는 &lt;code&gt;CALayer&lt;/code&gt; 의 서브클래스이고, 이러한 객체를 만들고 사용함으로써 우리는 실제로 뷰에 여분의 레이어를 추가합니다. 그것은 뷰의 최종 결과를 사용자 정의하는 데 사용 가능한 몇 가지 프로퍼티들을 가지고 있으며, 대부분은 애니메이션이 가능한데, 이것은 그 값들이 &lt;code&gt;CABasicAnimation&lt;/code&gt; 과 같은 애니메이션을 줄 수 있는 방법을 사용하여 변화될 수 있다는 것을 의미합니다. 애니메이션은 레이어에서 큰 챕터로 구성되어 있고, 이 포스트에서는 확인하지 않을 것입니다. 아마 어떠한 시점에서 다른 튜토리얼로 구성될 것입니다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CAShapeLayer&lt;/code&gt; 객체를 만들 때, 그것의 형태를 명시하거나, 다른 말로 경로를 명시하는 것은 필수적입니다. 경로를 설정하는 가장 쉬운 방법은 베지어 경로를 먼저 만들고, 그 다음에 그것을 형태 레이어 객체에 할당하는 것입니다. 이것이 가장 일반적인 접근법이기 때문에, 다음의 예제에서 이것을 사용해 볼 것입니다.&lt;/p&gt;
&lt;p&gt;경로를 명시하는 것 이외에, 설정 가능한 다른 프로퍼티들이 있고, 종종 이것들 또한 설정되어야 합니다. 예를 들어, 배경색, 테두리색, 선 굵기, 그리고 위치가 그러한 것들 중에 있으며, 우리는 그 모든 것들이 활동중임을 알게 될 것입니다. 또한, 형태 레이어 객체가 뷰의 레이어에서 사용될 수 있는 두 가지 방법이 있습니다. 서브레이어로서, 또는 마스크로서 그렇습니다. 잠시 후 그것들의 차이를 알아볼 것입니다. 마지막으로, 다중 형태 레이어들은 레이어에 서브레이어로 만들어지고 추가될 수 있습니다. 그러나, 최상단의 대부분의 레이어들이 그들 아래에 있는 것들을 덮기 때문에, 조심스럽게 크기와 위치를 설정해야 합니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;간단한 &lt;code&gt;CAShapeLayer&lt;/code&gt; 객체&lt;/h2&gt;
&lt;p&gt;우리의 첫 번째 &lt;code&gt;CAShapeLayer&lt;/code&gt; 객체를 만들어 봅시다. 하지만 그 전에, &lt;code&gt;draw(_:)&lt;/code&gt; 메소드에서 사용했던 모든 코드를 주석처리 해야 합니다. 우리가 할 수 있는 가장 간단한 것은 이것입니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;CAShapeLayer&lt;/code&gt; 를 만들어 뷰 레이어의 서브레이어로 추가하는 코드 작성하기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;제일 먼저, 직사각형 베지어 경로를 그리기 위해 이전 파트에서 구현한 &lt;code&gt;createRectangle()&lt;/code&gt; 메소드를 호출합니다. 이 메소드에 명시된 경로는 우리 클래스의 &lt;code&gt;path&lt;/code&gt; 프로퍼티로부터 오는 것을 기억하세요.&lt;/p&gt;
&lt;p&gt;다음으로, 형태 레이어 객체를 만드는데, 위에 표시된 것처럼 항상 쉽습니다. 먼저 객체를 생성하고, 베지어 경로를 그것의 &lt;code&gt;path&lt;/code&gt; 프로퍼티에 할당합니다. 하지만 이 프로퍼티가 &lt;code&gt;CGPath&lt;/code&gt; 값을 기대하는 반면에 우리의 &lt;code&gt;path&lt;/code&gt; 는 &lt;code&gt;UIBezierPath&lt;/code&gt; 객체임을 알아두세요. 그러므로 단지 &lt;code&gt;cgPath&lt;/code&gt; 프로퍼티에 접근하는 것으로 그것의 Core Graphics 표현을 사용합니다.&lt;/p&gt;
&lt;p&gt;마지막으로, 뷰의 레이어에 서브레이어로 추가합니다. 참고로 이것이 서브레이어를 추가하는 가장 일반적인 방법임에도 불구하고, 그러한 많은 것들을 가지고 있는 경우에 &lt;code&gt;CALayer&lt;/code&gt; 클래스가 제공하는 다음의 메소드들을 사용할 수 있습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-swift&quot; lang=&quot;swift&quot;&gt;insertSublayer(_:at:)
insertSublayer(_:above:)
insertSublayer(_:below:)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.apple.com/documentation/quartzcore/calayer/1410944-insertsublayer&quot;&gt;여기&lt;/a&gt;, &lt;a href=&quot;https://developer.apple.com/documentation/quartzcore/calayer/1410798-insertsublayer&quot;&gt;여기&lt;/a&gt;, &lt;a href=&quot;https://developer.apple.com/documentation/quartzcore/calayer/1410840-insertsublayer&quot;&gt;여기&lt;/a&gt;에서 각각 더 많은 것을 읽어보세요.&lt;/p&gt;
&lt;p&gt;이제 이 메소드를 호출하고 결과를 확인하기 위해 애플리케이션을 실행해 보세요.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;init(frame:)&lt;/code&gt; 에서 &lt;code&gt;simpleShapeLayer()&lt;/code&gt; 호출하기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;우리가 형태 레이어를 위한 배경색을 명시하지 않았다면, 검정색이 기본값으로 사용된 것을 확인 할 수 있을 것입니다. 이제 값을 설정하고, 더 많은 프로퍼티와 함께 놀아봅시다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;fillColor&lt;/code&gt; 프로퍼티와 &lt;code&gt;strokeColor&lt;/code&gt; 프로퍼티는 &lt;code&gt;CGColor&lt;/code&gt; 값을 기대하고 있고, 이것이 우리가 &lt;code&gt;UIColor&lt;/code&gt; 객체를 &lt;code&gt;cgColor&lt;/code&gt; 프로퍼티에 접근하여 &lt;code&gt;CGColor&lt;/code&gt; 로 변환해야 하는 이유입니다. &lt;code&gt;lineWidth&lt;/code&gt; 프로퍼티를 사용하여 경계선의 두께를 특정할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;마스크 또는 서브레이어?&lt;/h2&gt;
&lt;p&gt;형태 레이어는 두 가지의 다른 방법으로 사용될 수 있습니다. 뷰의 기본 레이어에 마스크로서, 또는 위에서 했던 것처럼 그것의 서브레이어로서 추가되는 방법이 있습니다. 하지만 이 두 개의 방법 사이의 진짜 차이는 무엇일까요? 그리고 무엇을 사용할 지 어떻게 결정할 수 있을까요?&lt;/p&gt;
&lt;p&gt;다시 한번 예제로 갑시다. 새로운 메소드가 있음을 알아챘을 것입니다.&lt;/p&gt;
&lt;p&gt;다시 한번 이전에 만든 &lt;code&gt;createTriangle()&lt;/code&gt; 메소드를 사용하고 있으며, 그 지점에 머무를 수 있습니다. 그 메소드는 삼각형의 경로를 만드는 경로를 그리고, 그것을 사용하기 위해 새로운 형태 레이어 객체를 생성합니다. 배경색을 명시해 주었고, 뷰의 기본 레이어에 서브레이어로 추가했습니다. 어려운 것도 없고, 새로운 것도 없습니다.&lt;/p&gt;
&lt;p&gt;이 새로운 메소드를 호출합시다. 그리고 예상했던 것보다 훨씬 더 아름다운 결과를 확인하세요.&lt;/p&gt;
&lt;p&gt;명백하게, 우리의 새로운 형태 레이어는 뷰의 최상단에 자리하고 있는 멋있는 노란색 삼각형이고, 배경색으로 커버되지 않는 부분은 어두운 회색으로 남아 있습니다.&lt;/p&gt;
&lt;p&gt;메소드에 다음과 같은 변화를 줘 봅시다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;self.layer.addSublayer(shapeLayer)&lt;/code&gt; -&amp;gt; &lt;code&gt;self.layer.mask = shapeLayer&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;code&gt;addSubLayer(_:)&lt;/code&gt; 메소드를 주석처리하고, 대신 &lt;code&gt;mask&lt;/code&gt; 프로퍼티를 사용하세요. &lt;/p&gt;
&lt;p&gt;이번에는 삼각형 모양의 형태만 있을 뿐이고, 배경색을 지정해 주었으나 더이상 노란색은 보이지 않습니다. 심지어 형태 레이어의 경로가 커버하지 못하는 뷰의 부분은 사라졌습니다!&lt;/p&gt;
&lt;p&gt;음, 이것이 마스크가 동작하는 방법입니다. 경로의 부분이 아닌 뷰의 부분은 잘려나가고, 실제로 뷰는 마스크로서 적용된 형태 레이어의 형태를 취합니다. 게다가, 배경색과 같은 프로퍼티는 새로운 레이어가 마스크일 때 아무런 효과도 내지 못합니다. 그러므로 삼각형의 색을 바꾸고 싶다면, 뷰의 배경색을 갱신할 필요가 있습니다.&lt;/p&gt;
&lt;p&gt;말하자면, 뷰에 사용자 정의 형태를 주고 싶다면 &lt;code&gt;mask&lt;/code&gt; 프로퍼티를 사용하고, 그렇지 않다면 당신이 만든 새로운 형태 레이어를 서브레이어로 추가하고 최종 목적을 달성하기 위해 뷰와 레이어의 프로퍼티들을 조작하세요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;단 하나의 서브레이어가 아니다&lt;/h2&gt;
&lt;p&gt;나는 이미 당신이 분명히 뷰의 레이어에 서브레이어로 하나 이상의 형태 레이어를 추가할 수 있다고 말했습니다. 그러므로 그것에 대해 더 많은 것을 알아볼 것입니다. 이 파트에서, 두 개의 서브레이어를 만들고 그것들의 몇몇 프로퍼티를 바꾼 후, 뷰에 적절하게 표시할 것입니다. 시작하는 사람을 위해, 두 개의 경로와 두 개의 형태를 만듭시다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;두 개의 &lt;code&gt;UIBezierPath&lt;/code&gt; 인스턴스와 두 개의 &lt;code&gt;CAShapeLayer&lt;/code&gt; 인스턴스 만들기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;위의 코드는 삼각형 형태에 해당하는 두 개의 경로를 만드는데, 첫 번째는 코를 든 모양이고, 두 번째는 코를 내린 모양입니다. 이번에 우리는 경로와 형태에 뷰의 전체 너비와 높이를 사용하지 않습니다. 그것들의 절반만을 사용합니다. 일단 두 가지 경로가 특정되면, 두 개의 형태 레이어 객체에 할당되고, 뷰의 레이어에 서브레이어로 차례로 추가될 것입니다.&lt;/p&gt;
&lt;p&gt;이 새로운 메소드를 호출합시다.&lt;/p&gt;
&lt;p&gt;보다시피 두 번째 형태 레이어가 첫 번째 것을 포개고 있습니다. 그리고 올바르게 보이지 않습니다. 그것을 움직여보는 건 어떨까요?&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;두 번째 레이어의 위치를 아래로 내리기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;좀 더 낫네요! 방금 사용한 &lt;code&gt;position&lt;/code&gt; 프로퍼티는 정말로 중요한데, 형태 레이어를 움직이게 허용해주기 때문입니다. 그리고 두 개의 레이어를 중앙에 두고 싶다면 어떻게 할까요? 다음의 두 줄로 코드를 교체하면 됩니다.&lt;/p&gt;
&lt;p&gt;대부분의 경우 &lt;code&gt;position&lt;/code&gt; 프로퍼티는 형태 레이어를 다른 위치에 두는 데 적합한 프로퍼티입니다. 그러나 레이어의 프레임을 바꾸기를 원하는 때도 있을 것입니다. 그러한 경우에는, 가슴 속에 새겨두세요. &lt;code&gt;frame&lt;/code&gt; 프로퍼티에 접근해서는 안됩니다. 대신에 서브레이어의 &lt;code&gt;bounds&lt;/code&gt; 프로퍼티에 접근하세요.&lt;/p&gt;
&lt;p&gt;문서에 따르면, &lt;code&gt;bounds&lt;/code&gt; 프로퍼티는 그 자신의 좌표계에서 서브레이어의 기원&lt;em&gt;origin&lt;/em&gt; 과 크기&lt;em&gt;size&lt;/em&gt; 를 표현합니다. 이것이 의미하는 것을 이해하고 직사각형의 바운드의 기원과 크기를 어떻게 바꾸는지 보기 위해 예제에서 약간의 변화를 줘봅시다.&lt;/p&gt;
&lt;p&gt;위의 추가로 서브레이어의 기본 크기를 변화시켰고, 명백하게 뷰의 볼 수 있는 공간을 초과하고 있습니다. 그려진 경로의 크기는 그것에 의해 영향을 받지 않지만, 기원을 변경한다면 경로는 움직일 것입니다.&lt;/p&gt;
&lt;p&gt;중요한 것을 알아채세요. 일반적인 뷰의 좌표계에서 오리진 포인트의 X값을 증가시켜 뷰를 오른쪽으로 이동시키고, Y값을 증가시켜 아래로 이동시킨 것과는 다르게, 여기서는 정반대로 일어납니다. 우리는 음수값을 주어서 경로를 오른쪽 그리고 아래쪽으로 이동시켰습니다. 양수값은 경로의 오리진을 각각 왼쪽과 위쪽으로 옮길 것입니다. 그러나, 대부분의 경우 당신은 단지 레이어의 위치를 다시 설정할 필요가 있을 것이고, 아마 &lt;code&gt;bounds&lt;/code&gt; 를 사용하는 일은 드물 것입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;경로 혼합하기&lt;/h2&gt;
&lt;p&gt;이 포스트에서 경로에 대해 논의하기 시작했을 때, &lt;code&gt;UIBezierPath&lt;/code&gt; 클래스가 제공하는 일련의 생성자들을 훑었고, 몇 가지 종류의 형태는 단지 이러한 생성자를 사용해서 만들 수 있음을 알았습니다. 그러나, 다양한 경로 타입이 함께 섞인 것은 확인하지 못했고, 이제는 도형 레이어에 이야기하기 가장 좋은 때입니다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;addLine(to:)&lt;/code&gt; 메소드가 두 포인트 사이에 선을 만드는 것을 이미 알고 있는 것과 비슷하게, 호와 곡선 같은 다른 종류의 형태를 만드는 메소드들이 있습니다.&lt;/p&gt;
&lt;p&gt;다음의 예제로 살펴보세요.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;복잡한 뷰를 그리는 코드 작성하기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;첫번째로, 코드에서 우리는 형태 레이어를 서브레이어가 아닌 마스크로 사용하였음을 알아두세요. 일부러 그렇게 했는데, 단지 최종 형태를 강조하고 싶었기 때문입니다. 그러나, 중요한 것은 경로를 만드는 것입니다. 보다시피 몇 가지 선, 호, 곡선의 조합으로 이루어져 있습니다. 좌측 상단(0.0, 0.0)에서 그리기를 시작하고, 시계 방향으로 그리기를 이어나갑니다. 경로가 단계적으로 어떻게 그려지는지 알기 위해 조심스럽게 주어진 포인트들을 살피세요.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;addCurve&lt;/code&gt; 메소드는 새로 나왔는데, 이것은 형태의 오른쪽에 보이는 곡선을 만듭니다. 곡선은 다음과 같은 것입니다.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;베지어 곡선과 컨트롤 포인트. 참고 링크들 참고하기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;위처럼 선을 그리는 메소드는 세 개의 매개변수: 곡선의 최종 포인트(끝점), 실제로 선의 곡률을 정의하는 두 개의 컨트롤 포인트를 기대합니다. 당신이 그것을 수정할 때 곡선이 어떻게 행동하는지 보기 위해 이 컨트롤 포인트의 값을 변경해 보세요. 그럼에도 불구하고, 불편한 진실이 있는데, 곡선 뒤편에 많은 수학적 거짓이 들어 있습니다.&lt;/p&gt;
&lt;p&gt;경로의 초반에 만든 호에 관해서는, 새롭거나 어려운 것이 없어 언급할 거리가 없습니다. 호를 그리는 것에 대해 말한 것만 기억하세요. 그러면 당신은 우리가 책에 의해서 레시피를 따라갔다는 것을 알게 될 것입니다. 나머지도 우리가 아는 것들입니다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;보너스 : &lt;code&gt;CATextLayer&lt;/code&gt; 사용하기&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;CATextLayer&lt;/code&gt; 클래스는 이러한 역할을 하는 클래스 중에서도 덜 알려지거나 사용 빈도가 낮은 것 중 하나입니다. 그것의 목적은 어떠한 텍스트를 표시하는 &lt;code&gt;CAShapeLayer&lt;/code&gt; 와 같은 레이어를 만드는 것입니다. 그리고 이 클래스가 베지어 경로나 형태와 함께 하는 일이 없다고 할지라도, 나는 그것을 이 포스트에서 보여주기를 정말로 원합니다. 그래서 여기에서 읽을만한 추가적인 것으로 제공할 것입니다. 이 부분은 이 포스트에서의 작은 삽입 어구로 생각하세요.&lt;/p&gt;
&lt;p&gt;모든 개발자들은 인터페이스에서 99%의 경우에 &lt;code&gt;UILabel&lt;/code&gt; 객체를 사용하여 텍스트를 표시합니다. 수정될 수 없는 텍스트에 대해서 말이죠. 하지만 때때로 레이블을 사용하는 것은 잘 작동하지 않거나, 레이블을 포함하는 뷰의 레이어에 많은 서브레이어가 추가되는 경우 난잡해보일 수도 있습니다. 이러한 경우에, &lt;code&gt;CATextLayer&lt;/code&gt; 가 당신이 정말로 필요로 하는 것입니다 이것의 추가적인 이점은 어떠한 뷰라도 최상단에 텍스트 레이어를 추가하는 것이므로, 단지 레이블에 의존하지 않아도 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;CATextLayer&lt;/code&gt; 를 만들고 사용하는 것은 텍스트가 표시되기 원하는 방법대로 프로퍼티들을 설정하는 문제만 있을 뿐입니다. 다음의 코드 스니펫은 우리 뷰의 기본 레이어의 서브레이어로 추가되는 텍스트 레이어 같은 것을 만듭니다. &lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;code&gt;CATextLayer&lt;/code&gt; 만드는 코드 작성하기&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;몇 가지 알아둘 것이 있습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;textLayer&lt;/code&gt; 객체의 &lt;code&gt;string&lt;/code&gt; 프로퍼티를 사용하여 우리가 표시하기 원하는 텍스트를 설정합니다.&lt;/li&gt;
&lt;li&gt;이름과 크기를 제공하여 폰트를 특정할지라도, 폰트 크기를 특정하기 위해 &lt;code&gt;fontSize&lt;/code&gt; 프로퍼티를 사용하는 것 또한 필수적입니다. 폰트 생성에서 주어진 크기는 중요하지 않아 보입니다.&lt;/li&gt;
&lt;li&gt;텍스트 정렬은 &lt;code&gt;textAlignmentMode&lt;/code&gt; 프로퍼티를 사용하여 설정 가능합니다. 당신이 설정할 수 있는 특정한 값들이 있고, &lt;code&gt;kCAAlignmnetCenter&lt;/code&gt; 를 사용하여 텍스트를 중앙 정렬시킬 수 있습니다. &lt;a href=&quot;https://developer.apple.com/reference/quartzcore/catextlayer/horizontal_alignment_modes&quot;&gt;여기&lt;/a&gt;에서 더 많은 값들을 확인하세요.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UILabel&lt;/code&gt; 객체에서 일어나는 것처럼, 라인 수를 설정할 수 있는 선택지는 여기에는 없습니다. 대신에, &lt;code&gt;\n&lt;/code&gt; 문자를 사용하여 텍스트를 여러 줄로 분리할 수 있습니다. 또한, 텍스트가 적절하게 레이어의 안에 들어갈 수 있도록 레이어의 프레임을 적절하게 설정하는 것을 염두해 두세요.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;항상 &lt;code&gt;contentScale&lt;/code&gt; 프로퍼티를 사용하세요.&lt;/strong&gt; 그래야 스케일 값을 고려하여 화면에 텍스트가 올바르게 그려질 수 있습니다. 사용하지 않으면, 결과는 픽셀화됩니다.&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;더 많은 정보는 &lt;a href=&quot;https://developer.apple.com/documentation/quartzcore/catextlayer&quot;&gt;공식 문서&lt;/a&gt;에서 확인하세요.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;요약&lt;/h2&gt;
&lt;p&gt;이 포스트의 끝에서, 나는 이번 파트들에 있는 컨텐츠가 모두에게 유용하고 교육적이었으면 좋겠습니다. 여기서 만난 기초들을 바탕으로, 사용자 정의 뷰나 사용자 정의 형태 레이어와 함께 복잡한 경로를 조합하는 진보된 경우에 대해서 더 나아갈 수 있을 것입니다. 사실, 여기서 배운 것을 사용하는 것은 당신에게 달려 있습니다. 하지만 이제 지식의 이점을 살리고 마법을 부릴 때가 되었습니다!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;참고 링크&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://www.appcoda.com/bezier-paths-introduction/&quot;&gt;A Beginner's Guide to Bezier Paths and Shape Layers&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://blog.coderifleman.com/2016/12/30/bezier-curves/&quot;&gt;중학생도 알 수 있는 베지어 곡선&lt;/a&gt;&lt;/p&gt;


&lt;/article&gt;</description>
      <category>iOS</category>
      <author>할루루</author>
      <guid isPermaLink="true">https://gorani95.tistory.com/257</guid>
      <comments>https://gorani95.tistory.com/257#entry257comment</comments>
      <pubDate>Tue, 11 Sep 2018 14:16:02 +0900</pubDate>
    </item>
    <item>
      <title>KVO (Key-Value Observing)</title>
      <link>https://gorani95.tistory.com/256</link>
      <description>&lt;article class=&quot;markdown-body&quot;&gt;
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset='UTF-8'&gt;&lt;meta name='viewport' content='width=device-width initial-scale=1'&gt;
&lt;title&gt;KVO&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;&lt;h1&gt;시작&lt;/h1&gt;
&lt;p&gt;야곰의 Swift 4 책의 키패스 부분을 보다가 짜증나서 그냥 넘겼던 기억이 있는데, 이제는 이해할 수 있고, KVO에 대해서도 말만 들어봤지 공부는 안해봤는데 슬슬 해야겠다는 생각이 들었다.&lt;/p&gt;
&lt;p&gt;사실 &lt;em&gt;RespectU&lt;/em&gt; 서버와 그에 따른 클라이언트 코드 수정에 생각보다 너무 많이 애를 먹어서 살짝 추진력이 떨어졌는데, 갑자기 KVO가 생각나서 공부한 것을 정리해둔다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;KeyPath&lt;/h1&gt;
&lt;p&gt;먼저 키패스에 대해서 알아보고 가자.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;&lt;strong&gt;키패스&lt;/strong&gt;는 어떤 객체의 프로퍼티 혹은 프로퍼티의 프로퍼티 체인에 대해서 그 이름을 통해서 값을 찾아나가는 표현을 말한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;기본적으로 Objective-C 쪽에서 사용해온 기능인 것 같고, Swift 초기에는 이것에 대한 기능이 별도로 마련되지 않았다고 한다.&lt;/p&gt;
&lt;p&gt;문자열을 사용하여 &lt;code&gt;NSObject&lt;/code&gt; 의 &lt;code&gt;value(forKey:)&lt;/code&gt; 또는 &lt;code&gt;setValue(_:forKey:)&lt;/code&gt; 를 사용할 수도 있다.&lt;/p&gt;
&lt;p&gt;하지만 문자열을 통해서 키패스를 사용하므로 오타 가능성이 있고, 오타에 의한 존재하지 않는 키패스를 참조하는 것을 확인할 방법이 없어 디버깅이 곤란한 부분이 있다. 또한 이렇게 가져온 데이터는 &lt;code&gt;Any&lt;/code&gt; 로 오고, &lt;code&gt;NSObject&lt;/code&gt; 를 상속받아야 기능을 사용할 수 있는 등 여러모로 좋지 않았다.&lt;/p&gt;
&lt;p&gt;Swift 4 에서 이러한 단점을 보완하기 위해 모든 Swift 타입에서 키패스를 통해 프로퍼티를 참조할 수 있는 범용적인 키패스 문법과 키패스를 위한 코어 타입이 추가되었다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;class Struct {
    var a: Int = 3
    var b: Int = 4
}
let object = Struct()
let keyPath = \Struct.a
print(object[keyPath: keyPath])	//3
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;&lt;p&gt;모든 Swift 타입에서 키패스를 통해 프로퍼티를 참조할 수 있는 키패스 문법이 추가되었다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;키패스는 &lt;code&gt;\&lt;/code&gt; 로 시작하고, &lt;strong&gt;타입 이름&lt;/strong&gt;을 쓴 후 &lt;code&gt;.&lt;/code&gt; 를 통해 &lt;strong&gt;프로퍼티에 접근&lt;/strong&gt;하면 된다.&lt;/p&gt;
&lt;p&gt;타입이 모호하지 않은 경우 바로 &lt;code&gt;.&lt;/code&gt; 로 시작할 수 있다. (&lt;code&gt;\Struct.a&lt;/code&gt; / &lt;code&gt;\.a&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;옵셔널의 경우 &lt;code&gt;?&lt;/code&gt; 를 붙여서 접근한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;Key-Value Observing&lt;/h1&gt;
&lt;p&gt;키패스를 알아보았으니 키-밸류 옵저빙을 알아볼 때가 되었다.&lt;/p&gt;
&lt;p&gt;Swift의 프로퍼티 감시자 (&lt;code&gt;willSet&lt;/code&gt; , &lt;code&gt;didSet&lt;/code&gt;) 과 비슷하지만, KVO는 타입이 정의된 곳 바깥에서 옵저버를 추가할 수 있다는 차이점이 있다.&lt;/p&gt;
&lt;p&gt;기본적으로 순수한 Swift 로는 작성할 수 없다. Objective-C 런타임에 의존하기 때문에, &lt;code&gt;NSObject&lt;/code&gt; 를 상속받는 클래스에서 &lt;code&gt;@objc dynamic&lt;/code&gt; 을 함께 작성하여 프로퍼티를 선언해야 한다.&lt;/p&gt;
&lt;pre&gt;&lt;code class='language-swift' lang='swift'&gt;class Class: NSObject {
    @objc dynamic var value: String = &amp;quot;안녕&amp;quot;
}
let object = Class()
object.observe(\Class.value) { (object, change) in
    print(&amp;quot;changed!!!&amp;quot;)
}
print(object.value)
object.value = &amp;quot;Wow&amp;quot;
print(object.value)
//안녕
//Wow
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;이런 식이다. 클로저에 프로퍼티 변경에 따른 적절한 처리를 넘겨줄 수 있다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;마무리&lt;/h1&gt;
&lt;p&gt;모델의 역할을 하는 클래스를 &lt;code&gt;NSObject&lt;/code&gt; 를 상속받게 하여, 특정 프로퍼티의 변화에 대응할 수 있도록 할 수 있겠다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Realm&lt;/em&gt; 을 사용할 때도 유용하게 사용될 수 있을 것 같다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;참고한 링크&lt;/h1&gt;
&lt;p&gt;&lt;a href='https://soooprmx.com/archives/9177'&gt;Swift4의 키패스 표현&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href='https://www.hackingwithswift.com/example-code/language/what-is-key-value-observing'&gt;What is key-value observing?&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href='http://seorenn.blogspot.com/2017/07/swift-4-kvo.html'&gt;Swift 4 에서 KVO 사용해보기&lt;/a&gt;&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;/article&gt;</description>
      <category>iOS</category>
      <author>할루루</author>
      <guid isPermaLink="true">https://gorani95.tistory.com/256</guid>
      <comments>https://gorani95.tistory.com/256#entry256comment</comments>
      <pubDate>Wed, 29 Aug 2018 23:02:40 +0900</pubDate>
    </item>
    <item>
      <title>HTTP Status Code</title>
      <link>https://gorani95.tistory.com/255</link>
      <description>&lt;article class=&quot;markdown-body&quot;&gt;



&lt;meta charset=&quot;UTF-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width initial-scale=1&quot;&gt;
&lt;title&gt;HTTP 상태(응답) 코드&lt;/title&gt;
&lt;h3&gt;&lt;a href=&quot;https://www.zerocho.com/category/NodeJS/post/579b4ead062e76a002648af7&quot;&gt;참고 링크 (zerocho.com)&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;1xx&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;정보&lt;/strong&gt;와 관련됨&lt;/p&gt;
&lt;h4&gt;100&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;서버가 요청의 일부를 받았고, 나머지 요청을 기다리고 있는 중&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;101&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;프로토콜 전환이 일어날 때 전환이 승인됨&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h2&gt;2xx&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;성공&lt;/strong&gt;과 관련됨&lt;/p&gt;
&lt;h4&gt;200: OK&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;일반적인 성공&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;201: Created&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;새로운 컨텐츠 만들기를 성공 (새로운 글, 댓글 등)&lt;/li&gt;
&lt;li&gt;POST 메소드에 대한 응답으로 잘 어울림&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;204&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;요청에 성공했으나 응답할 컨텐츠가 없음&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;206&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;요청에 대한 응답으로 일부만 먼저 전송함&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h2&gt;3xx&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;리다이렉션&lt;/strong&gt;과 관련됨&lt;/p&gt;
&lt;h4&gt;301: Moved Permanently&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;주소가 영구적으로 바뀌어 상태 코드와 함께 새로운  주소로 이동시킴&lt;/li&gt;
&lt;li&gt;새로운 주소는 캐싱되므로 속도가 빨라짐&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;302: Found&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;대부분의 리다이렉트에 사용되는 상태 코드&lt;/li&gt;
&lt;li&gt;임시적인 주소 변경에 사용&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;304: Not Modified&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;캐싱된 페이지를 그대로 사용&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;307: Temporary Redirect&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;임시로 페이지를 리다이렉트&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h2&gt;4xx&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;클라이언트 오류&lt;/strong&gt;와 관련됨&lt;/p&gt;
&lt;h4&gt;400: Bad Request&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;서버가 요청을 이해하지 못함&lt;/li&gt;
&lt;li&gt;클라이언트가 올바른 요청을 보냈는지 검사해야 함&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;401&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;접근 권한이 없음&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;403: Forbidden&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;접근이 금지됨&lt;/li&gt;
&lt;li&gt;관리자 페이지&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;404: Not Found&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;찾을 수 없는 페이지&lt;/li&gt;
&lt;li&gt;주소를 잘못 입력한 경우 등&lt;/li&gt;
&lt;li&gt;접근 금지된 페이지에 404 상태 코드를 보내어 중요한 페이지를 없는 페이지로 위장하여 해커의 공격을 예방할 수 있음&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;408&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;요청 시간 초과&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;409&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;서버가 요청을 처리하는 과정에서 충돌 발생&lt;/li&gt;
&lt;li&gt;회원가입 처리 중에 아이디 중복을 발견한 경우 등&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;410&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;영구적으로 사용할 수 없는 페이지&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;451&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;법적으로 접근이 금지된 페이지 표시&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h2&gt;5xx&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;서버 오류&lt;/strong&gt;와 관련됨&lt;/p&gt;
&lt;h4&gt;500: Internal Server Error&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;내부 서버 에러&lt;/li&gt;
&lt;li&gt;서버 관리자가 반드시 살펴보아야 함&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;501&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;서버에 요청을 처리하는 기능을 만들어 두지 않았음&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;502&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;클라이언트에서 온 요청이 중간에 유실됨&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;503: Service Unavailable&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;서버에 과부하가 걸리거나 유지보수중인 상태&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;504&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;서버 게이트웨이에 문제가 생겨 시간 초과&lt;/li&gt;

&lt;/ul&gt;
&lt;h4&gt;505&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;HTTP 버전이 달라 요청을 처리할 수 없음&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;h2&gt;Node.js에서 활용하기&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;res.status(???).json({})&lt;/code&gt; 과 같이 응답해줄 때 적절한 상태 코드와 함께 넘겨주기&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;iOS에서 상태 코드 활용하기&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;URLSession&lt;/em&gt; 을 사용하는 경우&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;dataTask(with:completionHandler:)&lt;/code&gt; 메소드의 컴플리션 핸들러에서 &lt;code&gt;URLResponse&lt;/code&gt; 타입을 갖는 매개변수를 &lt;code&gt;HTTPURLResponse&lt;/code&gt; 타입으로 캐스팅하여 &lt;code&gt;statusCode&lt;/code&gt; 프로퍼티로 접근 가능하다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;HTTPURLResponse&lt;/code&gt; 의 부모 클래스가 &lt;code&gt;URLResponse&lt;/code&gt; 이다.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; lang=&quot;swift&quot;&gt;let session = URLSession(configuration: .default)
let task = session.dataTask(with: url) { data, response, error) in
    if let httpResponse = response as? HTTPURLResponse {
        print(httpResponse.statusCode)
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;

&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;


&lt;/article&gt;</description>
      <category>Node.js</category>
      <author>할루루</author>
      <guid isPermaLink="true">https://gorani95.tistory.com/255</guid>
      <comments>https://gorani95.tistory.com/255#entry255comment</comments>
      <pubDate>Tue, 28 Aug 2018 21:08:38 +0900</pubDate>
    </item>
    <item>
      <title>데이터 넣는 중</title>
      <link>https://gorani95.tistory.com/254</link>
      <description>&lt;article class=&quot;markdown-body&quot;&gt;



&lt;meta charset=&quot;UTF-8&quot;&gt;&lt;meta name=&quot;viewport&quot; content=&quot;width=device-width initial-scale=1&quot;&gt;
&lt;title&gt;데이터넣는중&lt;/title&gt;
&lt;p&gt;기존에는 &lt;em&gt;Realm&lt;/em&gt; 에 저장하기 위해 네이티브 코드를 박아두었다.&lt;/p&gt;
&lt;p&gt;무식한 방법이지만 당시에는 어쩔 수 없었고 지금도 달리 방법이 생각나지 않는다.&lt;/p&gt;
&lt;p&gt;네이티브 코드로만 2000줄이 약간 안된다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/presto95/RespectU_iOS/blob/master/RespectU/Model/Init.swift&quot;&gt;링크&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;이 모든 데이터를 &lt;em&gt;MongoDB&lt;/em&gt; 에 박아넣고 있다.&lt;/p&gt;
&lt;p&gt;이 작업과 간단한 라우팅, 그리고 기존에 말도 안되는 데이터베이스를 정규화하는 과정이 일주일 정도 걸리고 있다.&lt;/p&gt;
&lt;p&gt;그래도 애초에 이렇게 했어야 했는데... 어쩔 수 없지.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;클라이언트에서 서버에서 받아온 데이터를 어떻게 사용할까 고민하고 있는데, 다음과 같다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;매번 서버로부터 요청하여 뿌려준다.&lt;/li&gt;
&lt;li&gt;서버와 클라이언트 데이터를 동기화한다. (서버 버전 변경 시 동기화한다.)&lt;/li&gt;

&lt;/ol&gt;
&lt;p&gt;1번처럼 하면 클라이언트 단에서도 많이 바꾸지 않고 쉽게 가능하겠지만 사실 말이 안된다.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://ios-factor.com/ko/prefer-local-over-remote&quot;&gt;iOS-Factor&lt;/a&gt; 에서도 비슷한 내용을 서술하고 있다.&lt;/p&gt;
&lt;p&gt;2번처럼 하는 것이 맞지만 클라이언트 단의 코드를 많이 바꾸어야할 것 같다. 생각할 것도 1번보다 훨씬 많아진다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;2번처럼 하는 것을 염두에 두고 진행하자.&lt;/p&gt;

&lt;/article&gt;</description>
      <category>Project/Node.js: RespectU (BackEnd)</category>
      <author>할루루</author>
      <guid isPermaLink="true">https://gorani95.tistory.com/254</guid>
      <comments>https://gorani95.tistory.com/254#entry254comment</comments>
      <pubDate>Sun, 26 Aug 2018 23:12:56 +0900</pubDate>
    </item>
    <item>
      <title>UITableViewCell / UICollectionReusableView 의 재사용</title>
      <link>https://gorani95.tistory.com/253</link>
      <description>&lt;article class=&quot;markdown-body&quot;&gt;
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset='UTF-8'&gt;&lt;meta name='viewport' content='width=device-width initial-scale=1'&gt;
&lt;title&gt;prepareForReuse&lt;/title&gt;&lt;/head&gt;
&lt;body&gt;&lt;h2&gt;&lt;code&gt;UITableViewCell&lt;/code&gt; 의 재사용&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;prepareForReuse()&lt;/code&gt;&lt;/h3&gt;
&lt;h4&gt;테이블 뷰의 델리게이트에 의해 재사용을 위한 재사용 가능한 셀을 준비한다&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;UITableViewCell&lt;/code&gt; 객체가 재사용 가능하면, 즉, &lt;em&gt;reuse identifier&lt;/em&gt; 를 가지고 있다면, 이 메소드는 &lt;code&gt;UITableView&lt;/code&gt; 의 &lt;code&gt;dequeueReusableCell(withIdentifier:)&lt;/code&gt; 메소드로부터 객체가 반환되기 직전에 호출된다. 퍼포먼스적 이유로, 알파값, 편집, 선택 상태와 같은 컨텐츠와 관련된 것이 아닌 셀의 속성을 리셋해야만 한다. &lt;code&gt;tableView(_:cellForRowAt:)&lt;/code&gt; 의 테이블 뷰 델리게이트는 &lt;strong&gt;항상&lt;/strong&gt; 셀을 재사용할 때 모든 컨텐츠를 리셋한다. 셀 객체가 관련된 &lt;em&gt;reuse identifier&lt;/em&gt; 를 가지고 있지 않다면, 이 메소드는 호출되지 않는다. 이 메소드를 재정의한다면, 상위 클래스 구현을 호출하는 것을 명확히 해야 한다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;UITableViewCell&lt;/code&gt; 클래스에 정의된 &lt;code&gt;prepareForReuse()&lt;/code&gt; 메소드와 관련된 문서 내용이다.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;reuse identifier&lt;/em&gt; 를 가지고 있다면, 따로 처리를 해주지 않아도 &lt;code&gt;tableView(_:cellForRowAt:)&lt;/code&gt; 에서 셀 재사용 시 모든 컨텐츠를 리셋해주므로 재사용 시 데이터가 개발자가 원치 않는 셀에 표시되는 이슈가 없다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2&gt;&lt;code&gt;UICollectionReusableView&lt;/code&gt; 의 재사용&lt;/h2&gt;
&lt;h3&gt;&lt;code&gt;prepareForReuse()&lt;/code&gt;&lt;/h3&gt;
&lt;h4&gt;뷰를 재사용하기 위해 준비하는 데 필요한 어떤 정리 작업을 수행한다&lt;/h4&gt;
&lt;p&gt;이 메소드의 기본 구현은 아무것도 하지 않는다. 하지만, 이 메소드를 재정의할 때, 아무튼 상위 메소드 구현을 호출하는 것을 추천한다.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;UICollectionViewCell&lt;/code&gt; 과 같은 서브클래스들은 이 메소드를 재정의하고 관련 행동을 수행하기 위해 사용한다. 그러므로 당신의 서브클래스가 &lt;code&gt;UICollectionViewCell&lt;/code&gt; 또는 다른 몇몇 중간 클래스로부터 상속받았다면, &lt;code&gt;super&lt;/code&gt; 를 호출하는 것은 그 클래스가 부모의 행동을 하는 것을 명확하게 한다.&lt;/p&gt;
&lt;p&gt;뷰가 사용을 위해 &lt;em&gt;dequeue&lt;/em&gt; 되었을 때, 이 메소드는 상응하는 &lt;em&gt;dequeue&lt;/em&gt; 메소드가 당신의 코드에서 뷰를 반환하기 전에 호출된다. 서브클래스들은 이 메소드를 재정의하여 프로퍼티들을 기본값으로 재설정하고 일반적으로 뷰가 다시 사용될 준비가 되게 하기 위해 사용한다. 당신은 이 메소드를 뷰에 어떤 새로운 데이터를 할당하기 위해 사용하지 말아야 한다. 그것은 당신의 데이터 소스 오브젝트의 역할이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;UICollectionViewReusableView&lt;/code&gt; 클래스에 정의된 &lt;code&gt;prepareForReuse()&lt;/code&gt; 메소드와 관련된 문서 내용이다.&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;UICollectionViewCell&lt;/code&gt; 은 &lt;code&gt;UICollectionReusableView&lt;/code&gt; 클래스를 상속받아 &lt;code&gt;prepareForReuse()&lt;/code&gt; 를 사용할 수 있고, 이 메소드를 재정의하여 셀 재사용 시 적절한 처리를 해줄 수 있다.&lt;/p&gt;
&lt;p&gt;여기서는 &lt;code&gt;UITableViewCell&lt;/code&gt; 과는 다르게 기본적으로 셀의 컨텐츠들을 리셋해주는 것이 없으므로 &lt;code&gt;UICollectionViewCell&lt;/code&gt; 를 사용할 때는 &lt;code&gt;prepareForReuse()&lt;/code&gt; 메소드를 반드시 재정의하여 적절한 처리를 해줄 필요가 있겠다.&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
&lt;/article&gt;</description>
      <category>iOS</category>
      <author>할루루</author>
      <guid isPermaLink="true">https://gorani95.tistory.com/253</guid>
      <comments>https://gorani95.tistory.com/253#entry253comment</comments>
      <pubDate>Fri, 24 Aug 2018 17:49:42 +0900</pubDate>
    </item>
  </channel>
</rss>