<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Milen's Writings</title>
		<description>Milen's Writings</description>		
		<link>http://milen.me/writings/</link>
		<atom:link href="/writings/feed.xml" rel="self" type="application/rss+xml" />
		
			
			<item>
				<title>Swift Unsafe Pointers</title>
				<description>&lt;p&gt;
Swift 3 has several different pointer-like types that allow interfacing with the outside world. This article provides a concise overview of &lt;code class=&quot;inline-code&quot;&gt;UnsafeRawPointer&lt;/code&gt;, &lt;code class=&quot;inline-code&quot;&gt;UnsafePointer&lt;/code&gt;, &lt;code class=&quot;inline-code&quot;&gt;AutoreleasingUnsafeMutablePointer&lt;/code&gt;, &lt;code class=&quot;inline-code&quot;&gt;Unmanaged&lt;/code&gt; and &lt;code class=&quot;inline-code&quot;&gt;OpaquePointer&lt;/code&gt;.
&lt;/p&gt;

&lt;p&gt;
Note that &lt;code class=&quot;inline-code&quot;&gt;UnsafeRawPointer&lt;/code&gt; and &lt;code class=&quot;inline-code&quot;&gt;UnsafePointer&lt;/code&gt; have mutable variants, namely &lt;code class=&quot;inline-code&quot;&gt;UnsafeMutableRawPointer&lt;/code&gt; and &lt;code class=&quot;inline-code&quot;&gt;UnsafeMutablePointer&lt;/code&gt;. I'll refer to both variants using the shorter names and clarify as required.
&lt;/p&gt;

&lt;p&gt;
In Swift 3, the pointer types now represent non-nullable pointers (&lt;code class=&quot;inline-code&quot;&gt;UnsafePointer&lt;/code&gt;, &lt;code class=&quot;inline-code&quot;&gt;UnsafeMutablePointer&lt;/code&gt;, &lt;code class=&quot;inline-code&quot;&gt;AutoreleasingUnsafeMutablePointer&lt;/code&gt;, &lt;code class=&quot;inline-code&quot;&gt;OpaquePointer&lt;/code&gt;, &lt;code class=&quot;inline-code&quot;&gt;Selector&lt;/code&gt; and &lt;code class=&quot;inline-code&quot;&gt;NSZone&lt;/code&gt;). This means you don't have to check whether they are &lt;code class=&quot;inline-code&quot;&gt;nil&lt;/code&gt; as nullability is expressed via the type system using optionals. This allows the preservation of nullability annotations when interacting with legacy APIs.
&lt;/p&gt;

&lt;h3 class=&quot;subheading&quot;&gt;UnsafeRawPointer&lt;/h3&gt;

&lt;p&gt;
&lt;code class=&quot;inline-code&quot;&gt;UnsafeRawPointer&lt;/code&gt; represents a untyped pointer (&lt;code class=&quot;inline-code&quot;&gt;void*&lt;/code&gt;) and is declared as a &lt;code class=&quot;inline-code&quot;&gt;struct&lt;/code&gt;:
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeRawPointer&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Strideable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Hashable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ... more code ...&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;distance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeRawPointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;advanced&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;by&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeRawPointer&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 class=&quot;subheading&quot;&gt;UnsafePointer&lt;/h3&gt;

&lt;p&gt;
&lt;code class=&quot;inline-code&quot;&gt;UnsafePointer&lt;/code&gt; represents a typed pointer. It's declared as a generic struct. Here's the mutable variant:
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeMutablePointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Pointee&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Strideable&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Hashable&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ... more code ...&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;pointee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Pointee&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;get&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;nonmutating&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;set&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;allocate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;capacity&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeMutablePointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Pointee&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;deallocate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;capacity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;to&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;newValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Pointee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;deinitialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeMutableRawPointer&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 class=&quot;subheading&quot;&gt;Memory State&lt;/h4&gt;

&lt;p&gt;
The memory referenced by an &lt;code class=&quot;inline-code&quot;&gt;UnsafeMutablePointer&lt;/code&gt; can be in one of the following states:
&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deallocated.&lt;/li&gt;
&lt;li&gt;Allocated but not initialised.&lt;/li&gt;
&lt;li&gt;Allocated and initialised.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
It's only safe to use the &lt;code class=&quot;inline-code&quot;&gt;pointee&lt;/code&gt; property if and only if the memory is allocated and initialised. This means you have to call &lt;code class=&quot;inline-code&quot;&gt;allocate()&lt;/code&gt;, &lt;code class=&quot;inline-code&quot;&gt;initialize()&lt;/code&gt;, &lt;code class=&quot;inline-code&quot;&gt;deinitialize()&lt;/code&gt; and &lt;code class=&quot;inline-code&quot;&gt;deallocate()&lt;/code&gt; in the correct order.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Allocate storage on the heap for UInt64 (8 bytes) and point to it&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;uint64Pointer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeMutablePointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UInt64&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;allocate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;capacity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// The memory state is undefined, so before using the pointee property, it must be initialised&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;uint64Pointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mh&quot;&gt;0xAABBCCDD&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;int value: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%X&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;uint64Pointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pointee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// prints AABBCCDD&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Treat the pointer as a pointer to UInt8&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;uint64Pointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;withMemoryRebound&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;capacity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeMutablePointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UInt8&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// When executing on a little endian machine, it will print DD,CC,BB,AA&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// On big endian, it will print AA,BB,CC,DD&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;first byte value: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%2X&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pointee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;second byte value: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%2X&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;advanced&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pointee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;third byte value: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%2X&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;advanced&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pointee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
  &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;fourth byte value: &quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;format&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;%2X&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;byte&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;advanced&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;by&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pointee&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;uint64Pointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deinitialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// `pointee` should not be used after being deinitialised&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// `uint64Pointer` can now be re-initialised&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;uint64Pointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deallocate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;capacity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// `uint64Pointer` cannot be used anymore&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 class=&quot;subheading&quot;&gt;Pointers to Reference Types&lt;/h4&gt;

