<?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>apple · michaelprimeaux.com</title><link>https://michaelprimeaux.com/en/tags/apple/</link><description>Parallel and Distributed Systems</description><generator>Hugo</generator><language>en</language><managingEditor>michael@michaelprimeaux.com (Michael Primeaux)</managingEditor><webMaster>michael@michaelprimeaux.com (Michael Primeaux)</webMaster><copyright>&#169; 2026 Michael Primeaux</copyright><lastBuildDate>Tue, 29 May 2012 00:06:00 +0000</lastBuildDate><atom:link href="https://michaelprimeaux.com/en/tags/apple/index.xml" rel="self" type="application/rss+xml"/><image><url>https://michaelprimeaux.com/sixafter-logo-150x150.png</url><title>michaelprimeaux.com</title><link>https://michaelprimeaux.com/en/</link></image><item><title>Apple WWDC 2012</title><link>https://michaelprimeaux.com/en/posts/2012-04-29-apple-wwdc-2012/</link><pubDate>Tue, 29 May 2012 00:06:00 +0000</pubDate><author>michael@michaelprimeaux.com (Michael Primeaux)</author><guid>https://michaelprimeaux.com/en/posts/2012-04-29-apple-wwdc-2012/</guid><description/><content:encoded><![CDATA[<p>I’ve attended the 
<a href="https://developer.apple.com/wwdc/" class="link-external" rel="noopener noreferrer" target="_blank">Apple WWDC
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 for the past five years and, of course, look forward to this year’s event, which sold out in less than two hours. I am fortunate to have a ticket! Two years ago, the WWDC sold out in approximately two weeks; last year it sold out in approximately 10 hours. What an amazing trend.</p>
<p>Apple did enact a very important 
<a href="https://developer.apple.com/wwdc/tickets/" class="link-external" rel="noopener noreferrer" target="_blank">change
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 this year. All WWDC tickets (including activation codes) are non-transferable. The new rules are certainly worth reading.</p>
<p>I suspect we’ll likely get a preview at iOS 6 and of course the latest developments with OS X Mountain Lion. That said, I don’t expect we’ll see an unveiling of Apple’s latest iPhone but I remain hopeful. Regardless, I’m sure the technical content and overall event will not disappoint.</p>
<p>I look forward to seeing you there.</p>]]></content:encoded><category>apple</category><category>wwdc</category></item><item><title>Universal Frameworks for iOS</title><link>https://michaelprimeaux.com/en/posts/2011-10-30-universal-frameworks-for-ios/</link><pubDate>Sun, 30 Oct 2011 00:06:00 +0000</pubDate><author>michael@michaelprimeaux.com (Michael Primeaux)</author><guid>https://michaelprimeaux.com/en/posts/2011-10-30-universal-frameworks-for-ios/</guid><description>As of the time of this writing, Xcode does not offer a framework project to for Cocoa Touch (only Cocoa). Apple’s primary reasons behind this decision are security, performance, and memory footprint. As such Xcode limits iOS developers to the Static Library project type. Static libraries are quite cumbersome to work with since we must make compile-time decisions when working with the iOS Simulator or an iOS device. The iOS simulator on Mac OS X uses the i386 architecture whereas the iOS devices use either armv6 (opens in a new window) or armv7 (opens in a new window) .</description><content:encoded><![CDATA[<p>As of the time of this writing, Xcode does not offer a framework project to for Cocoa Touch (only Cocoa). Apple’s primary reasons behind this decision are security, performance, and memory footprint.  As such Xcode limits iOS developers to the Static Library project type. Static libraries are quite cumbersome to work with since we must make compile-time decisions when working with the iOS Simulator or an iOS device. The iOS simulator on Mac OS X uses the i386 architecture whereas the iOS devices use either 
<a href="http://en.wikipedia.org/wiki/ARM_architecture" class="link-external" rel="noopener noreferrer" target="_blank">armv6
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 or 
<a href="http://en.wikipedia.org/wiki/ARM_architecture" class="link-external" rel="noopener noreferrer" target="_blank">armv7
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
.</p>
<p>Additionally, iOS 5 introduces a new compile-time memory management feature known as 
<a href="http://clang.llvm.org/docs/AutomaticReferenceCounting.html" class="link-external" rel="noopener noreferrer" target="_blank">Automatic Reference Counting (ARC)
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
. The abridged version is you will never need to type retain or release again, which dramatically simplifies the development process while reducing crashes and memory leaks. The compiler has a complete understanding of your objects, and releases each object the instant it is no longer used, so apps execute much faster, with predictable, smooth performance. However, it’ll take the community some time to refactor various open source libraries to support ARC. Therefore, we have a much larger need today than ever before to move these source files into static libraries that are compiled with ARC disabled so we can compile our primary applications with ARC enabled.</p>
<p>Alternatively, if you are including files that don’t yet support ARC in a project that is ARC enabled, you can set the -fno-objc-arc compiler flag for each of these files. To do this in Xcode, go to your active target and select the “Build Phases” tab. In the “Compiler Flags” column, set -fno-objc-arc for each of the source files. Of course, this can be a very laborious process.</p>
<p>Apple defines a 
<a href="http://developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/DynamicLibraries/100-Articles/OverviewOfDynamicLibraries.html" class="link-external" rel="noopener noreferrer" target="_blank">framework
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 as a bundle (a structured directory) that contains a dynamic shared library along with associated resources, such as nib files, image files, and header files. When you develop an application, your project links to one or more frameworks. For example, iOS application projects link by default to the Foundation, UIKit, and Core Graphics frameworks. Your code accesses the capabilities of a framework through the application programming interface (API), which is published by the framework through its header files. Because the library is dynamically shared, multiple applications can access the framework code and resources simultaneously. The system loads the code and resources of a framework into memory, as needed, and shares the one copy of a resource among all applications. A universal (or multi-architecture) file is nothing more than an application bundle.</p>
<p>As I mentioned above, iOS does not support dynamic shared libraries but using 
<a href="http://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man1/lipo.1.html" class="link-external" rel="noopener noreferrer" target="_blank">lipo
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 (a tool which comes with 
<a href="http://developer.apple.com/devcenter/ios" class="link-external" rel="noopener noreferrer" target="_blank">iOS SDK
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
) we are able to merge several static libraries into a single static library. By using lipo, we are able to create a static library that supports all architectures (armv6, armv7, and i386) packaged as a universal framework. Here’s how.</p>
<p>Within Xcode, either create a new iOS project or open an existing iOS project. If you do decide to create a new project then feel free to choose any application template you prefer. Which one you choose is irrelevant. Add a “Cocoa Bundle” target (not Cocoa Touch Bundle). Select the newly created bundle target in the left navigation panel, select the “Build Settings” tab and modify the following 
<a href="http://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/0-Introduction/introduction.html#//apple_ref/doc/uid/TP40003931-CH1-SW1" class="link-external" rel="noopener noreferrer" target="_blank">settings
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 as required:</p>
<ul>
<li><strong>Architectures</strong> (ARCHS): <em>Standard (armv6 armv7 armv7s)</em>. In Xcode 4.2, use the value of $(ARCHS_STANDARD_32_BIT). If you wish to compile for older devices then add a new line with a value of armv6. Please see 
<a href="https://devforums.apple.com/message/536368#536368" class="link-external" rel="noopener noreferrer" target="_blank">this
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 Apple Developer forum post for more details.</li>
<li><strong>Base SDK</strong> (SDKROOT). <em>Latest iOS (iOS X.X)</em>.</li>
<li><strong>Build Active Architecture Only</strong> (ONLY_ACTIVE_ARCH). <em>No</em>. This allows us to compile for armv6 and armv7.</li>
<li><strong>Valid Architecture</strong> (VALID_ARCHS): <em>Standard (armv6 armv7 armv7s)</em>. In Xcode 4.2 and greater, use the value of $(ARCHS_STANDARD_32_BIT). If you wish to compile for older devices then add a new line with a value of armv6.</li>
<li><strong>Dead Code Stripping</strong> (DEAD_CODE_STRIPPING): <em>No</em></li>
<li><strong>Link With Standard Libraries</strong> (LINK_WITH_STANDARD_LIBRARIES): <em>No</em></li>
<li><strong>Mach-O Type</strong> (MACH_O_TYPE): <em>Relocatable Object File</em>. This is the most important change. Here, we instruct the compiler to treat the Bundle as a relocatable file, by doing this, we can turn it into a framework with the wrapper setting.</li>
<li><strong>Wrapper Extension</strong> (WRAPPER_EXTENSION). <em>framework</em>. Here we change the Bundle to a Framework. To Xcode, frameworks is just a folder with the extension .framework, which has inside one or more compiled binary sources, resources and some folders, a folder, usually called Headers, contains all the public headers.</li>
<li><strong>Generate Debug Symbols</strong> (GCC_GENERATE_DEBUGGING_SYMBOLS): <em>No</em>.</li>
<li><strong>Generate Position-Dependent Code</strong> (GCC_DYNAMIC_NO_PIC): <em>No</em></li>
<li><strong>Targeted Device Family</strong> (TARGETED_DEVICE_FAMILY). <em>iPhone/iPad</em>.</li>
</ul>
<p>Here are the steps&hellip;</p>
<ul>
<li>With the bundle target still in focus, select the “Info” tab and ensure the “Bundle OS Type code” is equal to FMWK.</li>
<li>Add any source code and resources to the bundle. With the bundle target selected, click the “Build Phase” tab. At the bottom, press the “Add Phase” button and then “Add Copy Headers“.</li>
<li>Open the newly created “Copy Headers” section and separate your public headers from private or project headers.</li>
<li>Open the “Compile Source” section and add any .m, .c, .mm, .cpp and any other compilable source file. If your framework contains any non-compilable files such as images, sounds, and other resources, you can add them to the “Copy Bundle Resources” section.</li>
</ul>
<p>You can access any non-compilable resources by using NSBundle.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="p">[[</span><span class="n">NSBundle</span> <span class="n">mainBundle</span><span class="p">]</span> <span class="nl">pathForResource</span><span class="p">:</span><span class="s">@&#34;MyFramework.framework/Resources/FileName&#34;</span> <span class="nl">ofType</span><span class="p">:</span><span class="s">@&#34;fileExtension&#34;</span><span class="p">];</span>
</span></span></code></pre></div><p>Next we’ll create a new Aggregate Target. As mentioned earlier, to join both architectures products into one, we must to use lipo.</p>
<ul>
<li>Add a new target by pressing the “Add Target” button.</li>
<li>Under the Cocoa Touch section, select the “Other” subcategory and then choose the “Aggregate” target. The “Product Name” is arbitrary.</li>
<li>Add a new “Run Script” phase under this newly created target. Copy and paste the following script into the “Run Script” phase.</li>
</ul>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-shell" data-lang="shell"><span class="line"><span class="cl"><span class="c1"># The framework name and version</span>
</span></span><span class="line"><span class="cl"><span class="nv">X_FRAMEWORK_NAME</span><span class="o">=</span>CoreFramework
</span></span><span class="line"><span class="cl"><span class="nv">X_FRAMEWORK_VERSION</span><span class="o">=</span>A
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># This folder contains the final output of the framework.</span>
</span></span><span class="line"><span class="cl"><span class="nv">X_INSTALL_DIR</span><span class="o">=</span><span class="si">${</span><span class="nv">SRCROOT</span><span class="si">}</span>/Products/<span class="si">${</span><span class="nv">X_FRAMEWORK_NAME</span><span class="si">}</span>.framework
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># This working directory will be deleted after completion.</span>
</span></span><span class="line"><span class="cl"><span class="nv">X_WORKING_DIR</span><span class="o">=</span>build
</span></span><span class="line"><span class="cl"><span class="nv">X_DEVICE_DIR</span><span class="o">=</span><span class="si">${</span><span class="nv">X_WORKING_DIR</span><span class="si">}</span>/<span class="si">${</span><span class="nv">CONFIGURATION</span><span class="si">}</span>-iphoneos/<span class="si">${</span><span class="nv">X_FRAMEWORK_NAME</span><span class="si">}</span>.framework
</span></span><span class="line"><span class="cl"><span class="nv">X_SIMULATOR_DIR</span><span class="o">=</span><span class="si">${</span><span class="nv">X_WORKING_DIR</span><span class="si">}</span>/<span class="si">${</span><span class="nv">CONFIGURATION</span><span class="si">}</span>-iphonesimulator/<span class="si">${</span><span class="nv">X_FRAMEWORK_NAME</span><span class="si">}</span>.framework
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;******************************************************&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;X_DEVICE_DIR = </span><span class="si">${</span><span class="nv">X_DEVICE_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;X_SIMULATOR_DIR = </span><span class="si">${</span><span class="nv">X_SIMULATOR_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;******************************************************&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;SYMROOT = </span><span class="si">${</span><span class="nv">SYMROOT</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;OBJROOT = </span><span class="si">${</span><span class="nv">OBJROOT</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;PROJECT_DIR = </span><span class="si">${</span><span class="nv">PROJECT_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;CONFIGURATION_BUILD_DIR = </span><span class="si">${</span><span class="nv">CONFIGURATION_BUILD_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;CONFIGURATION = </span><span class="si">${</span><span class="nv">CONFIGURATION</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;CONFIGURATION_TEMP_DIR = </span><span class="si">${</span><span class="nv">CONFIGURATION_TEMP_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;DERIVED_FILE_DIR = </span><span class="si">${</span><span class="nv">DERIVED_FILE_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;BUILD_PRODUCTS_DIR = </span><span class="si">${</span><span class="nv">BUILT_PRODUCTS_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;BUILD_DIR = </span><span class="si">${</span><span class="nv">BUILD_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;TARGET_TEMP_DIR = </span><span class="si">${</span><span class="nv">TARGET_TEMP_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;PROJECT_TEMP_DIR = </span><span class="si">${</span><span class="nv">PROJECT_TEMP_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;PRODUCT_NAME = </span><span class="si">${</span><span class="nv">PRODUCT_NAME</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="nb">echo</span> <span class="s2">&#34;******************************************************&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Build both simulator and device architectures.</span>
</span></span><span class="line"><span class="cl">xcodebuild clean
</span></span><span class="line"><span class="cl">xcodebuild -configuration <span class="si">${</span><span class="nv">CONFIGURATION</span><span class="si">}</span> -target <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_FRAMEWORK_NAME</span><span class="si">}</span><span class="s2">&#34;</span> -sdk iphoneos -SYMROOT<span class="o">=</span><span class="si">${</span><span class="nv">SYMROOT</span><span class="si">}</span> -OBJROOT<span class="o">=</span><span class="si">${</span><span class="nv">OBJROOT</span><span class="si">}</span>
</span></span><span class="line"><span class="cl">xcodebuild -configuration <span class="si">${</span><span class="nv">CONFIGURATION</span><span class="si">}</span> -target <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_FRAMEWORK_NAME</span><span class="si">}</span><span class="s2">&#34;</span> -sdk iphonesimulator -SYMROOT<span class="o">=</span><span class="si">${</span><span class="nv">SYMROOT</span><span class="si">}</span> -OBJROOT<span class="o">=</span><span class="si">${</span><span class="nv">OBJROOT</span><span class="si">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Clean the oldest.</span>
</span></span><span class="line"><span class="cl"><span class="k">if</span> <span class="o">[</span> -d <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">&#34;</span> <span class="o">]</span>
</span></span><span class="line"><span class="cl"><span class="k">then</span>
</span></span><span class="line"><span class="cl">rm -rf <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl"><span class="k">fi</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Recreate the folder structure for the final product binaries.</span>
</span></span><span class="line"><span class="cl">mkdir -p <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">mkdir -p <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">/Versions&#34;</span>
</span></span><span class="line"><span class="cl">mkdir -p <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">/Versions/</span><span class="si">${</span><span class="nv">X_FRAMEWORK_VERSION</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">mkdir -p <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">/Versions/</span><span class="si">${</span><span class="nv">X_FRAMEWORK_VERSION</span><span class="si">}</span><span class="s2">/Resources&#34;</span>
</span></span><span class="line"><span class="cl">mkdir -p <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">/Versions/</span><span class="si">${</span><span class="nv">X_FRAMEWORK_VERSION</span><span class="si">}</span><span class="s2">/Headers&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Create the required symbolic links. Please note the paths MUST relative, </span>
</span></span><span class="line"><span class="cl"><span class="c1"># otherwise the symbolic links will be invalid when the folder is copied/moved.</span>
</span></span><span class="line"><span class="cl">ln -s <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_FRAMEWORK_VERSION</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">/Versions/Current&#34;</span>
</span></span><span class="line"><span class="cl">ln -s <span class="s2">&#34;Versions/Current/Headers&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">/Headers&#34;</span>
</span></span><span class="line"><span class="cl">ln -s <span class="s2">&#34;Versions/Current/Resources&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">/Resources&#34;</span>
</span></span><span class="line"><span class="cl">ln -s <span class="s2">&#34;Versions/Current/</span><span class="si">${</span><span class="nv">X_FRAMEWORK_NAME</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">X_FRAMEWORK_NAME</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Copy the headers and resources files to the final product folder.</span>
</span></span><span class="line"><span class="cl">cp -R <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_DEVICE_DIR</span><span class="si">}</span><span class="s2">/Headers/&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">/Versions/</span><span class="si">${</span><span class="nv">X_FRAMEWORK_VERSION</span><span class="si">}</span><span class="s2">/Headers/&#34;</span>
</span></span><span class="line"><span class="cl">cp -R <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_DEVICE_DIR</span><span class="si">}</span><span class="s2">/&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">/Versions/</span><span class="si">${</span><span class="nv">X_FRAMEWORK_VERSION</span><span class="si">}</span><span class="s2">/Resources/&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Remove artifacts from the resources folder.</span>
</span></span><span class="line"><span class="cl">rm -r <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">/Versions/</span><span class="si">${</span><span class="nv">X_FRAMEWORK_VERSION</span><span class="si">}</span><span class="s2">/Resources/Headers&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">/Versions/</span><span class="si">${</span><span class="nv">X_FRAMEWORK_VERSION</span><span class="si">}</span><span class="s2">/Resources/</span><span class="si">${</span><span class="nv">X_FRAMEWORK_NAME</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Use lipo to merge both binary files (i386 + armv6/armv7) into one universal files.</span>
</span></span><span class="line"><span class="cl">lipo -create <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_DEVICE_DIR</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">X_FRAMEWORK_NAME</span><span class="si">}</span><span class="s2">&#34;</span> <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_SIMULATOR_DIR</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">X_FRAMEWORK_NAME</span><span class="si">}</span><span class="s2">&#34;</span> -output <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_INSTALL_DIR</span><span class="si">}</span><span class="s2">/Versions/</span><span class="si">${</span><span class="nv">X_FRAMEWORK_VERSION</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">X_FRAMEWORK_NAME</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1"># Remove the working directory</span>
</span></span><span class="line"><span class="cl">rm -r <span class="s2">&#34;</span><span class="si">${</span><span class="nv">X_WORKING_DIR</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span></code></pre></div><p>You’ll need to modify the first non-comment line in the script to be equal to the product name of your framework bundle target.</p>
<p>Now build the Aggregate target. It does not matter which architecture you select to build (iOS Device or Simulator) since the script creates a working folder, compiles the framework target twice (once for the iOS device and once for the iOS Simulator) and generates the output to a folder named “Products” located in the $(SRCROOT) root folder</p>
<p>If you previously upgraded from Xcode 3.x to 4.2, then your existing (SYMROOT) value will very likely cause the above script to fail. The failure is caused because the script expects your (SYMROOT) value to be set to the new Xcode 4 value of “build”, which refers to a relative path to $(SRCROOT). Unfortunately, you are not able to modify this setting in Xcode 4 due to an already reported bug. To work around this bug, close Xcode and simply delete the existing SYMROOT key and value from your com.apple.dt.Xcode.plist file, which is located in ~/Library/Preferences/.</p>
<p>Isn’t it about time for the WWDC to be here again?</p>]]></content:encoded><category>software engineering</category><category>apple</category></item><item><title>Efficient Memory Usage in iOS</title><link>https://michaelprimeaux.com/en/posts/2011-06-19-efficient-memory-usage-in-ios/</link><pubDate>Sun, 19 Jun 2011 00:06:00 +0000</pubDate><author>michael@michaelprimeaux.com (Michael Primeaux)</author><guid>https://michaelprimeaux.com/en/posts/2011-06-19-efficient-memory-usage-in-ios/</guid><description>I wrote a post some time back on the value of singletons in a garbage collected language as an important component of scalability. The majority of my work these days targets Apple iOS (opens in a new window) devices and so a reduced memory footprint and overall memory management is not only fundamental but paramount. The use of singleton objects and an effective caching strategy are simple patterns to get you started.</description><content:encoded><![CDATA[<p>I wrote a 
<a href="/blog/2011/05/11/a-word-on-elegance/">post</a>
 some time back on the value of singletons in a garbage collected language as an important component of scalability. The majority of my work these days targets Apple 
<a href="http://en.wikipedia.org/wiki/IOS_%28Apple%29" class="link-external" rel="noopener noreferrer" target="_blank">iOS
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 devices and so a reduced memory footprint and overall memory management is not only fundamental but paramount. The use of singleton objects and an effective caching strategy are simple patterns to get you started.</p>
<p>I suggest reading Apple’s 
<a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading" class="link-external" rel="noopener noreferrer" target="_blank">Thread Programming Guide
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 as a prerequisite, which also covers some of the basic concepts behind Blocks and 
<a href="http://developer.apple.com/library/mac/#featuredarticles/BlocksGCD/_index.html" class="link-external" rel="noopener noreferrer" target="_blank">Grand Central Dispatch (GCD)
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
.</p>
<h2 id="singletons" class="heading">Singletons
    <a class="heading__anchor" href="#singletons" tabindex="-1" aria-hidden="true"
        title="Link to this section">
<svg class="icon icon--hash" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M5 9h14M5 15h14M10 3.5 8 20.5M16 3.5l-2 17"/>
</svg>
</a>
</h2>
<p>For purposes of this discussion, a singleton is a class that only allows a single instance of itself to be created within an operating system process.</p>
<p>Apple’s 
<a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html%23//apple_ref/doc/uid/TP40002974-CH4-SW32" class="link-external" rel="noopener noreferrer" target="_blank">documentation
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 on creating a singleton recommends a pattern that works for most iOS applications but is not thread-safe. Beginning with iOS 2.0 and prior to iOS 4.1, one of the most widely used methods to introduce a thread-safe singleton was through the use of the 
<a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Multithreading/ThreadSafety/ThreadSafety.html#//apple_ref/doc/uid/10000057i-CH8-SW3" class="link-external" rel="noopener noreferrer" target="_blank">@synchronized
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 directive.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="p">+</span> <span class="p">(</span><span class="n">MyClass</span><span class="o">*</span><span class="p">)</span> <span class="nf">instance</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">static</span> <span class="n">MyClass</span> <span class="o">*</span><span class="n">gInstance</span> <span class="o">=</span> <span class="nb">nil</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">@synchronized</span><span class="p">(</span><span class="nb">self</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span><span class="p">(</span><span class="nb">nil</span> <span class="o">==</span> <span class="n">gInstance</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="n">gInstance</span> <span class="o">=</span> <span class="p">[[</span><span class="n">MyClass</span> <span class="n">alloc</span><span class="p">]</span> <span class="n">init</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">gInstance</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>There are a few inefficiencies with this approach because not only generates a recursive mutex lock but also introduces an exception handler. Specifically, Apple’s documentation indicates that as a precautionary measure, the @synchronized block implicitly adds an exception handler to the protected code. This handler automatically releases the mutex in the event that an exception is thrown. This means that in order to use the @synchronized directive, you must also enable Objective-C exception handling in your code. If you do not want the additional overhead caused by the implicit exception handler, you should consider using the lock classes.</p>
<p>At the time of this writing, the @synchronized directive turns into this basic pseudo-code:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="kt">id</span> <span class="n">_eval_once</span> <span class="o">=</span> <span class="p">;</span>
</span></span><span class="line"><span class="cl"><span class="n">objc_sync_enter</span><span class="p">(</span> <span class="n">_eval_once</span> <span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="k">@try</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="cm">/* code goes here */</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="k">@finally</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">objc_sync_exit</span><span class="p">(</span> <span class="n">_eval_once</span> <span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>For implementation details see: 
<a href="http://www.opensource.apple.com/source/objc4/objc4-437.1/runtime/objc-sync.m" class="link-external" rel="noopener noreferrer" target="_blank">http://www.opensource.apple.com/source/objc4/objc4-437.1/runtime/objc-sync.m
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
</p>
<p>Much of Apple’s sample code prior to iOS 4.0 use this approach. There is a technically more efficient and lock-free approach for applications that target operating systems earlier than Mac OS X version 10.5 or iOS 4.0.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="p">+</span> <span class="p">(</span><span class="n">MyClass</span><span class="o">*</span><span class="p">)</span> <span class="nf">gInstance</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">static</span> <span class="kt">void</span> <span class="o">*</span> <span class="k">volatile</span> <span class="n">gInstance</span> <span class="o">=</span> <span class="nb">nil</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="n">gInstance</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">MyClass</span> <span class="o">*</span><span class="n">temp</span> <span class="o">=</span> <span class="p">[</span><span class="n">MyClass</span> <span class="p">[</span><span class="n">alloc</span><span class="p">]</span> <span class="n">init</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">OSAtomicCompareAndSwapPtrBarrier</span><span class="p">(</span><span class="mh">0x0</span><span class="p">,</span> <span class="n">temp</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">gInstance</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="p">[</span><span class="n">temp</span> <span class="k">release</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">gInstance</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>You can read more about preferred versions of the atomic and synchronization operations 
<a href="http://developer.apple.com/library/mac/#documentation/DriversKernelHardware/Reference/libkern_ref/OSAtomic_h/index.html" class="link-external" rel="noopener noreferrer" target="_blank">here
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
.</p>
<p>For applications that target operating systems equal to or greater than Mac OS X 10.6 or iOS 4.0, the recommended singleton pattern uses dispatch_once, which relies on components of Grand Central Dispatch (GCD).</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-objc" data-lang="objc"><span class="line"><span class="cl"><span class="p">+</span> <span class="p">(</span><span class="n">MyClass</span> <span class="o">*</span><span class="p">)</span> <span class="nf">instance</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="k">static</span> <span class="n">MyClass</span><span class="o">*</span> <span class="n">gInstance</span> <span class="o">=</span> <span class="nb">nil</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="k">static</span> <span class="n">dispatch_once_t</span> <span class="n">pred</span><span class="p">;</span>
</span></span><span class="line"><span class="cl"> 
</span></span><span class="line"><span class="cl">    <span class="n">dispatch_once</span><span class="p">(</span><span class="o">&amp;</span><span class="n">pred</span><span class="p">,</span> <span class="o">^</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">gInstance</span> <span class="o">=</span> <span class="p">[[</span><span class="n">MyClass</span> <span class="n">alloc</span><span class="p">]</span> <span class="n">init</span><span class="p">];</span>
</span></span><span class="line"><span class="cl">    <span class="p">});</span>
</span></span><span class="line"><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">gInstance</span><span class="p">);</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>It should go without saying but I’ll do so for completeness. All instance-level methods of classes that implement a singleton pattern 
<a href="http://www.ietf.org/rfc/rfc2119.txt" class="link-external" rel="noopener noreferrer" target="_blank">MUST
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 be thread-safe.</p>
<h2 id="nscache" class="heading">NSCache
    <a class="heading__anchor" href="#nscache" tabindex="-1" aria-hidden="true"
        title="Link to this section">
<svg class="icon icon--hash" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M5 9h14M5 15h14M10 3.5 8 20.5M16 3.5l-2 17"/>
</svg>
</a>
</h2>
<p>I suspect this class remains relatively unused by most iOS developers. 
<a href="http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/NSCache_Class/Reference/Reference.html" class="link-external" rel="noopener noreferrer" target="_blank">NSCache
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 is essentially a container that it stores key-value pairs but unfortunately does so without an O(1) time complexity (like that of 
<a href="http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSMutableDictionary_Class/Reference/Reference.html" class="link-external" rel="noopener noreferrer" target="_blank">NSMutableDictionary
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
) but does automatically evicts objects from its store when the ‘cost’ (a heuristic that of course involves memory pressure) of the cache rises above a configurable threshold.</p>
<p>Per Apple’s documentation, NSCache objects differ from other mutable collections in a few ways:</p>
<ul>
<li>The NSCache class incorporates various auto-removal policies, which ensure that it does not use too much of the system’s memory. The system automatically carries out these policies if memory is needed by other applications. When invoked, these policies remove some items from the cache, minimizing its memory footprint.</li>
<li>You can add, remove, and query items in the cache from different threads without having to lock the cache yourself.</li>
<li>Retrieving something from an NSCache object returns an autoreleased result.</li>
<li>Unlike an NSMutableDictionary object, a cache does not copy the key objects that are put into it.These features are necessary for the NSCache class, as the cache may decide to automatically mutate itself asynchronously behind the scenes if it is called to free up memory.</li>
</ul>
<p>Though not required, NSCache works in conjunction with objects that implement the 
<a href="http://developer.apple.com/library/mac/documentation/cocoa/reference/NSDiscardableContent_Protocol/Reference/Reference.html#//apple_ref/occ/intf/NSDiscardableContent" class="link-external" rel="noopener noreferrer" target="_blank">NSDiscardableContent
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 protocol in that the 
<a href="http://developer.apple.com/library/mac/documentation/cocoa/reference/NSDiscardableContent_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/NSDiscardableContent/discardContentIfPossible" class="link-external" rel="noopener noreferrer" target="_blank">discardContentIfPossible
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 method is called when an object is removed.</p>
<p>The two most widely used caching strategies are proactive and reactive loading.</p>
<ol>
<li><strong>Proactive Cache Loading</strong>. A proactive cache loading strategy attempts to retrieve all required state when a process or application starts and cache it for the lifetime of the process or application. A decision to use a proactive cache loading strategy is generally done so in conjunction with either asynchronous pull loading based on expected not actual usage of the information being cached or notification-based loading whereby an application’s services are notified when cached state changes.</li>
<li><strong>Reactive Cache Loading</strong>. A reactive cache loading strategy retrieves data as it is requested by the application and caches it for future requests. A decision to use a reactive cache loading strategy is generally done so in conjunction with synchronous pull loading since the pattern is relatively easy to test and implement.</li>
</ol>
<p>Regardless of the selected caching strategy, determining a cache expiration policy is is key for most applications. There are a plethora of expiration policy patterns but the majority of them fall into the following general categories:</p>
<ul>
<li><strong>Time-based</strong>. Cached information is invalidated based on relative (sliding window) or absolute time periods.</li>
<li><strong>Notification-based</strong>. Cached information is invalidated based on instructions from a source.</li>
<li><strong>Counter-based</strong>. Cached information is invalidated based on a reference counts.</li>
</ul>
<p>Regardless of the expiration policy, scavenging based on memory pressure and other heuristics are key to a proper cache design and symmetry of that design is a key component in any distributed algorithm.</p>
<p>For most applications, a reactive cache loading strategy with a synchronous pull model is the most appropriate option. NSCache does evict objects based on memory pressure and so I strongly recommend you implement the NSDiscardableContent protocol for any objects you plan to store in NSCache. NSDiscardableContent is a simple counter-based pattern. For information stored in NSCache that represents NSData objects, Apple provides the 
<a href="http://developer.apple.com/library/mac/documentation/cocoa/reference/NSPurgeableData_Class/Reference/Reference.html#//apple_ref/occ/cl/NSPurgeableData" class="link-external" rel="noopener noreferrer" target="_blank">NSPurgeableData
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 class. NSPurgeable data inherits from NSMutableData and is available in iOS 4.0 and Mac OS X 10.6 and later. A description of how to use this class can be found be reading 
<a href="http://developer.apple.com/library/mac/#technotes/CachingPurgeableMemory/Introduction/Introduction.html" class="link-external" rel="noopener noreferrer" target="_blank">Caching and Purgeable Memory
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
.</p>
<p>I’d like to make one last point. Please be careful not to over-engineer your caching strategy but be elegant about your design.</p>]]></content:encoded><category>software engineering</category><category>apple</category></item><item><title>Apple WWDC 2011</title><link>https://michaelprimeaux.com/en/posts/2011-06-08-apple-wwdc-2011/</link><pubDate>Wed, 08 Jun 2011 00:06:00 +0000</pubDate><author>michael@michaelprimeaux.com (Michael Primeaux)</author><guid>https://michaelprimeaux.com/en/posts/2011-06-08-apple-wwdc-2011/</guid><description>I’ve attended the Apple WWDC (opens in a new window) for the past 4 years and it’s been nothing short of exciting each year. This year, event sold out in 10 hours and so I am fortunate to have a spot. In contrast to last year, the event sold out in approxiately 14 days. Steve Jobs delivered a very interesting keynote speech (opens in a new window) with features that in my opinion ensure Apple will continue to stay a few years ahead of all other mobile companies. It’s amazing to think how far we’ve come since my first 4 Macs, which were the Apple II (opens in a new window) , IIc (opens in a new window) , IIe (opens in a new window) , and IIGS (opens in a new window) . Ahhh…and let us not forget other microcomputers such as the Amiga (opens in a new window) , Commodore 64 (opens in a new window) , and the earlier TRS-80 (opens in a new window) (also known as the “trash 80″). The TRS-80 was in fact technically my first personal computer.</description><content:encoded><![CDATA[<p>I’ve attended the 
<a href="http://developer.apple.com/wwdc/" class="link-external" rel="noopener noreferrer" target="_blank">Apple WWDC
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 for the past 4 years and it’s been nothing short of exciting each year. This year, event sold out in 10 hours and so I am fortunate to have a spot. In contrast to last year, the event sold out in approxiately 14 days. Steve Jobs delivered a very interesting 
<a href="http://events.apple.com.edgesuite.net/11piubpwiqubf06/event/" class="link-external" rel="noopener noreferrer" target="_blank">keynote speech
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 with features that in my opinion ensure Apple will continue to stay a few years ahead of all other mobile companies. It’s amazing to think how far we’ve come since my first 4 Macs, which were the 
<a href="http://en.wikipedia.org/wiki/Apple_II" class="link-external" rel="noopener noreferrer" target="_blank">Apple II
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
, 
<a href="http://en.wikipedia.org/wiki/Apple_IIc" class="link-external" rel="noopener noreferrer" target="_blank">IIc
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
, 
<a href="http://en.wikipedia.org/wiki/Apple_IIe" class="link-external" rel="noopener noreferrer" target="_blank">IIe
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
, and 
<a href="http://en.wikipedia.org/wiki/Apple_IIGS" class="link-external" rel="noopener noreferrer" target="_blank">IIGS
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
. Ahhh…and let us not forget other microcomputers such as the 
<a href="http://en.wikipedia.org/wiki/Amiga" class="link-external" rel="noopener noreferrer" target="_blank">Amiga
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
, 
<a href="http://en.wikipedia.org/wiki/Commodore_64" class="link-external" rel="noopener noreferrer" target="_blank">Commodore 64
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
, and the earlier 
<a href="http://en.wikipedia.org/wiki/TRS-80" class="link-external" rel="noopener noreferrer" target="_blank">TRS-80
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 (also known as the “trash 80″).  The TRS-80 was in fact technically my first personal computer.</p>
<p>Here are a few very interesting statistics at the time of this writing:</p>
<ul>
<li>There are over 225 million iOS devices worldwide.</li>
<li>Apple represents a 48% share of the tablet and mobile market.</li>
<li>25 million iPads have been sold to date.</li>
<li>There are 425,000 applications in the App Store with 90,000 of those applications specifically designed to run on the iPad.</li>
<li>The App Store has enjoyed over 14 billion downloads</li>
<li>Apple has 225 million credit card accounts.</li>
<li>Apple has shipped 54 million Macs and growing, which is a 28% growth over last year. To contrast this, PC growth is at a negative 1% growth over the same year.</li>
<li>73% of the Macs shipped today are notebooks</li>
</ul>
<p>These statistics are astounding.  I am of course not at liberty to discuss any information not made public by Apple regarding the upcoming technologies but it is sufficed to say Mac OS X Lion + 
<a href="http://www.apple.com/icloud/" class="link-external" rel="noopener noreferrer" target="_blank">iCloud
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 + 
<a href="http://www.apple.com/ios/ios5/" class="link-external" rel="noopener noreferrer" target="_blank">iOS 5
<svg class="icon icon--external" viewBox="0 0 24 24" width="20" height="20" fill="none" stroke="currentColor"
    stroke-width="1.75" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
    <path d="M14 4h6v6M20 4l-8.5 8.5"/>
    <path d="M18 14v5a1 1 0 0 1-1 1H5a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h5"/>
</svg>
<span class="visually-hidden"> (opens in a new window)</span>
</a>
 represents another leap in market share for Apple and a set of very useful features for consumers.</p>
]]></content:encoded><category>apple</category></item></channel></rss>