<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>IOS on letmecompile</title><link>https://www.letmecompile.com/category/ios/</link><description>Recent content in IOS on letmecompile</description><image><title>letmecompile</title><url>https://www.letmecompile.com/images/default-og-image.png</url><link>https://www.letmecompile.com/images/default-og-image.png</link></image><generator>Hugo -- 0.148.1</generator><language>ko-kr</language><lastBuildDate>Wed, 03 Sep 2025 20:40:23 +0900</lastBuildDate><atom:link href="https://www.letmecompile.com/category/ios/index.xml" rel="self" type="application/rss+xml"/><item><title>iOS 앱 리버스 엔지니어링 해보기</title><link>https://www.letmecompile.com/ios-app-reverse-engineering-with-frida/</link><pubDate>Wed, 03 Sep 2025 20:40:23 +0900</pubDate><guid>https://www.letmecompile.com/ios-app-reverse-engineering-with-frida/</guid><description>&lt;p>관심있게 지켜보던 iOS 앱의 블루투스 관련 코드가 어떤식으로 구현이 된건지 궁금해서 직접 비슷하게 만들어보려다가 잘 안되길래 최후의 수단인 리버스 엔지니어링을 시도해 보았다.
LLM과 대화를 나눠보니 탈옥된 폰에서 &lt;code>frida&lt;/code>를 사용하면 런타임에 코드를 후킹해서 조작하거나 로그를 찍어 분석이 가능하다고 해서 해당 방식으로 진행했던 부분 중 핵심적인 부분들만 단계별로 정리해 보았다.&lt;/p>
&lt;h2 id="iphone-탈옥">iPhone 탈옥&lt;/h2>
&lt;ul>
&lt;li>iPhone 기종/CPU 칩셋, iOS 버전에따라 다른 형태의 탈옥 툴이 존재&lt;/li>
&lt;li>테스트용 아이폰7 + iOS 15.6 기기를 dopamine 이용해서 탈옥 진행&lt;/li>
&lt;li>가이드 문서: &lt;a href="https://ios.cfw.guide/installing-dopamine/">https://ios.cfw.guide/installing-dopamine/&lt;/a>&lt;/li>
&lt;li>Sileo 설치&lt;/li>
&lt;/ul>
&lt;h2 id="탈옥-후-설정할-것">탈옥 후 설정할 것&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>아이폰의 Sileo 앱을 통해서 설치할 것&lt;/p></description></item><item><title>앱스토어 계정 이전시 애플 로그인 마이그레이션</title><link>https://www.letmecompile.com/apple-sign-in-migration-on-appstore-app-transfer/</link><pubDate>Wed, 13 Sep 2023 01:40:23 +0000</pubDate><guid>https://www.letmecompile.com/apple-sign-in-migration-on-appstore-app-transfer/</guid><description>&lt;div class="wp-block-jetpack-markdown">
&lt;p>
애플 로그인을 사용중인 앱을 다른 앱스토어 계정으로 이전하는 경우 해당 앱 내에서 애플 로그인 사용자를 구분하는데 사용되는 ID값(Team scoped identifier)이 변경된다. 이 값 뿐만 아니라 기존 애플 로그인 사용자가 이메일 가리기(private email) 기능을 활성화 했다면, 이로 인해 생성된 이메일 주소 또한 바뀌기 때문에 앱 이전(app transfer, 앱 트랜스퍼) 전/후로 별도의 마이그레이션을 꼭 수행해야한다. 이를 제대로 잘 처리하지않으면 기존 가입되어있던 사용자가 로그인을 시도해도 기존 사용자 정보로 로그인되는것이 아니고 신규 사용자 처럼 간주될 수 있기 때문에 주의해서 처리가 필요하다.
&lt;/p></description></item><item><title>모바일 디바이스간 P2P 연결 및 데이터 전송 방법</title><link>https://www.letmecompile.com/p2p-connection-for-mobile-device/</link><pubDate>Sat, 15 Dec 2018 04:05:47 +0000</pubDate><guid>https://www.letmecompile.com/p2p-connection-for-mobile-device/</guid><description>&lt;p>iOS/Android 모바일 디바이스들 사이에서 P2P 형태로 데이터 전송을 하는 방법에 대해 리서치 할 일이 있어서 알아본 내용을 간단히 공유합니다.&lt;/p>
&lt;h2 id="네트웍-타입별-androidios-p2p-연결-가능성-체크">네트웍 타입별 Android/iOS P2P 연결 가능성 체크&lt;/h2>
&lt;ul>
&lt;li>Bluetooth
&lt;ul>
&lt;li>애플 MFi인증 디바이스만 iPhone/iPod과 Bluetooth 연결 가능&lt;/li>
&lt;li>MFi는 apple에서 accessary 제조업체들이 만든 하드웨어를 인증하는 제도 (안드로이드는 인증되지 않음)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Bluetooth Low Energy
&lt;ul>
&lt;li>BLE는 애플 MFi인증 제약이 존재하지 않아서 안드로이드/iOS간 연결 가능&lt;/li>
&lt;li>BLE는 말그대로 저전력으로 설계된 spec이기때문에 전송 속도가 매우 느림&lt;/li>
&lt;li>iOS는 모두 지원하지만 안드로이드 디바이스별로 지원 스펙이 다름 (제대로 지원안하는 경우도 있음)&lt;/li>
&lt;li>BLE의 최대 전송속도
&lt;ul>
&lt;li>Apple guide line을 따르는 BLE 디바이스라면 디바이스에따라 이론적인 최대 전송속도 8~32kbps 정도가 한계
&lt;ul>
&lt;li>packet interval, MTU size 파라메터에 맞춰 application이 전송하는 데이터를 완벽하게 fit 시켰을때 나올 수 있는 이론적인 수치. 실제로는 더 느릴것 같음&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="https://devzone.nordicsemi.com/question/3440/how-do-i-calculate-throughput-for-a-ble-link/">https://devzone.nordicsemi.com/question/3440/how-do-i-calculate-throughput-for-a-ble-link/&lt;/a>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>WiFi
&lt;ul>
&lt;li>동일 네트워크 라우터에 접속한 디바이스들사이에서 P2P 연결 가능
&lt;ul>
&lt;li>multicast를 지원하는 라우터인경우 mDNS(ex: Apple Bonjour)를 이용하여 자동으로 동일 네트웍상의 디바이스를 찾아 주는 것이 가능&lt;/li>
&lt;li>개인적으로 사용하는 office/home wifi가 아닌 WiFi hotspot 같은 공용 라우터의 경우 P2P 연결이 안될 가능성이 높음.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>뮤직 서버에서 P2P연결 시작만 중계하는
&lt;ul>
&lt;li>NAT 뒤에 연결된 디바이스들도 연결이 가능하긴 함 UDP 홀펀칭 등의 방식을 사용하면 어느정도 커버가능하긴하지만 100% 연결 보장은 힘듦&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>참고자료
&lt;ul>
&lt;li>&lt;a href="http://www.goland.org/thaliiosandroidinterop/">Android/iOS Local Radio Interop&lt;/a>&lt;/li>
&lt;li>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="3rd-party-frameworks">3rd party frameworks&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://developers.google.com/nearby/">Google Nearby&lt;/a>
&lt;ul>
&lt;li>Bluetooth, BLE, WiFi 등의 연결방식을 상황에따라 적절히 조합해서 근처에 있는 device를 찾아서 연결해주는 framework&lt;/li>
&lt;li>아래 두가지 API set이 있는데 상황/용도에따라 다르게 사용&lt;/li>
&lt;li>Message API
&lt;ul>
&lt;li>iOS/Android&lt;/li>
&lt;li>small payload only through google server (devices do have to be connected to the Internet).&lt;/li>
&lt;li>음원전송은 불가능&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Connection API
&lt;ul>
&lt;li>Android ONLY&lt;/li>
&lt;li>P2P connection: message, file, stream transfer support&lt;/li>
&lt;li>음원전송에 적합&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;a href="http://p2pkit.io/">http://p2pkit.io&lt;/a>
&lt;ul>
&lt;li>유료 framework
&lt;ul>
&lt;li>$0.01/ MAU&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Android/iOS 둘다 서포트 하지만 GoogleNearBy 와 동일하게 대역폭한계로 음원전송에는 부적합해보임
&lt;ul>
&lt;li>20 messages per second and cannot exceed the size of 100KB&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>Playground에서 Cocoapod 라이브러리 사용하기</title><link>https://www.letmecompile.com/use-cocoapod-in-playground/</link><pubDate>Sat, 24 Nov 2018 18:17:03 +0000</pubDate><guid>https://www.letmecompile.com/use-cocoapod-in-playground/</guid><description>&lt;p>엑스코드 플레이그라운드(Xcode Playground)에서 간단하게 코드를 테스트 해보고 싶은데 해당 코드가 특정 cocoapod 라이브러리에 의존성이 있는 경우 &lt;code>cocoapods-playgrounds&lt;/code> 명령어 도구를 사용하면 편리하다.&lt;/p>
&lt;h2 id="설치-및-사용-방법">설치 및 사용 방법&lt;/h2>
&lt;h3 id="설치">설치&lt;/h3>
&lt;pre>&lt;code>sudo gem install cocoapods-playgrounds
&lt;/code>&lt;/pre>
&lt;h3 id="플레이그라운드-프로젝트-생성">플레이그라운드 프로젝트 생성&lt;/h3>
&lt;pre>&lt;code>cocoapods playgrounds podName
&lt;/code>&lt;/pre>
&lt;p>위 명령어를 실행하면 위 라이브러리가 연결된 워크스페이스가 자동으로 생성되고, 해당 워크스페이스 안에 우리가 사용할 수 있는 playground 파일까지 포함되어있으니 여기서 마음껏 테스트 해보면 된다.&lt;/p>
&lt;h3 id="여러-라이브러리-동시-참조">여러 라이브러리 동시 참조&lt;/h3>
&lt;p>여러개 라이브러리에 의존성을 가지는 플레이그라운드 프로젝트를 만들고 싶을 경우, 라이브러리 이름을 컴마로 구분하여 붙여 써 둔다.&lt;/p></description></item><item><title>Swift struct vs. class 차이점 비교 분석</title><link>https://www.letmecompile.com/swift-struct-vs-class-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EB%B9%84%EA%B5%90-%EB%B6%84%EC%84%9D/</link><pubDate>Tue, 30 Jan 2018 04:06:39 +0000</pubDate><guid>https://www.letmecompile.com/swift-struct-vs-class-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EB%B9%84%EA%B5%90-%EB%B6%84%EC%84%9D/</guid><description>&lt;p>Swift에는 &lt;code>struct&lt;/code>와 &lt;code>class&lt;/code>타입이 공존하고있기 때문에 아래의 차이점을 잘 숙지하고 상황에 맞게 사용하는것이 매우 중요하다.&lt;/p>
&lt;ul>
&lt;li>&lt;code>struct&lt;/code>
&lt;ul>
&lt;li>call by value (할당 또는 파라메터 전달시 value copy가 일어남)&lt;/li>
&lt;li>stack memory 영역에 할당 (속도가 빠름)
&lt;ul>
&lt;li>scope based lifetime: 컴파일타임에 compiler가 언제 메모리를 할당/해제할지 정확히 알고있음&lt;/li>
&lt;li>data locality: CPU 캐시 히트율이 높음&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>상속 불가능 (protocol은 사용 가능)&lt;/li>
&lt;li>&lt;code>NSData&lt;/code>로 serialize 불가능&lt;/li>
&lt;li>&lt;code>Codable&lt;/code> 프로토콜을 이용하여 손쉬운 &lt;code>JSON&lt;/code> &amp;lt;-&amp;gt; &lt;code>struct&lt;/code> 변환 가능 (Swift 4 이상)&lt;/li>
&lt;li>항상 새로운 변수로 copy가 일어나기때문에 multi-thread 환경에서 공유변수로 인해 문제를 일으킬 확률이 적음 &lt;sup id="fnref-706-thread_safe">&lt;a href="#fn-706-thread_safe" class="jetpack-footnote">1&lt;/a>&lt;/sup>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;code>class&lt;/code>
&lt;ul>
&lt;li>call by reference (할당 또는 파라메터 전달시 객체를 가리키고있는 메모리 주소값만 복사됨)&lt;/li>
&lt;li>heap memory 영역에 할당 (속도가 느림)
&lt;ul>
&lt;li>런타임에 직접 alloc하며 reference counting을 통해 dealloc이 필요&lt;/li>
&lt;li>memory fragmentation 등의 overhead가 존재&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>상속 가능&lt;/li>
&lt;li>&lt;code>NSData&lt;/code> serialize 가능&lt;/li>
&lt;li>&lt;code>Codable&lt;/code> 사용 불가능&lt;/li>
&lt;li>런타임에 타입 캐스팅을 통해서 클래스 인스턴스에 따라 여러 동작이 가능&lt;/li>
&lt;li>deinitializer 존재&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>참고: class안에 struct 변수를 property로 정의하는것 가능하며, 반대로 struct의 property중 하나로 class 인스턴스 변수를 갖고있는 것도 가능하다. 이 경우 해당 struct 변수의 copy가 일어날때 class 인스턴스의 주소값만 복사된다.&lt;/p></description></item><item><title>Swift Closure vs. Objective-C Block 차이점 비교 분석</title><link>https://www.letmecompile.com/swift-closure-vs-objective-c-block/</link><pubDate>Tue, 30 Jan 2018 03:07:08 +0000</pubDate><guid>https://www.letmecompile.com/swift-closure-vs-objective-c-block/</guid><description>&lt;p>Obj-C의 블락(block)이나 Swift 클로저(closure)는 컨셉은 거의 동일하나 closure 내부에서 현재 scope에 존재하는 값 타입(value type) 변수들을 캡쳐(capture)해서 사용할 때 &lt;strong>기본동작이 반대&lt;/strong>로 되어있기 때문에 사용법에 주의를 기울여야 한다. 반면 클래스 인스턴스와 같은 참조 타입(reference type) 변수들은 항상 reference copy가 일어나기 때문에 두 언어를 사용할때 차이점에 크게 신경쓰지않아도 된다. (대신 retain cycle이 생기지 않도록 조심해야 한다.)&lt;/p>
&lt;p>다음 예제들을 통해서 차이점을 좀 더 자세히 알아보자.&lt;/p>
&lt;h2 id="capture-in-swift-closure">Capture in Swift closure&lt;/h2>
&lt;p>Swift의 경우 일반적으로 value type 변수를 다른 변수에 할당하거나, 함수 파라메터로 전달 할 때 copy동작이 기본이다. 하지만 closure에서 변수를 capture를 할 때는 명시적인 capture list를 작성하지 않으면 &lt;strong>value type 변수(struct 변수 포함) 임에도 불구하고 reference capture&lt;/strong>가 일어난다. 확인을 위해서 다음 예제를 살펴보자.&lt;/p></description></item><item><title>Swift 익스텐션, Obj-C 카테고리 메서드명 Prefix하기</title><link>https://www.letmecompile.com/swift-extension-obj-c-category-method-prefix/</link><pubDate>Sat, 23 Sep 2017 14:51:47 +0000</pubDate><guid>https://www.letmecompile.com/swift-extension-obj-c-category-method-prefix/</guid><description>&lt;h2 id="obj-c-category의-위험성">Obj-C category의 위험성&lt;/h2>
&lt;p>Obj-C에서 동일한 메서드 이름을 가진 카테고리(category) A, B가 동시에 존재하더라도, 컴파일 타임에 오류가 발생하지 않고 정상적으로 빌드되어 실행이 가능하다. 하지만 런타임에서 A와 B중 어떤 녀석이 먼저 호출될지 알 수 없기때문에 (규칙이 없으며 랜덤하게 호출됨) 매우 위험한 상황이 발생한다. 이를 방지하기 위해서 Obj-C에서 카테고리 메서드에는 프로젝트에서 사용하는 고유의 prefix를 붙여줘서 이름이 완전히 겹칠 확률을 최대한 줄여주는 방식을 꼭 사용해야 한다. 그렇지 않으면 외부 라이브러리를 사용할때 해당 라이브러리에 동일한 category명이 존재해서 랜덤하게 호출되는 상황이 발생 할 수 있다. 이는 매우 원인 파악도 힘든 에러가 될 것이기에 꼭 피해야 한다.&lt;/p></description></item><item><title>유니버셜링크 vs. 커스텀URL스킴 비교 분석</title><link>https://www.letmecompile.com/universal-link-vs-custom-url-scheme/</link><pubDate>Mon, 21 Aug 2017 05:50:44 +0000</pubDate><guid>https://www.letmecompile.com/universal-link-vs-custom-url-scheme/</guid><description>&lt;p>iOS의 경우 기본적으로 Sandbox환경이라 다른 앱들간에 정보를 주고받는것이 간단하지 않다. 이때 정보를 주고받을 수 있는 대표적인 방법이 custom URL scheme이다. 앱의 고유한 scheme을 정의하고 이 scheme으로 시작하는 URL안에 정보를 담아서 URL을 열게되면 해당 scheme이 갖는 다른 앱을 실행하면서 정보전달을 할 수 있다. 하지만 이 방법에는 치명적인 단점이 있는데, 애플 앱스토어에서 해당 앱이 정의한 scheme의 uniqueness를 보장해주지 않기때문에 다른 앱들이 자신이 정의한 scheme을 사용하고 있을 수 있다는 점이다.&lt;/p>
&lt;p>자신의 앱을 MyApp이라고 하고 이 앱이 &lt;code>myapp://&lt;/code> 이라는 custom URL scheme을 사용한다고 가정하자. (MyApp안의 info.plist 내에 존재하는 “URL types – URL Schemes” 항목에 &lt;code>myapp&lt;/code> 이 정의하면 됨) 방금 정의한 custom scheme&lt;code>myapp&lt;/code>은 unique가 보장되지 않기 때문에 앱스토어에 올라온 YourApp 이라는 엉뚱한 앱이 동일하게 앱 내부에 custom scheme으로 &lt;code>myapp&lt;/code>을 정의하는 일이 발생할 수 있다. 만약 MyApp과 YourApp이 동시에 설치되어 있는 device에서 &lt;code>myapp://&lt;/code>으로 시작하는 URL을 open하게 되면 두 앱 중에서 누가 열릴지 알 수 없게 되어버린다. 설치 순서에 영향을 받는 것도 아니라서 특정한 규칙이 없으며, 상황에따라 두 앱중 하나가 열리게 되는 랜덤한 현상이 발생한다.&lt;/p></description></item><item><title>iOS 인앱 정기결제(IAP Auto-renewable Subscription) 튜토리얼</title><link>https://www.letmecompile.com/in-app-purchase-auto-renewable-subscription/</link><pubDate>Sun, 26 Jun 2016 15:10:33 +0000</pubDate><guid>https://www.letmecompile.com/in-app-purchase-auto-renewable-subscription/</guid><description>&lt;p>iOS 앱에서 상품을 등록하고 판매하는 과정은 꽤나 복잡하다. 그 중에서도 정기구독 자동결제(Auto-Renewable Subscription) 상품을 판매하는 경우 신경써야 할 부분이 매우 많다. 2016년 WWDC에서 애플은 Auto-Renewable Subscription을 모든 카테고리의 앱에 적용가능하도록 허용하기로 했고(기존에는 잡지, 음악 등 특정 컨텐츠에 대해서만 허용되었었음), 해당 타입의 결제를 통해 발생한 매출의 경우 다음 조건을 만족할 경우 앱 판매 수수료를 30% -&amp;gt;15%로 인하 하는 내용에 대해서 &lt;a href="https://developer.apple.com/app-store/subscriptions/whats-new/">발표&lt;/a>했다.&lt;/p>
&lt;ul>
&lt;li>수수료 인하 조건
&lt;ul>
&lt;li>해당유저가 1년이상 결제를 유지한 경우 1년 이후 결제분의 수수료를 15%로 인하 (2016년 6월 13일 이후 부터 적용)&lt;/li>
&lt;li>사용자가 중간에 정기 결제를 취소했더라도 60일 이내에 다시 정기결제를 시작한경우 해당 유저의 결제 기간은 계속 누적된다. (60일을 넘을 경우 리셋)&lt;/li>
&lt;li>이번 발표 전 기존 결제 기간도 카운트 된다. (Prior days of paid service are counted.) 즉, 이미 1년간 결제해온 사용자가 6월 13일 이후에 결제할 경우 수수료는 15%로 줄어든다.&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>Auto-Renewable Subscription에 대해 자세히 설명하기 전에 먼저 앱스토어의 다른 상품 타입들에 대해서도 간략히 정리해보도록 하자.&lt;/p></description></item><item><title>UIImage의 scale을 올바르게 처리하기</title><link>https://www.letmecompile.com/uiimage%EC%9D%98-scale%EC%9D%84-%EC%98%AC%EB%B0%94%EB%A5%B4%EA%B2%8C-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0/</link><pubDate>Mon, 06 Jul 2015 02:21:33 +0000</pubDate><guid>https://www.letmecompile.com/uiimage%EC%9D%98-scale%EC%9D%84-%EC%98%AC%EB%B0%94%EB%A5%B4%EA%B2%8C-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0/</guid><description>&lt;p>&lt;code>UIImage&lt;/code>의 size 는 픽셀(px)단위가 아닌 포인트(point) 단위로 처리가된다. 따라서 사이즈 정보에 추가적으로 스케일(scale) 정보를 같이 같고있다. &lt;code>UIImage&lt;/code>를 bundle에서 &lt;code>[UIImage imageNamed:]&lt;/code>를 이용하여 불러올때는 이미지에 붙어있는 &lt;code>@2x&lt;/code> 또는 &lt;code>@3x&lt;/code> 포스트픽스를 통해서 해당이미지의 스케일이 정상적으로 설정되어 특별히 신경쓸 필요가 없다. 마찬가지로 서버에 이미지 데이터를 요청해서 받아올 경우에도 AFNetworking의 &lt;code>AFImageResponseSerializer&lt;/code>을 사용하면 &lt;code>UIImage&lt;/code>를 만들어줄 때 스케일 관련 정보 또한 내부적으로 처리를 해주니 신경을 쓸 필요가 없다.&lt;/p>
&lt;p>하지만 &lt;code>NSData&lt;/code>로부터 &lt;code>UIImage&lt;/code> 를 생성할때나 파일명에 포스트 픽스가 없는 다운로드된 파일로 부터 &lt;code>UIImage&lt;/code>를 생성할 때는 이러한 스케일 처리를 따로 해줘야 된다.&lt;/p></description></item><item><title>Cocoapod version update for Mac OS Yosemite</title><link>https://www.letmecompile.com/cocoapod-version-update-for-mac-os-yosemite/</link><pubDate>Mon, 27 Oct 2014 15:31:08 +0000</pubDate><guid>https://www.letmecompile.com/cocoapod-version-update-for-mac-os-yosemite/</guid><description>&lt;p> &lt;br>
Mac OS X Yosemite 로 업그레이드를 하게되면 cocoaPod이 잘 작동하지 않을것이다. 이때 다음 인스트럭션을 따라 해결해 나가면 된다.&lt;/p>
&lt;ol>
&lt;li>코코아팟 최신버전으로 업데이트 (현재 최신은 0.34.4 입니다)
sudo gem uninstall cocoapods
sudo gem uninstall xcodeproj
sudo gem install xcodeproj
sudo gem install cocoapods&lt;/li>
&lt;/ol>
&lt;p> &lt;br>
2. Podfile의 첫줄에 다음 코드 추가&lt;/p>
&lt;pre>&lt;code> source 'https://github.com/CocoaPods/Specs.git'
&lt;/code>&lt;/pre>
&lt;ul>
&lt;li>이부분은 옵셔널하긴한데, 추가하지 않으면 deprecated warning이 뜨기때문에 추가해주는것이 좋다.&lt;/li>
&lt;/ul>
&lt;p> &lt;br>
3. 빌드시 Podfile.lock 혹은 Manifest.lock 관련 에러가 날 경우 처리방법&lt;/p></description></item><item><title>코코아팟(CocoaPods) 젠킨스(Jenkins) 설정 연동</title><link>https://www.letmecompile.com/%EC%BD%94%EC%BD%94%EC%95%84%ED%8C%9Fcocoapods-%EC%A0%A0%ED%82%A8%EC%8A%A4jenkins-%EC%84%A4%EC%A0%95-%EC%97%B0%EB%8F%99/</link><pubDate>Wed, 23 Jul 2014 04:47:28 +0000</pubDate><guid>https://www.letmecompile.com/%EC%BD%94%EC%BD%94%EC%95%84%ED%8C%9Fcocoapods-%EC%A0%A0%ED%82%A8%EC%8A%A4jenkins-%EC%84%A4%EC%A0%95-%EC%97%B0%EB%8F%99/</guid><description>&lt;p> &lt;/p>
&lt;p>코코아팟(CocoaPods)을 사용하게 될경우 프로젝트(.xcproject)기반에서 워크스페이스(.xcworkspace) 기반으로 변경된다. 이때 젠킨스(Jenkins)에서 기존 프로젝트 기반 설정을 그대로 사용할경우 기본 프로젝트는 잘 컴파일되지만, 연결된 Pods 프로젝트가 업데이트 및 컴파일이 되지 않아서 &lt;code>-lPods&lt;/code> 링크 에러(link error)가 나는데. 이때 Jenkins에서 CocoaPods을 잘 인식할 수 있게 할 수 있는 설정방법을 공유하고자 한다.&lt;/p>
&lt;h2 id="설정-방법">설정 방법&lt;/h2>
&lt;p>기존에 프로젝트 기반으로 빌드설정이 되어있던 젠킨스 빌드설정 페이지를 열고,&lt;/p>
&lt;ol>
&lt;li>
&lt;p>Build 섹션에서 “Add build step” 버튼을 눌러서 Execute shell 항목을 추가 후 &lt;code>pod install&lt;/code> 명령어 입력&lt;/p></description></item><item><title>allocWithZone: 의 의미</title><link>https://www.letmecompile.com/allocwithzone-%EC%9D%98-%EC%9D%98%EB%AF%B8/</link><pubDate>Tue, 15 Jul 2014 13:30:08 +0000</pubDate><guid>https://www.letmecompile.com/allocwithzone-%EC%9D%98-%EC%9D%98%EB%AF%B8/</guid><description>&lt;p>어떤 클래스에 대해 &lt;code>NSCopying&lt;/code> 프로토콜을 구현하다보면 &lt;code>allocWithZone:&lt;/code> 이라는 메서드에 맞닥뜨리게된다.&lt;br>
객체의 경우 힙(heap)에 할당되는데, 이 힙을 zone으로 나누고 해당 zone별로 메모리를 할당 및 관리하여 메모리 파편화를 막는데 도움을 주기위해 존재하는 메서드이다. 하지만  최근 런타임관련 알고리즘이 많이 효율적으로 변경되어서 굳이 zone을 사용하지 않아도되며, ARC로 바뀌면서 아예 zone을 사용하지 말라고 다음과같이 설명하고있다.&lt;sup id="fnref-403-1">&lt;a href="#fn-403-1" rel="footnote">1&lt;/a>&lt;/sup>.&lt;/p>
&lt;blockquote>
&lt;p>You cannot use memory zones.&lt;/p>
&lt;p>There is no need to use NSZone any more—they are ignored by the modern Objective-C runtime anyway.&lt;/p></description></item><item><title>오토레이아웃 IB(Interface Builder)에서 다루기</title><link>https://www.letmecompile.com/%EC%98%A4%ED%86%A0%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-ibinterface-builder%EC%97%90%EC%84%9C-%EB%8B%A4%EB%A3%A8%EA%B8%B0/</link><pubDate>Tue, 15 Jul 2014 13:15:37 +0000</pubDate><guid>https://www.letmecompile.com/%EC%98%A4%ED%86%A0%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-ibinterface-builder%EC%97%90%EC%84%9C-%EB%8B%A4%EB%A3%A8%EA%B8%B0/</guid><description>&lt;h2 id="제약조건constraint-설정">제약조건(constraint) 설정&lt;/h2>
&lt;ul>
&lt;li>하나의 뷰를 선택 – 해당 뷰와 슈퍼뷰와의 관계 설정가능, 선택된 뷰 자체의 제약사항 설정가능&lt;/li>
&lt;li>두개 이상의 뷰를 선택:&lt;br>
 선택된 뷰들간의 관계 설정가능, 선택된 뷰들의 공통제약사항 설정가능(ex: equal width)&lt;/li>