&lt;p&gt;
It's important to realise that when &lt;code class=&quot;inline-code&quot;&gt;UnsafePointer&lt;/code&gt; is used with reference types, it does &lt;em&gt;not&lt;/em&gt; in fact point to an object but rather, it points to a managed reference (which itself points to an object). Reference type lvalues represent managed pointers which perform reference counting, so the storage of &lt;code class=&quot;inline-code&quot;&gt;let x: NSObject&lt;/code&gt; translates to &lt;code class=&quot;inline-code&quot;&gt;NSObject *x&lt;/code&gt;. Consequently, &lt;code class=&quot;inline-code&quot;&gt;UnsafeMutablePointer&amp;lt;NSObject&amp;gt;&lt;/code&gt; can be thought of as pointing to a &lt;code class=&quot;inline-code&quot;&gt;var x: NSObject&lt;/code&gt; and assigning through &lt;code class=&quot;inline-code&quot;&gt;pointee&lt;/code&gt; is equivalent to assigning to &lt;code class=&quot;inline-code&quot;&gt;var x&lt;/code&gt; (i.e., referencing counting will be performed). Let's illustrate with some code.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;c1&quot;&gt;// Allocate storage for `var x: NSObject` (NSObject *x), the memory state is undefined&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;objVarPointer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeMutablePointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSObject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;allocate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;capacity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Set the initial value to a new NSObject, equivalent to `var x = NSObject()`.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Underneath, it's equivalent to the following pseudocode:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//   x = obj&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//   retain(x)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;objVarPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;initialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;to&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objVarPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pointee&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Assign another obj, equivalent to `x = NSObject()`.&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Underneath, it's equivalent to the following pseudocode:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//   release(x)&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//   x = obj&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//   retain(x)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;objVarPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pointee&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;objVarPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pointee&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;description&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// It's crucial to de-initialise ref type pointers. Underneath, equivalent to:&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;//   release(x)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;objVarPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deinitialize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;count&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Deallocate storage for the managed reference&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;objVarPointer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;deallocate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;capacity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h4 class=&quot;subheading&quot;&gt;AutoreleasingUnsafeMutablePointer&lt;/h4&gt;

&lt;p&gt;
&lt;code class=&quot;inline-code&quot;&gt;AutoreleasingUnsafeMutablePointer&lt;/code&gt; is a typed pointer to references and it must point to storage that does not own the referenced object. By contrast, &lt;code class=&quot;inline-code&quot;&gt;UnsafeMutablePointer&lt;/code&gt; assumes the referenced storage owns a ref count to the referenced object.
&lt;/p&gt;

&lt;h3 class=&quot;subheading&quot;&gt;Unmanaged&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;inline-code&quot;&gt;Unmanaged&lt;/code&gt; represents an unmanaged reference to an instance of a particular type. It is declared as a generic struct restricted to reference types. Its job is to facilitative the conversion from unmanaged to managed references and vice versa.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unmanaged&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Instance&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AnyObject&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// ... more code ...&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;passRetained&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unmanaged&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;passUnretained&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Instance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unmanaged&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
    
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;takeUnretainedValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Instance&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;takeRetainedValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Instance&lt;/span&gt;
  
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fromOpaque&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;value&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeRawPointer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Unmanaged&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Instance&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;kd&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;toOpaque&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UnsafeMutableRawPointer&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
If you receive an unmanaged &lt;code class=&quot;inline-code&quot;&gt;CFType&lt;/code&gt; reference from an unannotated API, you can convert it to a managed one using the &lt;code class=&quot;inline-code&quot;&gt;take&lt;/code&gt; family of methods. Use &lt;code class=&quot;inline-code&quot;&gt;takeUnretainedValue()&lt;/code&gt; when you're not responsible for releasing the instance (those usually come from &lt;code class=&quot;inline-code&quot;&gt;Get&lt;/code&gt; family of functions). Use &lt;code class=&quot;inline-code&quot;&gt;takeRetainedValue()&lt;/code&gt; when you're responsible for releasing the instance (those usually come from &lt;code class=&quot;inline-code&quot;&gt;Copy&lt;/code&gt; or &lt;code class=&quot;inline-code&quot;&gt;Create&lt;/code&gt; family of functions).
&lt;/p&gt;

&lt;p&gt;
To go in the other direction, use the take &lt;code class=&quot;inline-code&quot;&gt;pass&lt;/code&gt; family of methods. If there's an unannotated &lt;code class=&quot;inline-code&quot;&gt;CFType&lt;/code&gt; API which expects to receive a +1 reference, you need to use &lt;code class=&quot;inline-code&quot;&gt;passRetained()&lt;/code&gt;. Note that the receiver of the unmanaged reference is responsible for balancing the +1, otherwise the object will leak. Most of time, you need to use &lt;code class=&quot;inline-code&quot;&gt;passUnretained()&lt;/code&gt; when interacting with APIs which expect a +0 reference.
&lt;/p&gt;

&lt;p&gt;
Finally, &lt;code class=&quot;inline-code&quot;&gt;fromOpaque()&lt;/code&gt; and &lt;code class=&quot;inline-code&quot;&gt;toOpaque()&lt;/code&gt; allow you to convert between raw pointers (i.e., &lt;code class=&quot;inline-code&quot;&gt;void*&lt;/code&gt; pointers) and &lt;code class=&quot;inline-code&quot;&gt;Unmanaged&lt;/code&gt; references.
&lt;/p&gt;

&lt;h3 class=&quot;subheading&quot;&gt;OpaquePointer&lt;/h3&gt;

&lt;p&gt;
OpaquePointer is used for C pointers that cannot be represented in Swift (e.g., pointers to incomplete struct types). There's very little you can do with this type: it can be created, compared and debug logged.
&lt;/p&gt;

&lt;div class=&quot;social-updates-container&quot;&gt;
	&lt;div class=&quot;social-updates&quot;&gt;
		Follow &lt;a href=&quot;https://twitter.com/milend&quot;&gt;@milend&lt;/a&gt; and &lt;a href=&quot;http://milen.me/writings/feed.xml&quot;&gt;subscribe (RSS)&lt;/a&gt; to get the latest updates.
	&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;/writings/&quot; style=&quot;text-decoration: none;&quot;&gt;&amp;larr; Back to Writings&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;footer-line&quot;&gt;&lt;/div&gt;


&lt;div class=&quot;references&quot;&gt;
	&lt;p&gt;References&lt;/p&gt;
	&lt;ul&gt;

&lt;li&gt;&lt;a href=&quot;https://github.com/apple/swift-evolution/blob/master/proposals/0107-unsaferawpointer.md&quot; target=&quot;_blank&quot;&gt;SE-0107: UnsafeRawPointer API&lt;/a&gt; &amp;#x2192;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/apple/swift-evolution/blob/master/proposals/0055-optional-unsafe-pointers.md&quot;&gt;SE-0055: Unsafe Pointer Nullability&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://swift.org/migration-guide/se-0107-migrate.html&quot; target=&quot;_blank&quot;&gt;UnsafeRawPointer Migration&lt;/a&gt; &amp;#x2192;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://technology.meronapps.com/2016/09/27/swift-3-0-unsafe-world-2/&quot; target=&quot;_blank&quot;&gt;Swift 3.0 Unsafe World&lt;/a&gt;&amp;#x2192;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.apple.com/library/content/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html#//apple_ref/doc/uid/20001148-CJBEJBHH&quot;&gt;Memory Management Programming Guide for Core Foundation&lt;/a&gt;&amp;#x2192;&lt;/li&gt;
		
	&lt;/ul&gt;
&lt;/div&gt;</description>
				<pubDate>Sun, 06 Nov 2016 00:00:00 +0000</pubDate>
				<link>/writings/swift-unsafe-pointers/</link>
				<guid isPermaLink="true">/writings/swift-unsafe-pointers/</guid>
			</item>
			
		
			
			<item>
				<title>The Mac Platform Decline</title>
				<description>&lt;p&gt;&lt;a href=&quot;http://owensd.io/blog/hello-again/&quot;&gt;David Owens II:&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
To me, Thursday’s event signaled one thing for me, and maybe I’m completely wrong, but the Mac is officially over.
&lt;/blockquote&gt;

&lt;blockquote&gt;
Apple, the MacBook Pro is not a pro-level computer. It’s simply not.
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href=&quot;http://www.tedlandau.com/slantedviewpoint/index.php/archives/2016/2014&quot;&gt;Ted Landau:&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
Apple’s desktop Mac lineup is headed for the graveyard. Dead. Done. Over.
&lt;/blockquote&gt;


&lt;p&gt;
It has taken me some time to collect my thoughts on the state of the Mac platform. My feelings have been developing over several years and I think after the October 2016 event, it's time to put them in writing. It's fair to say that I've gone through the five stages of grief: denial, anger, bargaining, depression, acceptance.
&lt;/p&gt;

&lt;h3 class=&quot;subheading&quot;&gt;hello again&lt;/h3&gt;

&lt;p&gt;
At the &lt;a href=&quot;http://www.macrumors.com/2016/10/27/live-coverage-october-2016-event/&quot;&gt;October 2016 event&lt;/a&gt;, Apple announced updated models of the MacBook Pro line while desktop Macs did not even get a single mention. At the time of writing, desktops have not been &lt;a href=&quot;http://buyersguide.macrumors.com/#iMac&quot;&gt;updated&lt;/a&gt; in &lt;em&gt;at least&lt;/em&gt; a year.
&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;iMac&lt;/strong&gt;: Last updated 382 days ago&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Mac Mini&lt;/strong&gt;: Last updated 744 days ago&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;Mac Pro&lt;/strong&gt;: Last updated 1045 days ago&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;Pro for Professional?&lt;/h3&gt;

&lt;p&gt;
From where I'm standing, Apple are redefining (shrinking) their target audience for the Mac platform. If you feel left out by the latest updates and the neglect on the desktop, it's simple as Apple deciding not to serve your segment's needs. I know that it can feel quite personal to Mac devotees, like me, but it's simply business and strategy.
&lt;/p&gt;

&lt;p&gt;
If we look purely at the revenue split, the Mac accounts for about 10% of Apple's revenues. It's entirely plausible that a decision was made not to invest in a declining ecosystem which does not represent the future in Apple's mind. I'm not judging whether it's logical or it makes sense to do that, I'm just making it clear that such a scenario, which would reflect the reality we're seeing, seems possible.
&lt;/p&gt;

&lt;p&gt;
Tim Cook's &lt;a href=&quot;http://www.telegraph.co.uk/technology/2016/01/21/apples-tim-cook-declares-the-end-of-the-pc-and-hints-at-new-medi/&quot;&gt;thoughts&lt;/a&gt; on computers are clearly expressed in this interview:
&lt;/p&gt;

&lt;blockquote&gt;
I think if you’re looking at a PC, why would you buy a PC anymore? No really, why would you buy one? Yes, the iPad Pro is a replacement for a notebook or a desktop for many, many people. They will start using it and conclude they no longer need to use anything else, other than their phones.
&lt;/blockquote&gt;

&lt;p&gt;
Yes, absolutely: the iPad Pro can and has replaced many people's computers, including Macs. But in the near term, it simply cannot replace it for a small minority with genuine high-end needs.
&lt;/p&gt;

&lt;h3&gt;Outdated Hardware&lt;/h3&gt;

&lt;p&gt;
Let me address the following point: Who needs anything more than a MacBook Pro? The answer is a very small segment of high-demanding users. Those are the people who have been waiting for a very long time to only be disappointed by the October 2016 event. Activities include heavy 2D / 3D post-processing, video editors, highly-demanding software development. While the base performance of laptops continuously improves to cover more use cases, some highly specialised workloads still require significantly more power.
&lt;/p&gt;

&lt;p&gt;
I'm currently using a 6-core Mac Pro (2013) with 64GB of RAM. I'm developing code on a huge codebase and running a lot of demanding apps. I run out of memory on a &lt;a href=&quot;https://twitter.com/milend/status/736186281437335552&quot;&gt;regular basis&lt;/a&gt; and have the CPUs at very high utilisation throughout my work day. This workload is simply not possible on a laptop due to the thermal envelope (CPU-only TDPs of &lt;a href=&quot;http://ark.intel.com/products/75780/Intel-Xeon-Processor-E5-1650-v2-12M-Cache-3_50-GHz&quot;&gt;130W&lt;/a&gt; vs  &lt;a href=&quot;http://ark.intel.com/products/88972/Intel-Core-i7-6920HQ-Processor-8M-Cache-up-to-3_80-GHz&quot;&gt;45W&lt;/a&gt;).
&lt;/p&gt;

&lt;p&gt;
The Mac Pro is just embarrassingly outdated, still selling for the same price&lt;sup id=&quot;fnref:mp-price&quot;&gt;&lt;a href=&quot;#fn:mp-price&quot; rel=&quot;footnote&quot;&gt;&lt;/a&gt;&lt;/sup&gt; it did when it launched 3 years ago. The Xeon CPUs are 2 generations behind, the dual workstation-class GPUs are now significantly slower than a single high-end consumer &lt;a href=&quot;https://en.wikipedia.org/wiki/GeForce_10_series&quot;&gt;Nvidia card&lt;/a&gt;. &lt;a href=&quot;https://twitter.com/brianstucki/status/791671150703091712&quot;&gt;Brian Stucki&lt;/a&gt; notices:
&lt;/p&gt;

&lt;blockquote&gt;
Reminder: The current Mac Pro page brags about the performance with Aperture, a program that Apple retired 2+ years ago
&lt;/blockquote&gt;

&lt;p&gt;
Anecdotally, the people who need GPU perf now all use PCs: not because of the cost of Apple hardware but simply because the Mac Pro's GPU performance is not at all competitive&lt;sup id=&quot;fnref:mp-chicken-egg&quot;&gt;&lt;a href=&quot;#fn:mp-chicken-egg&quot; rel=&quot;footnote&quot;&gt;&lt;/a&gt;&lt;/sup&gt;. If we look at the fastest GPU configuration with a pair of workstation-class D700, this provides a total of 7 TFLOPS (3.5 TFLOPS per card). Over at the Nvidia camp, a single Quadro P6000 GPU has 12 TFLOPS, even the consumer Titan X Pascal can do 11 TFLOPS. So, a consumer Titan X Pascal is 57% faster than a dual D700. If you compare against dual Titan X Pascals, you would have a performance increase of 214%. For highly demanding GPU workflows, this sort of performance &lt;em&gt;does matter&lt;/em&gt;.
&lt;/p&gt;

&lt;p&gt;
After discussing the topic with a friend of mine, he remarked that he knows about a company who switched from an all-Mac setup to Linux and Windows machines in the span of a couple of years. For similar stories, you should visit some of the more prominent Mac Pro forums and see for yourself.
&lt;/p&gt;

&lt;p&gt;
That's why professionals feel left out. As &lt;a href=&quot;https://twitter.com/lapcatsoftware/status/792401114897547264&quot;&gt;Jeff J.&lt;/a&gt; puts it:
&lt;/p&gt;