&lt;li>IB왼쪽의 ViewTree화면이나 IB 화면에서 에서 하나의 뷰를 선택 후 컨트롤 키를 누르고 드래그하여 다른 아이템을 선택하면 두 아이템 관계를 설정 가능.&lt;/li>
&lt;/ul>
&lt;p>IB에서 최상위 view를 선택한 후, 오른쪽 속성창에서 orientation, top bar, bottom bar 유무 등 옵션을 조정하여 실제보이는 형태를 실행하지 않고 시뮬레이트 가능.&lt;/p></description></item><item><title>iOS 고급 오토레이아웃(auto layout)</title><link>https://www.letmecompile.com/advanced-auto-layout/</link><pubDate>Wed, 18 Jun 2014 09:39:09 +0000</pubDate><guid>https://www.letmecompile.com/advanced-auto-layout/</guid><description>&lt;p>본 글에서는 기본적인 오토레이아웃 튜토리얼들에서 잘 다루지 않는 커스텀 뷰에 오토레이아웃(auto layout)을 적용하는 방법과, 전반적으로 레이아웃 시스템이 어떻게 동작하는지를 중심으로 설명해보도록 하겠다. 오토레이아웃의 종류나 기본적인 적용방법들은 다른 &lt;a href="http://www.raywenderlich.com/ko/21139/ios-6%EC%97%90%EC%84%9C-%EC%98%A4%ED%86%A0-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0-%ED%8C%8C%ED%8A%B8-1-1">좋은 튜토리얼&lt;/a>들이 많으니 다루지 않을 예정이다.&lt;/p>
&lt;h2 id="autolayout-programmatically-사용하기">AutoLayout Programmatically 사용하기&lt;/h2>
&lt;p>개인적으로 오토레이아웃을 사용할 때도 인터페이스빌더를 되도록이면 쓰지 않으면서 코드만로 작성하는 방법을 선호한다. 애플에서 제공하는 &lt;code>NSLayoutConstraint&lt;/code> 의 경우 가독성이 매우 떨어지는 단점이 있고, 이를 보완하기 위한 &lt;a href="https://developer.apple.com/library/ios/documentation/userexperience/conceptual/AutolayoutPG/VisualFormatLanguage/VisualFormatLanguage.html#//apple_ref/doc/uid/TP40010853-CH3-SW1">Visual format language&lt;/a> 가 있지만, 이 또한 아주 직관적인 편은 아니며 문자열을 그대로 사용하기때문에 오타의 위험성도 존재한다. 이래저래 알아본 결과 &lt;a href="https://github.com/Masonry/Masonry">Masonry&lt;/a>라는 라이브러리가 그나마 가장 직관적이면서 가독성이 좋아 오토레이아웃 제약조건 코드를 작성할때 만족하며 사용중이다. Swift에서 사용을 원한다면 동일한 사람이 개발한 &lt;a href="https://github.com/SnapKit/SnapKit">SnapKit&lt;/a>을 사용하면 된다.&lt;/p></description></item><item><title>Cocoa Binding Controller Keys</title><link>https://www.letmecompile.com/cocoa-binding-controller-keys/</link><pubDate>Sat, 14 Jun 2014 07:37:57 +0000</pubDate><guid>https://www.letmecompile.com/cocoa-binding-controller-keys/</guid><description>&lt;p>코코아 바인딩 컨트롤러의 경우 최소한의 코딩만으로 model값이 변화할때 view와 model 사이의 싱크를 맞춰주는 역할을 한다.&lt;/p>
&lt;p>애플에서 제공하는 각 클래스별 바인딩 가능한 키값들은 &lt;a href="https://developer.apple.com/library/mac/documentation/cocoa/reference/CocoaBindingsRef/CocoaBindingsRef.html#//apple_ref/doc/uid/10000189-BCICJDHA">다음 문서&lt;/a>&lt;br>
에서 확인하면 되고,&lt;/p>
&lt;p>본 글에서는 자주 사용하는 바인딩 컨트롤러들의 상속구조를 살펴보고, 각각의 컨트롤러들에 어떤 키/경로 값을 설정할 수 있는지 정리해 보았다.&lt;/p>
&lt;h2 id="바인딩-컨트롤러-상속구조">바인딩 컨트롤러 상속구조&lt;/h2>
&lt;ul>
&lt;li>NSController -&amp;gt; NSObjectController&lt;/li>
&lt;li>NSController -&amp;gt; NSObjectController -&amp;gt; NSArrayController&lt;/li>
&lt;li>NSController -&amp;gt; NSObjectController -&amp;gt; NSArrayController -&amp;gt; NSDictionaryController&lt;/li>
&lt;li>NSController -&amp;gt; NSObjectController -&amp;gt; NSTreeController&lt;/li>
&lt;li>NSController -&amp;gt; NSUserDefaultsController&lt;/li>
&lt;/ul>
&lt;h2 id="nsobjectcontroller">NSObjectController&lt;/h2>
&lt;ul>
&lt;li>canAdd&lt;/li>
&lt;li>canRemove&lt;/li>
&lt;li>isEditable&lt;/li>
&lt;li>selectedObjects&lt;/li>
&lt;li>selection&lt;/li>
&lt;/ul>
&lt;h2 id="nsarraycontroller">NSArrayController&lt;/h2>
&lt;ul>
&lt;li>arrangedObjects&lt;/li>
&lt;li>canAdd&lt;/li>
&lt;li>canInsert&lt;/li>
&lt;li>canRemove&lt;/li>
&lt;li>canSelectNext&lt;/li>
&lt;li>canSelectPrevious&lt;/li>
&lt;li>filterPredicate&lt;/li>
&lt;li>isEditable&lt;/li>
&lt;li>selectedObjects&lt;/li>
&lt;li>selection&lt;/li>
&lt;li>selectionIndex&lt;/li>
&lt;li>selectionIndexes&lt;/li>
&lt;li>sortDescriptors&lt;/li>
&lt;/ul>
&lt;h2 id="nsdictionarycontroller">NSDictionaryController&lt;/h2>
&lt;ul>
&lt;li>arrangedObjects&lt;/li>
&lt;li>canAdd&lt;/li>
&lt;li>canInsert&lt;/li>
&lt;li>canRemove&lt;/li>
&lt;li>canSelectNext&lt;/li>
&lt;li>canSelectPrevious&lt;/li>
&lt;li>isEditable&lt;/li>
&lt;li>selectedObjects&lt;/li>
&lt;li>selection&lt;/li>
&lt;li>selectionIndex&lt;/li>
&lt;li>selectionIndexes&lt;/li>
&lt;li>sortDescriptors&lt;/li>
&lt;/ul>
&lt;h2 id="nstreecontroller">NSTreeController&lt;/h2>
&lt;ul>
&lt;li>arrangedObjects&lt;/li>
&lt;li>canAdd&lt;/li>
&lt;li>canAddChild&lt;/li>
&lt;li>canInsert&lt;/li>
&lt;li>canInsertChild&lt;/li>
&lt;li>canRemove&lt;/li>
&lt;li>isEditable&lt;/li>
&lt;li>selectedObjects&lt;/li>
&lt;li>selectedNodes&lt;/li>
&lt;li>selection&lt;/li>
&lt;li>selectionIndexPath&lt;/li>
&lt;li>selectionIndexPaths&lt;/li>
&lt;li>sortDescriptors&lt;/li>
&lt;/ul>
&lt;h2 id="nsuserdefaultscontroller">NSUserDefaultsController&lt;/h2>
&lt;ul>
&lt;li>hasUnappliedChanges&lt;/li>
&lt;li>values&lt;/li>
&lt;/ul></description></item><item><title>MacOS 10.10 &amp; iOS 8 새기능 익스텐션(Extensions) 개념 잡기</title><link>https://www.letmecompile.com/extensions-for-macos-10-10-ios-8/</link><pubDate>Sat, 14 Jun 2014 06:03:45 +0000</pubDate><guid>https://www.letmecompile.com/extensions-for-macos-10-10-ios-8/</guid><description>&lt;p>기존의 OS X나 iOS에서는 custom URL Scheme을 이용하거나 custom pasteboard(번들 seed ID를 동일한경우만 가능) 등을 이용하여 어플리케이션 간에 데이터를 **‘전달’**하는 것만 가능했다.&lt;/p>
&lt;p>즉, A라는 앱에서 B라는 앱으로 데이터를 전달한 후 B앱으로 컨텍스트가 전환된 후 그 데이터를 받아서 추가적인 화면을 보여주거나 처리를 할 수는 있었지만, &lt;strong>아예 앱간 컨텍스트 전환 없이 A앱 내부에서 B앱이 가진 기능을 바로 사용하는 것이 불가능&lt;/strong>했다.&lt;/p>
&lt;p>하지만 이번에 새로운 OS에 “익스텐션(Extensions)” 이라는 이름으로 이것을 가능하게 해주는 기술을 애플에서 공개했다. 앱간에 정보를 주고받으면서 앱 to 앱으로 전환이 일어나는 것 자체가 사용자에게 있어서는 불편이었기 때문에 이러한 익스텐션 기능이 잘 적용되면 사용자 경험 자체가 많이 좋아질 것으로 예상된다.&lt;br>
(사용자에게 있어서는 앱전환이 일어나지 않는것으로 보이지만, 실제로 기술적인 관점에서 봤을때 익스텐션 자체는 실행중인 앱과는 다른 독립적인 프로세스인 것에 주의)&lt;/p></description></item><item><title>Aspect Oriented Programming in Objective-C</title><link>https://www.letmecompile.com/aspect-oriented-programming-in-objective-c/</link><pubDate>Fri, 30 May 2014 14:29:11 +0000</pubDate><guid>https://www.letmecompile.com/aspect-oriented-programming-in-objective-c/</guid><description>&lt;h2 id="관점지향프로그래밍-aspect-oriented-programmingaop이란">관점지향프로그래밍, Aspect Oriented Programming(AOP)이란?&lt;/h2>
&lt;p>‘Aspect’ 란 어떤 프로그램의 공통적인 기능(common feature)이 프로그램 전반에 걸쳐 영향을 주는 형태를 지칭한다.&lt;br>
예를들어 회원 정보를 관리하는 프로그램을 만드는 경우, 실제 회원 정보를 인덱싱하는 것이 핵심적인 문제(core concern)이며, 이 부분을 수정할때에는 해당 핵심 부분만 변경하면 되기때문에 영향받는 범위가 좁아서 모듈화(modularity)이 깨지지 않는다. 하지만 이 프로그램에 로깅(logging) 기능을 추가하게되면 어떻게될까?&lt;br>
로깅 기능은 DB, 인증, 등 시스템 전반에 걸쳐 적용이되어야하는 문제(cross-cutting concern)이며 따라서 로깅에 관한 코드들은 프로그램의 코드들 곳곳에 분포한다. 따라서 로깅기능을 추가하면서 기존의 객체지향프로그래밍(OOP)이나 절차지향프로그래밍(procedural programming) 방법론으로 개발할경우에는 모듈화가 깨지게 된다.&lt;br>
이러한 기존의 방법론의 한계점을 해결하기위해 특정 상황에서 제한적으로 AOP를 도입하는 것을 고려해볼만 하다.&lt;/p></description></item><item><title>Xcode Debugging tips</title><link>https://www.letmecompile.com/xcode-debugging-tips/</link><pubDate>Tue, 20 May 2014 15:00:27 +0000</pubDate><guid>https://www.letmecompile.com/xcode-debugging-tips/</guid><description>&lt;p>엑스코드(Xcode)를 사용하면서 여러가지 유용하게 사용해왔던 기능들을 간단히 정리해보았다.&lt;br>
본 글에서는 잘 사용하지 않아서 모르고있지만 유용하게 사용될 수 있는 기능위주로 설명을 할 것이고 실제 디버거를 이용한 프로그램에대한 디버깅 방법은 다음 글에 더 자세히 적어두었으니 참조하도록 하자.&lt;br>
&lt;a href="http://www.letmecompile.com/xcode-lldb-%EB%94%94%EB%B2%84%EA%B9%85-%ED%85%8C%ED%81%AC%EB%8B%89/">http://www.letmecompile.com/xcode-lldb-디버깅-테크닉/&lt;/a>&lt;/p>
&lt;h2 id="xcode-디버깅-콘솔에-색상-적용하기">Xcode 디버깅 콘솔에 색상 적용하기&lt;/h2>
&lt;p>네트워크 어플리케이션을 개발하다보면 다양한 로그들이 여러 스레드에서 복합적으로 출력되어 한눈에 알아보기가 쉽지 않다. 이때 CocoaLumberjack과 XcodeColors 플러그인의 조합으로 콘솔화면에 로깅 타입에따라서 색상 적용이 가능해서 매우 편리하다.&lt;/p>
&lt;p>다음 링크를 참고해서 설정하면 된다.&lt;/p></description></item><item><title>Objective-C Tips from WWDC 2013</title><link>https://www.letmecompile.com/objective-c-tips-from-wwdc-2013/</link><pubDate>Mon, 19 May 2014 14:38:03 +0000</pubDate><guid>https://www.letmecompile.com/objective-c-tips-from-wwdc-2013/</guid><description>&lt;p>애플 WWDC2013, Session 228에 소개된 내용들 중 iOS나 Mac 개발시 자주쓰일만한 팁들을 추려내서 간단히 정리해보았다.&lt;/p>
&lt;h2 id="서브스크립팅subscripting-사용하기">서브스크립팅(subscripting) 사용하기&lt;/h2>
&lt;p>Modern Objective-C 문법이 적용되면서 NSDictionary나 NSArray같은 foundation 데이터 구조객체들은 서브스크립팅을 이용하여 다음과같이 간결하게 작성이 가능하게되었다.&lt;/p>
&lt;p>&lt;code>[myArray objectAtIndex:3]&lt;/code> -&amp;gt; &lt;code>myArray[3]&lt;/code>&lt;br>
&lt;code>[myDictionary objectForKey:@&amp;quot;key&amp;quot;]&lt;/code> -&amp;gt; &lt;code>myDictionary[@&amp;quot;key&amp;quot;]&lt;/code>&lt;/p>
&lt;p>사용자가 만든 커스텀 클래스에도 서브스크립팅을 위한 set/get메서드만 잘 정의해두면 훨씬 더 간결한 프로그램 작성이 가능하다.&lt;/p>
&lt;p>MyCustomArray 클래스에&lt;/p>
&lt;pre>&lt;code> - (id)objectAtIndexedSubscript:(NSUInteger)idx;
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;
&lt;/code>&lt;/pre>
&lt;p>위 두가지 메서드 구현시 다음과같이 배열처럼 인덱스로 바로 접근 가능&lt;/p></description></item><item><title>iOS 타이틀레이블 위치 강제 조정</title><link>https://www.letmecompile.com/ios-%ED%83%80%EC%9D%B4%ED%8B%80%EB%A0%88%EC%9D%B4%EB%B8%94-%EC%9C%84%EC%B9%98-%EA%B0%95%EC%A0%9C-%EC%A1%B0%EC%A0%95/</link><pubDate>Mon, 19 May 2014 14:10:23 +0000</pubDate><guid>https://www.letmecompile.com/ios-%ED%83%80%EC%9D%B4%ED%8B%80%EB%A0%88%EC%9D%B4%EB%B8%94-%EC%9C%84%EC%B9%98-%EA%B0%95%EC%A0%9C-%EC%A1%B0%EC%A0%95/</guid><description>&lt;p>iOS 네비게이션바(Navigationbar)의 좌우 툴바버튼이 폭 균형이 맞지 않을경우, 타이틀 레이블의 중앙 정렬이 한쪽으로 쏠리면서 좋지 않게 보인다. 이를 방지하여 레이블을 강제로 중앙 정렬하기 위해서 다음과 같은 방법들이 있으니 상황에따라서 적절히 적용하면 된다.&lt;/p>
&lt;h2 id="방법1">방법1:&lt;/h2>
&lt;p>&lt;code>viewWillAppear:&lt;/code>에서 titleView를 hide했다가 &lt;code>viewDidAppear&lt;/code>에서 titleView의 위치를 원하는대로 설정 후 unhide&lt;br>
이경우 타이틀레이블의 트랜지션 애니메이션은 보이지 않게되니 네비게이션 push동작이있는 상황에서는 쓰지 않는것을 추천한다.&lt;/p>
&lt;h2 id="방법2">방법2:&lt;/h2>
&lt;p>네비게이션바의 타이틀뷰에 &lt;code>UILabel&lt;/code>을 상속받은 &lt;code>CustomTitleLabel&lt;/code>를 set.&lt;br>
&lt;code>navigationItem.titleView = [[CustomTitleLabel alloc] init];&lt;/code>&lt;/p>
&lt;p>네비게이션바의 레이아웃이 조정될때 자동으로 titleView의 frame값도 같이 조정되게 되는데, 기본적으로 중앙정렬을 하는 동작이 일어나게 된다. 해당 동작이 일어나는 것을 막기위해 &lt;code>CustomTitleLabel&lt;/code>의 &lt;code>setFrame:&lt;/code> 메서드를 오버라이드하여 &lt;code>setFrame:&lt;/code>의 동작을 마음대로 조정한다.&lt;/p></description></item><item><title>NSTimer 백그라운드 진입시 동작 분석</title><link>https://www.letmecompile.com/nstimer-%EB%B0%B1%EA%B7%B8%EB%9D%BC%EC%9A%B4%EB%93%9C-%EC%A7%84%EC%9E%85%EC%8B%9C-%EB%8F%99%EC%9E%91-%EB%B6%84%EC%84%9D/</link><pubDate>Thu, 24 Apr 2014 16:40:32 +0000</pubDate><guid>https://www.letmecompile.com/nstimer-%EB%B0%B1%EA%B7%B8%EB%9D%BC%EC%9A%B4%EB%93%9C-%EC%A7%84%EC%9E%85%EC%8B%9C-%EB%8F%99%EC%9E%91-%EB%B6%84%EC%84%9D/</guid><description>&lt;p>iOS에서 특정 시간주기로 특정 메서드을 호출하기위해 NSTimer를 사용하게 된다. 이때 앱이 백그라운드(background)로 진입할때, 그리고 잠시 후 다시 포어그라운드(foreground)로 돌아올경우 예약되어 사용중인 NSTimer가 어떻게 동작하는지 살펴보도록 하자.&lt;/p>
&lt;p>기본적으로 타이머의 실행 주기는 타이머가 &lt;strong>등록되는 시간을 기준&lt;/strong>으로하여 **고정 간격으로 실행(fire)**된다. 이는 앱이 백그라운드로 진입하면서 잠시 타이머가 정지한다 해도 영향을 받지않고 동일하게 적용된다.&lt;/p>
&lt;h3 id="백그라운드-진입시-nstimer는-언제-정지하는가">백그라운드 진입시 NSTimer는 언제 정지하는가?&lt;/h3>
&lt;ol>
&lt;li>앱이 백그라운드로 진입하면서 AppDelegate의 &lt;code>applicationDidEnterBackground:&lt;/code>가 호출될 때, 특별히 명시적으로 &lt;code>backgroundTask&lt;/code>를 등록하지 않은경우에는 백그라운드 진입과 동시에 타이머는 정지하게된다.&lt;/p></description></item><item><title>GCD 튜토리얼</title><link>https://www.letmecompile.com/gcd-%ED%8A%9C%ED%86%A0%EB%A6%AC%EC%96%BC/</link><pubDate>Tue, 18 Mar 2014 15:24:44 +0000</pubDate><guid>https://www.letmecompile.com/gcd-%ED%8A%9C%ED%86%A0%EB%A6%AC%EC%96%BC/</guid><description>&lt;p>지난 포스트에서 블록(block)의 동작에 대해서 분석해보았는데, 이런 블록들을 이용하여 멀티스레드 프로그래밍을 손쉽게 할 수 있는 방법을 제공하는 GCD (Grand Central Dispatch) 에대해 알아보도록 하자. 본 포스트의 내용은 &lt;sup id="fnref-1">&lt;a href="#fn-1" rel="footnote">1&lt;/a>&lt;/sup> 의 내용을 요약하면서 추가적으로 유용한 내용들을 GCD 애플 문서&lt;sup id="fnref-2">&lt;a href="#fn-2" rel="footnote">2&lt;/a>&lt;/sup>에서 발췌하여 정리한 내용임을 밝힌다.&lt;/p>
&lt;h2 id="디스패치-큐의-종류">디스패치 큐의 종류&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>컨커런트 디스패치 큐 (concurrent dispatch queue) : 해당 큐 내의 작업들간에 실행 순서는 보장할 수 없다.
dispatch_queue_t queue = dispatch_queue_create(“com.letmecompile.concurrentQueue”, DISPATCH_QUEUE_CONCURRENT);&lt;/p>
&lt;/li>
&lt;li>
&lt;p>시리얼 디스패치 큐 (serial dispatch queue): 해당 큐 내의 작업들은 큐에 추가된 순서로 하나씩 수행됨을 보장한다. 때문에 시리얼큐는 하나 생성될때마다 스레드가 하나 더 생기기때문에 과도하게 많은숫자를 하면 성능에 문제가 있을 수 있다.
dispatch_queue_t queue = dispatch_queue_create(“com.letmecompile.serialQueue”, NULL);&lt;/p></description></item><item><title>Xcode LLDB 디버깅 테크닉</title><link>https://www.letmecompile.com/xcode-lldb-%EB%94%94%EB%B2%84%EA%B9%85-%ED%85%8C%ED%81%AC%EB%8B%89/</link><pubDate>Fri, 28 Feb 2014 09:19:37 +0000</pubDate><guid>https://www.letmecompile.com/xcode-lldb-%EB%94%94%EB%B2%84%EA%B9%85-%ED%85%8C%ED%81%AC%EB%8B%89/</guid><description>&lt;p>Xcode에 기본으로 내장되어있는 디버거(debugger)인 LLDB는 기존에 가장 많이 사용되던 gdb보다 많은 유용한 기능들을 갖고있다. LLDB 명령어 분석기에는 파이썬(Python) 인터프리터가 내장되어있어서 &lt;code>script&lt;/code> 명령어로 파이썬 코드들을 사용할 수 있다. 이 또한 반대로 모든 LLDB API들이 SB(Scripting Bridge) 를 통해서 Python에서도 사용이 가능하도록 되어있다.[^1] 이러한 파이썬과의 연계를 통해서 Xcode 디버깅을 진행 할때 더 세분화된 조건들을 정의하여 브레이크포인트(breakpoint)에 지정할 수 있게되었고, 이런 조건에따라 액션 수행, 브레이크포인트 무시/진행여부 결정 등의 다양한 동작이 가능하다[^2].&lt;br>
본 글은 애플의 “Advance Debugging with LLDB (WWDC 2013, Session 413)” 발표자료[^3]를 토대로 요약 및 정리한 내용이다.&lt;/p></description></item><item><title>KVO 컨텍스트 표현을 위한 자기참조 포인터</title><link>https://www.letmecompile.com/kvo-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%ED%91%9C%ED%98%84%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9E%90%EA%B8%B0%EC%B0%B8%EC%A1%B0-%ED%8F%AC%EC%9D%B8%ED%84%B0/</link><pubDate>Thu, 20 Feb 2014 14:19:02 +0000</pubDate><guid>https://www.letmecompile.com/kvo-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8-%ED%91%9C%ED%98%84%EC%9D%84-%EC%9C%84%ED%95%9C-%EC%9E%90%EA%B8%B0%EC%B0%B8%EC%A1%B0-%ED%8F%AC%EC%9D%B8%ED%84%B0/</guid><description>&lt;p>다음과같은 포인터변수에 자신의 변수명 그대로 자기자신의 주소값을 할당하는 특이한 변수선언을 처음 볼 경우 당황스러울 것이다.&lt;/p>
&lt;blockquote>
&lt;p>void *myVariableName = &amp;amp;myVariableName&lt;/p>&lt;/blockquote>
&lt;p>하지만 이는 자기참조 포인터 혹은 유니크 컨텍스트 포인터(unique context pointer)라는 이름으로 불리는 엄연히 C/C++/Obj-C에서 유효한 문법이다. 이를 이용하여 컴파일타임에 유니크한 포인터값을 생성할 수 있어서 컨텍스트 구분을 위한 변수를 표현할때 매우 유용하게 사용될 수 있다.&lt;/p>
&lt;p>해당 컨텍스트변수가 해당 파일 내에서만 사용할 경우.&lt;/p>
&lt;p>&lt;code>.m&lt;/code>파일에 다음과같이 선언하면된다.&lt;/p>
&lt;blockquote>
&lt;p>static void *MyContext = &amp;amp;MyContext;&lt;/p>&lt;/blockquote>
&lt;p>만약 다른 파일에서도 사용되는 컨텍스트라면,&lt;/p></description></item><item><title>Objective-C Block 동작 심층 분석</title><link>https://www.letmecompile.com/objective-c-block-%EB%8F%99%EC%9E%91-%EC%8B%AC%EC%B8%B5-%EB%B6%84%EC%84%9D/</link><pubDate>Tue, 11 Feb 2014 14:33:28 +0000</pubDate><guid>https://www.letmecompile.com/objective-c-block-%EB%8F%99%EC%9E%91-%EC%8B%AC%EC%B8%B5-%EB%B6%84%EC%84%9D/</guid><description>&lt;p>블락은 애플에서 closure 개념을 도입하기위해 ANSI C 에 익스텐션 형태로 만들어진 문법이다. 따라서 C/C++/Objective-C에서 모두 사용이 가능하지만 사용법과 메모리 관리에 있어서의 사용법은 언어특성에따라 조금씩 달라진다. 여기서는 Objective-C에서의 블락에 초점을 맞춰 분석을 할 예정이다.&lt;/p>
&lt;h2 id="블락block의-실체">블락(Block)의 실체&lt;/h2>
&lt;p>블락을 선언할 경우 실제로 컴파일러에의해 생성되는 코드에서는 &lt;code>__block_literal&lt;/code> 이라는 구조체(struct) 형태로 선언이된다. 이 구조체 안에는 &lt;code>isa&lt;/code> 정보가 포함되어있어서 결국 Objective-C의 객체의 특성을 가지게 된다.(심지어 블락이 C/C++에서 사용되더라도 동일하게 Objective-C의 객체특성을 가진다). Obj-C의 런타임에서 &lt;code>isa&lt;/code>에관한 세부 내용은&lt;a href="http://www.letmecompile.com/objective-c-%EB%9F%B0%ED%83%80%EC%9E%84runtime-%EB%82%B4%EB%B6%80-%EB%8F%99%EC%9E%91-%EB%B6%84%EC%84%9D">Objective-C 런타임 내부동작 분석&lt;/a> 글에 자세히 설명되어있다.&lt;/p></description></item><item><title>코어데이터(Core Data) 한줄로 데이터 불러오기</title><link>https://www.letmecompile.com/%EC%BD%94%EC%96%B4-%EB%8D%B0%EC%9D%B4%ED%84%B0core-data-%ED%95%9C%EC%A4%84%EB%A1%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%88%EB%9F%AC%EC%98%A4%EA%B8%B0/</link><pubDate>Sat, 17 Aug 2013 07:53:58 +0000</pubDate><guid>https://www.letmecompile.com/%EC%BD%94%EC%96%B4-%EB%8D%B0%EC%9D%B4%ED%84%B0core-data-%ED%95%9C%EC%A4%84%EB%A1%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%88%EB%9F%AC%EC%98%A4%EA%B8%B0/</guid><description>&lt;p>코어 데이터는 익숙해지면 매우 편리한 기능을 제공해주지만 한번 사용하려고 할 때 마다 셋업해줘야 할 것들이 매우 많아서 처음 접해보는 개발자들에게 문턱이 높은 편이다.&lt;/p>
&lt;p>애플의 Core Data Programming Guide에서 데이터를 불러오기(fetch)위해 사용하는 코드는 다음과 같다.&lt;/p>
&lt;pre>NSManagedObjectContext *moc = [self managedObjectContext];
NSEntityDescription *entityDescription = [NSEntityDescription
entityForName:@"Employee" inManagedObjectContext:moc];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entityDescription];
// Set example predicate and sort orderings...
NSNumber *minimumSalary = ...;
NSPredicate *predicate = [NSPredicate predicateWithFormat:
@"(lastName LIKE[c] 'Worsley') AND (salary &amp;gt; %@)", minimumSalary];
[request setPredicate:predicate];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc]
initWithKey:@"firstName" ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
[sortDescriptor release];
NSError *error = nil;
NSArray *array = [moc executeFetchRequest:request error:&amp;error];
if (array == nil)
{
// Deal with error...
}
&lt;/pre>
&lt;p>단순히 데이터를 불러오기 위해 13줄이나 코드를 쓰는 것은 고역이다.&lt;/p></description></item><item><title>Objective-C 런타임(runtime) 내부 동작 분석</title><link>https://www.letmecompile.com/objective-c-%EB%9F%B0%ED%83%80%EC%9E%84runtime-%EB%82%B4%EB%B6%80-%EB%8F%99%EC%9E%91-%EB%B6%84%EC%84%9D/</link><pubDate>Sat, 17 Aug 2013 02:44:54 +0000</pubDate><guid>https://www.letmecompile.com/objective-c-%EB%9F%B0%ED%83%80%EC%9E%84runtime-%EB%82%B4%EB%B6%80-%EB%8F%99%EC%9E%91-%EB%B6%84%EC%84%9D/</guid><description>&lt;p>맥의 코코아(Cocoa)나 iOS의 코코아터치(CocoaTouch) 프레임워크를 다루다보면 Objective-C 런타임(runtime)과 항상 맞닥뜨리게 된다. 입문자들의 경우에는 프레임워크를 이용해서 잘 동작하는 Objective-C 코드를 작성하는데만 급급하지만, 해당 객체가 응답할 수 없는 잘못된 메시지를 보내서 런타임 에러가 나는 것 등의 여러가지 예외 상황을 겪게되면 점점 Objective-C 런타임이 어떻게 동작하는지 궁금해지게 된다. 필자도 이것이 궁금해져서 구글링을 하다가 설명이 잘되어있는 Colin Wheeler의 포스팅[^1]을 발견했다. 본 글의 내용들은 이 포스팅을 번역하여 작성되었고 내용상의 설명순서는 좀더 이해하기 쉽게 재배열 하였다. 부분적으로 추가 설명이 더 필요한 부문은 애플의 Objective-C Runtime Programming Guide[^2]도 참조했다.&lt;/p></description></item><item><title>코어데이터(Core Data)와 데이터베이스의 차이</title><link>https://www.letmecompile.com/%EC%BD%94%EC%96%B4%EB%8D%B0%EC%9D%B4%ED%84%B0core-data%EC%99%80-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4%EC%9D%98-%EC%B0%A8%EC%9D%B4/</link><pubDate>Wed, 14 Aug 2013 20:53:51 +0000</pubDate><guid>https://www.letmecompile.com/%EC%BD%94%EC%96%B4%EB%8D%B0%EC%9D%B4%ED%84%B0core-data%EC%99%80-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4%EC%9D%98-%EC%B0%A8%EC%9D%B4/</guid><description>&lt;p>애플의 Core Data Programming Guide 문서에는 코어데이터(Core Data)가 데이터베이스가 아니라고 명시되어있다. 하지만 코어데이터와 데이터베이스 둘다 검색가능하고, 영속적인 저장소를 제공하는 방법이므로 구체적으로 무엇이 다른지는 명확하지 않다. 이 포스트에서는 코어데이터가 동작하는 방법을 살펴보면서 왜 코어데이터가 일반적인 SQL 데이터베이스와 다른지 비교해 볼 것이다(코어데이터를 사용하더라도 실제 뒷단의 저장소는 SQL 데이터베이스가 사용되는 경우도 있다).&lt;/p>
&lt;h2 id="소개">소개&lt;/h2>
&lt;p>코어데이터와 SQL 데이터베이스 모두 구조화된 데이터를 검색가능한 저장소에 저장하는 수단을 제공해준다. 일반적으로 개발자들이 데이터베이스에 익숙하고, 코어데이터가 실제로 뒷단에서 SQLite 데이터 베이스를 사용하여 데이터를 저장하는 경우도 있기 때문에 코어데이터가 마치 SQLite의 wrapper인 것처럼 생각되기 쉽다.&lt;/p></description></item><item><title>iOS, Mac 앱 개발시 하위 호환성 유지</title><link>https://www.letmecompile.com/ios-mac-os-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EC%8B%9C-%ED%95%98%EC%9C%84-%ED%98%B8%ED%99%98%EC%84%B1-%EC%9C%A0%EC%A7%80/</link><pubDate>Thu, 25 Jul 2013 20:20:55 +0000</pubDate><guid>https://www.letmecompile.com/ios-mac-os-%EC%95%B1-%EA%B0%9C%EB%B0%9C%EC%8B%9C-%ED%95%98%EC%9C%84-%ED%98%B8%ED%99%98%EC%84%B1-%EC%9C%A0%EC%A7%80/</guid><description>&lt;p>맥OS에서 개발할때, 최신 버전의 SDK를 사용하면 최신 기능들을 이용해서 더 멋진 어플리케이션을 손쉽게 개발 할 수 있다. 하지만 결국 하위 호환성(backward compatibility)을 고려하지 않으면 이전 버전의 OS에서 제대로 작동하지 않는 사태가 종종 발생한다. 이러한 상황은 MacOS 뿐 아니라 iOS에서도 동일하게 적용된다.&lt;/p>
&lt;p>현재 필자의 개발환경은 다음과 같다.&lt;/p>
&lt;ul>
&lt;li>MacOS 10.7 (Lion)&lt;/li>
&lt;li>XCode 4.6.2 with MacOS SDK 10.8 (Mountain Lion)&lt;/li>
&lt;/ul>
&lt;p>하지만 다음 링크에서 볼 수 있듯이 &lt;a href="http://chitika.com/os-x-version-distribution">http://chitika.com/os-x-version-distribution&lt;/a> 아직도 10.6(Snow leopard)가 점유율이 가장 높아서, 현재 개발중인 어플리케이션은 최소 스노우 레오파드를 타겟으로 개발을 하기로 마음을 먹었다. 이런 상황에서 호환성을 유지하려면 어떤 점들이 고려되어야 하는지 살펴보도록 하자.&lt;/p></description></item></channel></rss>