&lt;blockquote&gt;
Those complaining about Apple's current Mac lineup are not haters, they're lovers. They've spent 10+ years and 5+ figures on Macs.
&lt;/blockquote&gt;

&lt;p&gt;
The real kicker is that the ecosystem and platform where you might have invested 10+ years is suddenly disappearing from underneath you because you're not the target market anymore. On the software side, it seems that almost all updates are about feature integrations with iOS or collateral improvements from the shared base macOS and iOS share.
&lt;/p&gt;

&lt;p&gt;
On the other side of the spectrum, we have the Mac Mini. To the uneducated observer, the Mac Mini might seem like a very unimportant product but it plays a crucial role in companies that develop Apple software at scale to provide continuous integration. For example, Facebook have &lt;a href=&quot;https://code.facebook.com/posts/300815046928882/the-mobile-device-lab-at-the-prineville-data-center/&quot;&gt;clusters of Mac Minis&lt;/a&gt; that continuously compile and &lt;a href=&quot;https://www.wired.com/2013/12/apples-mac-mini-reborn/&quot;&gt;test&lt;/a&gt; their codebase. There are dedicated companies, like &lt;a href=&quot;https://macminicolo.net&quot;&gt;Macminicolo&lt;/a&gt;, whose sole job is colocating those small computers running macOS.
&lt;/p&gt;

&lt;p&gt;
Last time Apple updated the Mac Mini, it took a big step backwards: it removed the quad-core i7 CPU option with only a dual-core option. This ended up reducing multicore CPU performance by almost 37% which represents a serious regression. From the outside, it seems that Apple just does not want to cater to those needs&lt;sup id=&quot;fnref:2&quot;&gt;&lt;a href=&quot;#fn:2&quot; rel=&quot;footnote&quot;&gt;&lt;/a&gt;&lt;/sup&gt;.
&lt;/p&gt;

&lt;h3&gt;Tradeoffs&lt;/h3&gt;

&lt;p&gt;According to the October 2016 event, Apple's vision of the Mac future is just MacBook Pros: a one-size-fits-all approach. Apple has even &lt;a href=&quot;http://www.macrumors.com/2016/10/28/apple-out-of-display-business/&quot;&gt;left&lt;/a&gt; the standalone display business which provides further signal about their long-term plans.&lt;/p&gt;

&lt;p&gt;This one-size approach has fundamental flaws because we haven't reached the stage where the tradeoffs are acceptable to high-demanding professionals. Almost every choice we make in this life is all about tradeoffs: it's the same in hardware engineering. For example, making laptops thinner and lighter means sacrificing performance that you wouldn't if you did not have those constraints &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; rel=&quot;footnote&quot;&gt;&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;

&lt;p&gt;But when you need all the power you can get, you don't care about thinness of your desktop, you have all the space you need. In this particular case, you should be able to pick a different set of constraints. And that's where one-size-fits-all simply does not work: you can't put a 12-core Xeon CPU, a Titan X and 64GB of RAM in a laptop package as thin as the MacBook Pro.
&lt;/p&gt;

&lt;p&gt;
Once upon a time, those of us in the Apple ecosystem could choose between different sets of tradeoffs according to our needs. But increasingly, Apple is tuning the tradeoffs to casual consumer needs across its entire product line, leaving professionals out in the cold.
&lt;/p&gt;

&lt;h3&gt;Professional Ecosystem&lt;/h3&gt;

&lt;p&gt;
Here's the &lt;em&gt;most important&lt;/em&gt; question: If professionals don't make Apple enough money to be worth targeting, why should they invest resources to support them and create products for them? If that's the case, then there's no point in professionals complaining because Apple is actively choosing not to cater to their needs. We could argue that Apple has done the maths and concluded that losing professionals and focusing on consumers&lt;sup id=&quot;fnref:consumer-focus&quot;&gt;&lt;a href=&quot;#fn:consumer-focus&quot; rel=&quot;footnote&quot;&gt;&lt;/a&gt;&lt;/sup&gt; would be a net positive. Professionals might disagree with this stance but it's an entirely logical and sensible position&lt;sup id=&quot;fnref:aperture&quot;&gt;&lt;a href=&quot;#fn:aperture&quot; rel=&quot;footnote&quot;&gt;&lt;/a&gt;&lt;/sup&gt; for Apple to take.
&lt;/p&gt;

&lt;p&gt;
The counterargument that I'll make is that if you lose the professionals, you’ll lose a significant chunk of innovation and content that keeps consumers in the Apple ecosystem. Those professionals are content creators and if they use Macs at work, they're more likely to use Macs at home and create for Apple platforms. Professionals are influencers and affect the computing choices of their immediate family &amp;amp; friends.&lt;/p&gt;

&lt;p&gt;
A lot of the best indie Mac apps happened because their developers were Mac users before becoming programmers. You could say that macOS is currently the platform choice for a large part of the developer community, especially web developers. This creates a large ecosystem of people who are inclined to further develop the platform and create software for it. A big reason why consumers like Apple is because they used to benefit from the spillover from their professional-level tools.
&lt;/p&gt;

&lt;h3&gt;Sentiment&lt;/h3&gt;

&lt;p&gt;
Sentiment about Apple from professional users has become almost uniformly negative over the past few years. This gloomy attitude is also reflected in the regular conversations I have with engineers who develop for Apple's platforms. If Apple alienates developers to such a degree that they will no longer develop for its platforms in their free time, they'll have a very real long-term problem. Furthermore, developers act as evangelists for the platform. And let's not forget that the Mac sits at the bottom of the pyramid: all the iOS, watchOS and tvOS software gets created on the Mac. Neglecting the Mac platform will have a knock-on effect on the wider Apple ecosystem.
&lt;/p&gt;

&lt;p&gt;
Another worrying aspect is the perceived health of the Mac ecosystem. If professionals feel that the platform is slowly dying and not catering to their needs, they have less of a reason to keep investing in it which eventually starts a vicious self-perpetuating spiral.
&lt;/p&gt;

&lt;h3&gt;The Future&lt;/h3&gt;

&lt;p&gt;
I don't want the professional Mac platform to die a slow death of neglect but that's where things seem to be going. The scary part is that the Mac community is unanimous in their characterisation of the situation. The trust in the ecosystem, its longevity, continued support and innovation seems to have been lost. Even if Apple were to release updated desktop hardware tomorrow, a big if, it will still not be enough to completely eliminate the mistrust.&lt;/p&gt;

&lt;p&gt;For more on the subject, you should go and read &lt;a href=&quot;http://mjtsai.com/blog/2016/10/27/new-macbook-pros-and-the-state-of-the-mac/&quot;&gt;Michael Tsai's excellent blog post&lt;/a&gt;. If you're into podcasts, listen to &lt;a href=&quot;http://atp.fm/episodes/193&quot;&gt;Accidental Tech Podcast: The Escape Zone (193)&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;I'd like to thank &lt;a href=&quot;https://twitter.com/nicklockwood&quot;&gt;Nick Lockwood&lt;/a&gt; for his feedback on this article.&lt;/p&gt;

&lt;p&gt;
If history has taught us anything, it's that developers can make or break a platform. &lt;a href=&quot;https://twitter.com/nicklockwood/status/791610546302906368&quot;&gt;Nick&lt;/a&gt; &lt;a href=&quot;https://twitter.com/nicklockwood/status/791612112741232640&quot;&gt;Lockwood&lt;/a&gt;:
&lt;/p&gt;

&lt;blockquote&gt;
  Here is what I imagine Apple&amp;#39;s decline will look like: It won&amp;#39;t be poor sales, or loss of revenue. It won&amp;#39;t be a shiny new iPhone killer…
&lt;/blockquote&gt;

&lt;blockquote&gt;
  It will be a switch from iOS developers using Macs at home to them using PCs at home and having a &amp;quot;work Mac&amp;quot; for commercial development.
&lt;/blockquote&gt;

&lt;blockquote&gt;
  Most will still use iPhones, but they won&amp;#39;t write apps for them except to make money. Their personal projects will be for Web or Windows.
&lt;/blockquote&gt;

&lt;blockquote&gt;
  All of the $70 indie apps that made Mac and iOS fun to develop on will dry up. The only apps will be social networking clients or F2P games.
&lt;/blockquote&gt;

&lt;blockquote&gt;
  And that&amp;#39;s all. Apple will still be profitable, and consumers will still view it as the premium brand, but devs will favour other platforms.
&lt;/blockquote&gt;

&lt;div class=&quot;social-updates-container&quot;&gt;
	&lt;div class=&quot;social-updates&quot;&gt;
		Follow &lt;a href=&quot;https://twitter.com/milend&quot;&gt;@milend&lt;/a&gt; and &lt;a href=&quot;http://milen.me/writings/feed.xml&quot;&gt;subscribe (RSS)&lt;/a&gt; to get the latest updates.
	&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;/writings/&quot; style=&quot;text-decoration: none;&quot;&gt;&amp;larr; Back to Writings&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;footer-line&quot;&gt;&lt;/div&gt;


&lt;div class=&quot;footnotes&quot;&gt;
	&lt;ol&gt;

&lt;li class=&quot;footnote&quot; id=&quot;fn:1&quot;&gt;
    &lt;p&gt;There's diminishing returns as you keep making laptops thinner and lighter. You reach a point where the tradeoff is no longer worth it for the vast majority of people. You could also argue we have reached that point already: a lot of people complain about wanting better battery life rather than thinner laptops.&lt;a href=&quot;#fnref:1&quot; title=&quot;return to article&quot;&gt; &amp;#x21A9;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li class=&quot;footnote&quot; id=&quot;fn:2&quot;&gt;
    &lt;p&gt;Remember Xserve?&lt;a href=&quot;#fnref:2&quot; title=&quot;return to article&quot;&gt; &amp;#x21A9;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li class=&quot;footnote&quot; id=&quot;fn:mp-price&quot;&gt;
    &lt;p&gt;In the UK, the Mac Pro price actually &lt;a href=&quot;https://www.theguardian.com/technology/2016/oct/28/brexit-apple-mac-customers-prices-rise-us-dollar-pound-sterling&quot; target=&quot;_blank&quot;&gt;&lt;em&gt;increased&lt;/em&gt;&lt;/a&gt; by £500 due to currency exchange rate adjustments. &lt;a href=&quot;#fnref:mp-price&quot; title=&quot;return to article&quot;&gt; &amp;#x21A9;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li class=&quot;footnote&quot; id=&quot;fn:consumer-focus&quot;&gt;
    &lt;p&gt;I believe that's Apple's thinking right now. It's not that they deliberately don't care about professionals, it's just that in their version of the future, it does not make financial sense to target the high-end professionals.&lt;a href=&quot;#fnref:consumer-focus&quot; title=&quot;return to article&quot;&gt; &amp;#x21A9;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li class=&quot;footnote&quot; id=&quot;fn:aperture&quot;&gt;
    &lt;p&gt;The discontinuation of &lt;a href=&quot;https://en.wikipedia.org/wiki/Aperture_(software)&quot;&gt;Aperture&lt;/a&gt; is another example of this direction.&lt;a href=&quot;#fnref:aperture&quot; title=&quot;return to article&quot;&gt; &amp;#x21A9;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

&lt;li class=&quot;footnote&quot; id=&quot;fn:mp-chicken-egg&quot;&gt;
    &lt;p&gt;There's now a chicken-and-egg problem when it comes to investing in the Mac Pro line. Many professionals with high-end needs have already switched away from it due to poor hardware, leaving a smaller userbase. This is makes it increasingly harder to justify further investment.&lt;a href=&quot;#fnref:mp-chicken-egg&quot; title=&quot;return to article&quot;&gt; &amp;#x21A9;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

	&lt;/ol&gt;
&lt;/div&gt;




&lt;div class=&quot;references&quot;&gt;
	&lt;p&gt;References&lt;/p&gt;
	&lt;ul&gt;

&lt;li&gt;&lt;a href=&quot;http://mjtsai.com/blog/2016/10/27/new-macbook-pros-and-the-state-of-the-mac/&quot; target=&quot;_blank&quot;&gt;New MacBook Pros and the State of the Mac&lt;/a&gt; &amp;#x2192;&lt;/li&gt;
		
	&lt;/ul&gt;
&lt;/div&gt;</description>
				<pubDate>Sun, 30 Oct 2016 00:00:00 +0100</pubDate>
				<link>/writings/mac-platform-decline/</link>
				<guid isPermaLink="true">/writings/mac-platform-decline/</guid>
			</item>
			
		
			
			<item>
				<title>Live Photo API on iOS</title>
				<description>&lt;p&gt;
What are Live Photos? From a marketing perspective, Live Photos record the moments just before and after you take a photo. Under the hood, a Live Photo is just a JPEG image together with a &lt;a href=&quot;https://en.wikipedia.org/wiki/QuickTime_File_Format&quot;&gt;QuickTime file&lt;/a&gt; contaning an &lt;a href=&quot;https://en.wikipedia.org/wiki/H.264/MPEG-4_AVC&quot;&gt;H.264&lt;/a&gt; track.
&lt;/p&gt;

&lt;h3 class=&quot;subheading&quot;&gt;Storing Live Photo Data&lt;/h3&gt;

&lt;p&gt;
  The first step in using Live Photos is to retrieve them and then access the underlying data. The easiest way to get hold of a Live Photo is to ask the user to select one from their camera roll. For this, we can use &lt;code class=&quot;inline-code&quot;&gt;UIImagePickerController&lt;/code&gt; &amp;mdash; the crucial part is including &lt;strong&gt;both&lt;/strong&gt; &lt;code class=&quot;inline-code&quot;&gt;kUTTypeLivePhoto&lt;/code&gt; and &lt;code class=&quot;inline-code&quot;&gt;kUTTypeImage&lt;/code&gt; in the media types array.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;@IBAction&lt;/span&gt; &lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;showImagePicker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;sender&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIButton&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;picker&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImagePickerController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;picker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;delegate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;picker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;allowsEditing&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;picker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sourceType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;PhotoLibrary&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;picker&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;mediaTypes&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;kUTTypeLivePhoto&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;kUTTypeImage&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;];&lt;/span&gt;
  
  &lt;span class=&quot;nf&quot;&gt;presentViewController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;picker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animated&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;completion&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
  Once the user has selected a photo, the delegate method will be called. From there we can check whether they have actually selected a Live Photo. If that's the case, we will generate a random directory where we can store all the associated resources. The &lt;code class=&quot;inline-code&quot;&gt;PHAssetResourceManager&lt;/code&gt; gives us chunks of data which we concatenate. If we wanted to be more efficient, we could have used an &lt;code class=&quot;inline-code&quot;&gt;NSOutputStream&lt;/code&gt; or &lt;code class=&quot;inline-code&quot;&gt;NSFileHandle&lt;/code&gt;.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;imagePickerController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;picker&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UIImagePickerController&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;didFinishPickingMediaWithInfo&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AnyObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;guard&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;livePhoto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UIImagePickerControllerLivePhoto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as?&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PHLivePhoto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;photoDir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;generateFolderForLivePhotoResources&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;assetResources&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PHAssetResource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;assetResourcesForLivePhoto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;livePhoto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;resource&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;assetResources&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;buffer&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSMutableData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;kt&quot;&gt;PHAssetResourceManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;defaultManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;requestDataForAssetResource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
      &lt;span class=&quot;n&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;options&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;dataReceivedHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;appendData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;chunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;},&lt;/span&gt;
      &lt;span class=&quot;nv&quot;&gt;completionHandler&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;saveAssetResource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;inDirectory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;photoDir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
  Once we finished collecting the data for a resource, we're ready to write it to a file. We get the preferred file extension and save the file to disk.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;saveAssetResource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PHAssetResource&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;inDirectory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
  &lt;span class=&quot;nv&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSMutableData&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;maybeError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maybeError&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Could not request data for resource: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;, error: &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;maybeError&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;maybeExt&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;UTTypeCopyPreferredTagWithClass&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;uniformTypeIdentifier&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;kUTTagClassFilenameExtension&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)?&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;takeRetainedValue&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;guard&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;ext&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;maybeExt&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fileUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;inDirectory&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;URLByAppendingPathComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSUUID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UUIDString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;fileUrl&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileUrl&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;URLByAppendingPathExtension&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ext&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;buffer&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;writeToURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileUrl&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;atomically&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Could not save resource &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;resource&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt; to filepath &lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fileUrl&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
  Below, you can see how we generate a random directory. In the example code, it will be a subdirectory of the temporary directory, which gets cleaned up by the OS at unspecified intervals.
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;generateFolderForLivePhotoResources&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;photoDir&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;// NB: Files in NSTemporaryDirectory() are automatically cleaned up by the OS&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;fileURLWithPath&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSTemporaryDirectory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(),&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;isDirectory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;URLByAppendingPathComponent&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSUUID&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;UUIDString&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;fileManager&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSFileManager&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// we need to specify type as ()? as otherwise the compiler generates a warning&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;success&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()?&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;try&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fileManager&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;createDirectoryAtURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;photoDir&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;withIntermediateDirectories&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;attributes&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
  
  &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;success&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;photoDir&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;
After you have saved all the resources to disk, you can transfer them to your servers or any other destination.
&lt;/p&gt;

&lt;h3 class=&quot;subheading&quot;&gt;Displaying Live Photos&lt;/h3&gt;

&lt;p&gt;
To go in the other direction, all we need is a list of file &lt;code class=&quot;inline-code&quot;&gt;NSURL&lt;/code&gt;s representing a single Live Photo. Those would have been downloaded by your app from your servers. Note that the block callback will be executed multiple times, initially providing a &lt;code class=&quot;inline-code&quot;&gt;PHLivePhoto&lt;/code&gt; of degraded quality.
&lt;/p&gt;

&lt;pre class=&quot;code-box code-box-warning&quot;&gt;
Note that there's currently a crasher bug in &lt;code class=&quot;inline-code&quot;&gt;PHLivePhotoView&lt;/code&gt;. It manifests itself if you try to request a Live Photo from non-existing files. The workaround is to check for a non-nil photo with zero size.
&lt;/pre&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;showLivePhoto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;photoFiles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSURL&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;requestID&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PHLivePhoto&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;requestLivePhotoWithResourceFileURLs&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;photoFiles&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;placeholderImage&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;targetSize&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CGSizeZero&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;contentMode&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;AspectFit&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;livePhoto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;PHLivePhoto&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;?,&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;NSObject&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AnyObject&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Void&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;in&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;PHLivePhotoInfoErrorKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as?&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSError&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;degraded&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;PHLivePhotoInfoIsDegradedKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as?&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSNumber&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cancelled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;info&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;PHLivePhotoInfoCancelledKey&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;as?&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;NSNumber&lt;/span&gt;
      &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;finished&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;error&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;cancelled&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cancelled&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;boolValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;||&lt;/span&gt;
        &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;degraded&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;degraded&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;boolValue&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;finished&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// If you have saved `requestID`, you can now set it to PHLivePhotoRequestIDInvalid&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Live photo request finished&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      
      &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;photo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;livePhoto&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;photo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;CGSizeZero&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;c1&quot;&gt;// Workaround for crasher rdar://24021574 (https://openradar.appspot.com/24021574)&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
      &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
      
      &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;photoView&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;livePhoto&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;livePhoto&lt;/span&gt;
  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;div class=&quot;social-updates-container&quot;&gt;
	&lt;div class=&quot;social-updates&quot;&gt;
		Follow &lt;a href=&quot;https://twitter.com/milend&quot;&gt;@milend&lt;/a&gt; and &lt;a href=&quot;http://milen.me/writings/feed.xml&quot;&gt;subscribe (RSS)&lt;/a&gt; to get the latest updates.
	&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;/writings/&quot; style=&quot;text-decoration: none;&quot;&gt;&amp;larr; Back to Writings&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;footer-line&quot;&gt;&lt;/div&gt;

&lt;div class=&quot;references&quot;&gt;
	&lt;p&gt;References&lt;/p&gt;
	&lt;ul&gt;

&lt;li&gt;&lt;a href=&quot;https://developer.apple.com/library/ios/documentation/Photos/Reference/PHLivePhoto_Class/&quot; target=&quot;_blank&quot;&gt;PHLivePhoto Class Reference&lt;/a&gt; &amp;#x2192;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.apple.com/library/ios/documentation/PhotosUI/Reference/PHLivePhotoView_Class/&quot; target=&quot;_blank&quot;&gt;PHLivePhotoView Class&lt;/a&gt; &amp;#x2192;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIImagePickerController_Class/&quot; target=&quot;_blank&quot;&gt;UIImagePickerController Class Reference&lt;/a&gt; &amp;#x2192;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.apple.com/library/ios/documentation/Photos/Reference/PHAssetResourceManager_Class/&quot; target=&quot;_blank&quot;&gt;PHAssetResourceManager Class Reference&lt;/a&gt; &amp;#x2192;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSURL_Class/&quot; target=&quot;_blank&quot;&gt;NSURL Class Reference &lt;/a&gt; &amp;#x2192;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSOutputStream_Class/&quot; target=&quot;_blank&quot;&gt;NSOutputStream Class Reference&lt;/a&gt; &amp;#x2192;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.apple.com/library/ios/documentation/Cocoa/Reference/Foundation/Classes/NSFileHandle_Class/&quot; target=&quot;_blank&quot;&gt;NSFileHandle Class Reference&lt;/a&gt; &amp;#x2192;&lt;/li&gt;

&lt;li&gt;&lt;a href=&quot;https://openradar.appspot.com/24021574&quot; target=&quot;_blank&quot;&gt;PHLivePhotoView crasher (rdar://24021574)&lt;/a&gt; &amp;#x2192;&lt;/li&gt;



	&lt;/ul&gt;
&lt;/div&gt;
</description>
				<pubDate>Wed, 30 Dec 2015 00:00:00 +0000</pubDate>
				<link>/writings/live-photo-ios-api-overview/</link>
				<guid isPermaLink="true">/writings/live-photo-ios-api-overview/</guid>
			</item>
			
		
			
			<item>
				<title>Swift Generic Protocols</title>
				<description>&lt;p&gt;Protocols in Swift can be generic via abstract type members rather than parameterisation. Consequently, the protocol itself can no longer be used as a type but only as a generic constraint.&lt;/p&gt;

&lt;h3 class=&quot;subheading&quot;&gt;The Problem&lt;/h3&gt;

&lt;p&gt;If you tried to use a generic protocol as a type as follows:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;protocol&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;GenericProtocol&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;typealias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AbstractType&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;magic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AbstractType&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;GenericProtocol&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;We would see the following error message:&lt;/p&gt;
&lt;pre class=&quot;code-box-error code-box&quot;&gt;
Protocol '&lt;code class=&quot;inline-code&quot;&gt;GenericProtocol&lt;/code&gt;' can only be used as a generic constraint because it has &lt;code class=&quot;inline-code&quot;&gt;Self&lt;/code&gt; or associated type requirements.
&lt;/pre&gt;

&lt;p&gt;
	If you're not familiar with generics, you might be wondering why generic protocols cannot be used as types. The explanation is quite simple &amp;mdash; the name of the generic protocol, e.g. &lt;code class=&quot;inline-code&quot;&gt;GenericProtocol&lt;/code&gt;, represents a &lt;strong&gt;set of types&lt;/strong&gt; rather than a single type. If you were to have an arbitrary array of &lt;code class=&quot;inline-code&quot;&gt;GenericProtocol&lt;/code&gt;, you would not be able to say anything about the return type of the &lt;code class=&quot;inline-code&quot;&gt;magic()&lt;/code&gt; method, as it might be different for the various contained elements.
&lt;/p&gt;

&lt;p&gt;This is nicely &lt;a href=&quot;http://stackoverflow.com/questions/27725803/how-to-use-generic-protocol-as-a-variable-type&quot;&gt;illustrated&lt;/a&gt; on StackOverflow.&lt;/p&gt;

&lt;h3 class=&quot;subheading&quot;&gt;Type Members vs Parameterisation&lt;/h3&gt;

&lt;p&gt;
In Swift, protocols can be made generic by using abstract type members (&lt;code class=&quot;inline-code&quot;&gt;typealias&lt;/code&gt; keyword) while classes, structs, methods and functions become generic by type parameterisation (see below).
&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;genericFunc&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;ts&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;kc&quot;&gt;true&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// not very exciting&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Turns out that, in general, type members and parameterisation have equivalent expressivity &amp;mdash; as long as any language &lt;sup id=&quot;fnref:1&quot;&gt;&lt;a href=&quot;#fn:1&quot; rel=&quot;footnote&quot;&gt;&lt;/a&gt;&lt;/sup&gt; in question fully supports both ways. We can imagine Swift supporting generic parameterised protocols in a future iteration which would make the following code possible:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;protocol&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;GenericProtocolWithParam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;magic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;list&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;GenericProtocolWithParam&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

If you're interested in the tradeoffs between type parameterisation and abstract type members, check out the &lt;a href=&quot;https://devforums.apple.com/thread/230611?tstart=0&quot;&gt;discussion&lt;/a&gt; on the dev forums and &lt;a href=&quot;http://www.artima.com/weblogs/viewpost.jsp?thread=270195&quot;&gt;the article&lt;/a&gt; on how the issue affects Scala.

&lt;h3 class=&quot;subheading&quot;&gt;Workaround&lt;/h3&gt;

&lt;p&gt;We can workaround the lack of type parameterisation in protocols by using a &lt;a href=&quot;https://en.wikipedia.org/wiki/Thunk&quot;&gt;thunk&lt;/a&gt;. We do this by defining a struct which implements the protocol by forwarding all methods to an abstract type which implements said protocol, provided as part of the initialisation of the struct (a form of &lt;a href=&quot;https://en.wikipedia.org/wiki/Dependency_injection&quot;&gt;dependency injection&lt;/a&gt;). The actual forwarding is done with closures.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;protocol&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;GenericProtocol&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;typealias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AbstractType&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;magic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AbstractType&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;GenericProtocolThunk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;GenericProtocol&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;// closure which will be used to implement `magic()` as declared in the protocol&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;_magic&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;
	
	&lt;span class=&quot;c1&quot;&gt;// `T` is effectively a handle for `AbstractType` in the protocol&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;init&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;P&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;GenericProtocol&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;where&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;AbstractType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;dep&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;P&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;c1&quot;&gt;// requires Swift 2, otherwise create explicit closure&lt;/span&gt;
		&lt;span class=&quot;n&quot;&gt;_magic&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;dep&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;magic&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
	
	&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;magic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;T&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;c1&quot;&gt;// any protocol methods are implemented by forwarding&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;_magic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;Once we have a thunk, we can proceed to use it as a type by providing type values.&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;StringMagic&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;GenericProtocol&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;typealias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;AbstractType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;magic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;Magic!&quot;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// we can now create arrays of thunks if we specify the type param&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;let&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;magicians&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;GenericProtocolThunk&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;GenericProtocolThunk&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;StringMagic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;())]&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;magicians&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;first&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;!.&lt;/span&gt;&lt;span class=&quot;nf&quot;&gt;magic&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;c1&quot;&gt;// returns &quot;Magic!&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 class=&quot;subheading&quot;&gt;Self Requirement&lt;/h3&gt;

&lt;p&gt;In the context of a protocol declaration, &lt;code class=&quot;inline-code&quot;&gt;Self&lt;/code&gt; refers to the type adopting the protocol. This makes the protocol generic, as &lt;code class=&quot;inline-code&quot;&gt;Self&lt;/code&gt; can be thought of as syntactic sugar for a convenience type member. For example:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;protocol&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EquatableSelf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;other&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;Self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// By adopting `EquatableSelf`, every occurrence of `Self` in the protocol gets&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// semantically replaced with `ImplicitStruct`&lt;/span&gt;
&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ImplicitStruct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EquatableSelf&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int64&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ImplicitStruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;If we did not have the ability to use Self, we could have achieved the same in the following way:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;protocol&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EquatableTypealias&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;typealias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EquatableType&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;other&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EquatableType&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ExplicitStruct&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EquatableTypealias&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;typealias&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;EquatableType&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ExplicitStruct&lt;/span&gt;
	&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Int64&lt;/span&gt;
	&lt;span class=&quot;kd&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;equals&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;ExplicitStruct&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
		&lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;other&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;val&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;;&lt;/span&gt;
	&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;h3 class=&quot;subheading&quot;&gt;Protocol-Oriented Programming&lt;/h3&gt;

&lt;p&gt;Protocols in Swift play a central role, as &lt;a href=&quot;https://en.wikipedia.org/wiki/David_Abrahams_(computer_programmer)&quot;&gt;Dave Abrahams&lt;/a&gt; &lt;a href=&quot;http://asciiwwdc.com/2015/sessions/408&quot;&gt;says&lt;/a&gt; in &lt;a href=&quot;https://developer.apple.com/videos/wwdc/2015/?id=408&quot;&gt;Session 408&lt;/a&gt; (&lt;a href=&quot;http://devstreaming.apple.com/videos/wwdc/2015/408509vyudbqvts/408/408_protocoloriented_programming_in_swift.pdf?dl=1&quot;&gt;PDF&lt;/a&gt;) at &lt;a href=&quot;https://developer.apple.com/videos/wwdc/2015/&quot;&gt;WWDC 2015&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;&amp;#x2026; When we made Swift, we made the first protocol-oriented programming language.&lt;/blockquote&gt;

&lt;p&gt;Watching the full video is highly recommended for any developers interested in Swift and the protocol-oriented approach. In particular, there's a very good slide illustrating the consequence of adding a Self requirement to a protocol. &lt;/p&gt;

&lt;img src=&quot;/images/writings/swift-generic-protocols/swift-protocols-two-worlds.png&quot; /&gt;

&lt;h3 class=&quot;subheading&quot;&gt;Generics and Type Variance&lt;/h3&gt;

&lt;p&gt;Another issue that pops up with the introduction of generics is the variance of generic types. In simple terms, it deals with the following problem:&lt;/p&gt;

&lt;figure class=&quot;highlight&quot;&gt;&lt;pre&gt;&lt;code class=&quot;language-swift&quot; data-lang=&quot;swift&quot;&gt;&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Animal&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;// Animal-specific ivars + methods&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;kd&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Cat&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;kt&quot;&gt;Animal&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
	&lt;span class=&quot;c1&quot;&gt;// Cat-specific ivars + methods&lt;/span&gt;
&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;cats&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Cat&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()]&lt;/span&gt;

&lt;span class=&quot;c1&quot;&gt;// Here, we're typecasting from [Cat] to [Animal].&lt;/span&gt;
&lt;span class=&quot;c1&quot;&gt;// Such typecasts could be unsafe depending on the details.&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;var&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;animals&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;kt&quot;&gt;Animal&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;cats&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;

&lt;p&gt;I can suggest starting off with the Wikipedia page on &lt;a href=&quot;https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)&quot;&gt;type variance&lt;/a&gt; to further explore the issue at hand.&lt;/p&gt;

&lt;div class=&quot;social-updates-container&quot;&gt;
	&lt;div class=&quot;social-updates&quot;&gt;
		Follow &lt;a href=&quot;https://twitter.com/milend&quot;&gt;@milend&lt;/a&gt; and &lt;a href=&quot;http://milen.me/writings/feed.xml&quot;&gt;subscribe (RSS)&lt;/a&gt; to get the latest updates.
	&lt;/div&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href=&quot;/writings/&quot; style=&quot;text-decoration: none;&quot;&gt;&amp;larr; Back to Writings&lt;/a&gt;&lt;/p&gt;

&lt;div class=&quot;footer-line&quot;&gt;&lt;/div&gt;


&lt;div class=&quot;footnotes&quot;&gt;
	&lt;ol&gt;

&lt;li class=&quot;footnote&quot; id=&quot;fn:1&quot;&gt;
    &lt;p&gt;&lt;a href=&quot;http://www.scala-lang.org&quot;&gt;Scala&lt;/a&gt; is such a language.&lt;a href=&quot;#fnref:1&quot; title=&quot;return to article&quot;&gt; &amp;#x21A9;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;

	&lt;/ol&gt;
&lt;/div&gt;




&lt;div class=&quot;references&quot;&gt;
	&lt;p&gt;References&lt;/p&gt;
	&lt;ul&gt;

&lt;li&gt;&lt;a href=&quot;http://mjtsai.com/blog/2015/09/01/swift-protocols/&quot; target=&quot;_blank&quot;&gt;Swift Protocols (Michael Tsai)&lt;/a&gt; &amp;#x2192;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Covariance_and_contravariance_(computer_science)&quot; target=&quot;_blank&quot;&gt;Covariance &amp;amp; Contravariance&lt;/a&gt; &amp;#x2192;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developer.apple.com/videos/wwdc/2015/?id=408&quot; target=&quot;_blank&quot;&gt;Protocol-Oriented Programming in Swift&lt;/a&gt; (&lt;a href=&quot;http://asciiwwdc.com/2015/sessions/408&quot; target=&quot;_blank&quot;&gt;Transcript&lt;/a&gt;, &lt;a href=&quot;http://devstreaming.apple.com/videos/wwdc/2015/408509vyudbqvts/408/408_protocoloriented_programming_in_swift.pdf?dl=1&quot; target=&quot;_blank&quot;&gt;PDF&lt;/a&gt;)&amp;#x2192;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://devforums.apple.com/thread/230611?tstart=0&quot; target=&quot;_blank&quot;&gt;Associated Types vs. Type Parameters (Swift)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.artima.com/weblogs/viewpost.jsp?thread=270195&quot; target=&quot;_blank&quot;&gt;Abstract Type Members versus Generic Type Parameters in Scala&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.russbishop.net/swift-associated-types&quot; target=&quot;_blank&quot;&gt;Swift Associated Types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://forums.developer.apple.com/message/18038&quot; target=&quot;_blank&quot;&gt;Swift Generic Protocol Thunks&lt;/a&gt;&lt;/li&gt;
		
	&lt;/ul&gt;
&lt;/div&gt;</description>
				<pubDate>Fri, 04 Sep 2015 00:00:00 +0100</pubDate>
				<link>/writings/swift-generic-protocols/</link>
				<guid isPermaLink="true">/writings/swift-generic-protocols/</guid>
			</item>
			
		
			
		
			
		
			
		
			
		
			
		
			
		
	</channel>
</rss>
