<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Jon's Blog]]></title><description><![CDATA[Jonathan Cole's website.]]></description><link>https://jons.website</link><generator>GatsbyJS</generator><lastBuildDate>Thu, 26 Jan 2023 22:28:14 GMT</lastBuildDate><item><title><![CDATA[So You Want to Build a VR App]]></title><description><![CDATA[In this article, I describe the essential considerations that will affect the scope of your VR game early on, how they differ from traditional game development, and how to best meet them head-on.]]></description><link>https://jons.website/blog/so-you-want-to-build-a-vr-app/</link><guid isPermaLink="false">https://jons.website/blog/so-you-want-to-build-a-vr-app/</guid><pubDate>Mon, 09 Aug 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In this article, I describe the essential considerations that will affect the scope of your VR game early on, how they differ from traditional game development, and how to best meet them head-on.&lt;/p&gt;
&lt;!--more--&gt;
&lt;p&gt;You can read it &lt;a href=&quot;https://www.rightpoint.com/thought/articles/2021/08/09/so-you-want-to-build-a-vr-app&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Why XCFrameworks Matter]]></title><description><![CDATA[XCFrameworks are the future of framework development on iOS. I’ve written an article covering just what they are and why they’re important…]]></description><link>https://jons.website/blog/why-xcframeworks-matter/</link><guid isPermaLink="false">https://jons.website/blog/why-xcframeworks-matter/</guid><pubDate>Tue, 12 Jan 2021 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;XCFrameworks are the future of framework development on iOS. I’ve written an article covering just what they are and why they’re important, which you can read &lt;a href=&quot;https://www.rightpoint.com/rplabs/2021/01/why-xcframeworks-matter/&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[OpenCV, InputArray, OutputArray, and You]]></title><description><![CDATA[When you’re writing OpenCV code in C++, you’ll eventually want to pass whatever Mat objects you have into a function or a class method. For…]]></description><link>https://jons.website/blog/opencv-tip-arrays/</link><guid isPermaLink="false">https://jons.website/blog/opencv-tip-arrays/</guid><pubDate>Wed, 13 Mar 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;When you’re writing OpenCV code in C++, you’ll eventually want to pass whatever &lt;code&gt;Mat&lt;/code&gt; objects you have into a function or a class method. For the purposes of this post, let’s say we want to write a utility function that prepares a BGR888 &lt;code&gt;Mat&lt;/code&gt; for edge detection. This typically involves converting the image to grayscale, as well as blurring it to remove superficial details.&lt;/p&gt;
&lt;p&gt;It’s tempting to write the following function signature:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Revision 1&lt;/span&gt;
Mat &lt;span class=&quot;token function&quot;&gt;preprocess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;const&lt;/span&gt; Mat&lt;span class=&quot;token operator&quot;&gt;&amp;amp;&lt;/span&gt; input&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Mat gray&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; output&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;cvtColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; gray&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; COLOR_BGR2GRAY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;blur&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gray&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; output&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; output&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is good C++ code; we pass a reference to the input &lt;code&gt;Mat&lt;/code&gt; so that we don’t incur a copy, and we use &lt;code&gt;const&lt;/code&gt; to mark the reference as read-only. However, OpenCV provides some utilities that we can use to improve this function.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Mat&lt;/code&gt; is not the only container for representing an image in OpenCV. If you’re looking to leverage OpenCV’s &lt;a href=&quot;https://www.learnopencv.com/opencv-transparent-api/&quot;&gt;Transparent API&lt;/a&gt; for GPU acceleration, you’ll want to use &lt;code&gt;UMat&lt;/code&gt; as your container instead. If you have an existing codebase full of utility functions written like above, you’re going to have to make copies that take a &lt;code&gt;UMat&lt;/code&gt; reference if you want to use those.&lt;/p&gt;
&lt;p&gt;Fortunately, OpenCV has a solution to this problem in the form of the &lt;a href=&quot;https://docs.opencv.org/4.0.1/d4/d32/classcv_1_1__InputArray.html#details&quot;&gt;&lt;code&gt;InputArray&lt;/code&gt;&lt;/a&gt; proxy class. As per the docs, &lt;code&gt;InputArray&lt;/code&gt; lets you pass in a &lt;code&gt;Mat&lt;/code&gt;, &lt;code&gt;UMat&lt;/code&gt;, or even a &lt;code&gt;std::vector&lt;/code&gt;, among others.&lt;/p&gt;
&lt;p&gt;Here’s what our function looks like using &lt;code&gt;InputArray&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Revision 2&lt;/span&gt;
Mat &lt;span class=&quot;token function&quot;&gt;preprocess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;InputArray input&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Mat gray&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; output&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;cvtColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; gray&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; COLOR_BGR2GRAY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;blur&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gray&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; output&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; output&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Note that we aren’t passing a reference to &lt;code&gt;input&lt;/code&gt;. &lt;code&gt;InputArray&lt;/code&gt; internally typedefs as a reference, so that’s taken care of for you; that said, &lt;code&gt;Mat&lt;/code&gt; and &lt;code&gt;UMat&lt;/code&gt; are internally backed by smart pointers, so we don’t need to worry about getting a reference anyway! Using &lt;code&gt;InputArray&lt;/code&gt; also has the nice benefit of making your image read-only as far as the OpenCV SDK is concerned, which helps the compiler find issues and makes your code easier to read.&lt;/p&gt;
&lt;p&gt;OpenCV provides a similar proxy class called &lt;a href=&quot;https://docs.opencv.org/4.0.1/d2/d9e/classcv_1_1__OutputArray.html#details&quot;&gt;&lt;code&gt;OutputArray&lt;/code&gt;&lt;/a&gt;, which wraps the same types but is treated as write-only. Let’s rewrite &lt;code&gt;preprocess()&lt;/code&gt; with that:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Revision 3&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;preprocess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;InputArray input&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; OutputArray output&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Mat gray&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;cvtColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; gray&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; COLOR_BGR2GRAY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;blur&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;gray&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; output&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now instead of returning a new &lt;code&gt;Mat&lt;/code&gt; object, whatever we pass into &lt;code&gt;output&lt;/code&gt; will be written to.&lt;/p&gt;
&lt;p&gt;Why would we want to do this? Well, when you’re writing computer vision code, you need to be careful about how your image data is being passed around. After all, the images you’re passing around are uncompressed; a 4000x4000 image in BGR888 format would take around 48 megabytes of space in RAM. That’s not a lot, but it adds up fast, particularly if you’re parallelizing or running on a mobile platform. If we gave that image to Revision 2 of the &lt;code&gt;preprocess()&lt;/code&gt; function, we would be allocating two copies of the image; one temporary (&lt;code&gt;gray&lt;/code&gt;) and one that we keep and return ( &lt;code&gt;output&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;With Revision 3, we’ve moved the decision to allocate the output from inside of the function to wherever it gets called. If you want a copy, call &lt;code&gt;preprocess(someMat, someOtherMat)&lt;/code&gt;. If you want to overwrite the original &lt;code&gt;Mat&lt;/code&gt;, just call &lt;code&gt;preprocess(someMat, someMat)&lt;/code&gt;, using the same object for the input and the output. If you’ve wondered why so many of OpenCV’s functions write outputs to an &lt;code&gt;OutputArray&lt;/code&gt; parameter instead of returning a &lt;code&gt;Mat&lt;/code&gt;, this is why!&lt;/p&gt;
&lt;p&gt;Now let’s say we &lt;em&gt;always&lt;/em&gt; want &lt;code&gt;preprocess()&lt;/code&gt; to operate in-place. We can make use of OpenCV’s &lt;code&gt;InputOutputArray&lt;/code&gt; to completely avoid allocating new images in &lt;code&gt;preprocess()&lt;/code&gt; and make the function a little easier to read:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;// Revision 4&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;preprocess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;InputOutputArray input&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;cvtColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; input&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; COLOR_BGR2GRAY&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;blur&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; input&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;Size&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Easy.&lt;/p&gt;
&lt;p&gt;As a footnote, you might be wondering to yourself, “Why not just avoid all of this and use &lt;code&gt;UMat&lt;/code&gt; everywhere?” The simple answer is that OpenCV functions that consume a &lt;code&gt;UMat&lt;/code&gt; will run on the GPU if it can, falling back on the CPU if not. If you pass a &lt;code&gt;Mat&lt;/code&gt;, it will always run on the CPU. Sometimes you’ll want to explicitly force an algorithm to run on the CPU (or bail on using &lt;code&gt;UMat&lt;/code&gt; when you run into some platform-specific bug), so having the ability to quickly switch between the two will save you a lot of time.&lt;/p&gt;
&lt;h2 id=&quot;optional-outputs-with-inputarray-and-outputarray&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#optional-outputs-with-inputarray-and-outputarray&quot; aria-label=&quot;optional outputs with inputarray and outputarray permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Optional outputs with &lt;code&gt;InputArray&lt;/code&gt; and &lt;code&gt;OutputArray&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;A nice trick you can do with &lt;code&gt;InputArray&lt;/code&gt; is making parameters optional. Let’s suppose we want to write a function that takes a &lt;code&gt;Mat&lt;/code&gt; and a mask (also a &lt;code&gt;Mat&lt;/code&gt;):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;someFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;InputArray input&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        OutputArray output&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        InputArray mask&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 1. Use the mask on the input&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 2. Write something into the output&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Masks in OpenCV’s own functions are typically optional; that is, you can pass in &lt;code&gt;noArray()&lt;/code&gt; and no masking operation will take place. We can do that in our function as well:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;void&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;someFunction&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;InputArray input&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        OutputArray output&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        InputArray mask &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;noArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;mask&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;empty&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// 1. Use the mask on the input&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// 2. Write something into the output&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is a trivial detail, but writing the function this way makes it so that if you don’t want a mask, you can just omit the parameter entirely instead of writing in &lt;code&gt;noArray()&lt;/code&gt; yourself.&lt;/p&gt;
&lt;p&gt;A more interesting case is the ability to make an &lt;code&gt;OutputArray&lt;/code&gt; optional. Let’s suppose we’re writing a function that tells us how many closed edges it could find in an image (and for good measure, let’s use Revision 3 of the &lt;code&gt;preprocess&lt;/code&gt; function we wrote earlier):&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getNumberOfClosedEdges&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;InputArray input&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Mat processed&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; edges&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;preprocess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; processed&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;Canny&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;processed&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; edges&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;170&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// Imaginary function that returns the number&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// of closed edges in `edges`&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;numberOfClosedEdges&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;edges&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All we care about when we’re using this function is the number of closed edges. However, you can use the result of the Canny edge detection (&lt;code&gt;edges&lt;/code&gt;) for visualization purposes or other processing tasks later on, so wouldn’t it be nice if we could optionally choose to keep it?&lt;/p&gt;
&lt;p&gt;&lt;code&gt;OutputArray&lt;/code&gt; has a read-only &lt;code&gt;needed()&lt;/code&gt; property, which returns &lt;code&gt;false&lt;/code&gt; if its backing object is a &lt;code&gt;noArray()&lt;/code&gt; instance. Let’s use that with our function:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;cpp&quot;&gt;&lt;pre class=&quot;language-cpp&quot;&gt;&lt;code class=&quot;language-cpp&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getNumberOfClosedEdges&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;InputArray input&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        OutputArray outputEdges &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;noArray&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  Mat processed&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; edges&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;preprocess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;input&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; processed&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token function&quot;&gt;Canny&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;processed&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; edges&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;170&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;outputEdges&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;needed&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    edges&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;copyTo&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;outputEdges&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;// Imaginary function that returns the number&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;// of closed edges in `edges`&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;numberOfClosedEdges&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;edges&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Now we have an optional parameter to write the Canny results into if we want them. This technique is particularly useful for cases where you have an image processing pipeline with several steps and you want to store intermediates for visualization or debugging.&lt;/p&gt;
&lt;h2 id=&quot;links&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#links&quot; aria-label=&quot;links permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Links&lt;/h2&gt;
&lt;ul class=&quot;bullet-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/opencv/opencv/wiki/Coding_Style_Guide&quot;&gt;Coding Style Guide · opencv/opencv Wiki · GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.opencv.org/4.0.1/d4/d32/classcv_1_1__InputArray.html#details&quot;&gt;InputArray - OpenCV Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.opencv.org/4.0.1/d2/d9e/classcv_1_1__OutputArray.html#details&quot;&gt;OutputArray - OpenCV Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded></item><item><title><![CDATA[Randomizing UIColor with Method Swizzling]]></title><description><![CDATA[Lately, I’ve helped contribute to Slide for Reddit, an open-source Reddit client for iOS written in Swift. We’re reconsidering some aspects…]]></description><link>https://jons.website/blog/randomizing-uicolor-with-swizzling/</link><guid isPermaLink="false">https://jons.website/blog/randomizing-uicolor-with-swizzling/</guid><pubDate>Fri, 10 Aug 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Lately, I’ve helped contribute to &lt;a href=&quot;https://github.com/ccrama/Slide-iOS&quot;&gt;Slide for Reddit&lt;/a&gt;, an open-source Reddit client for iOS written in Swift. We’re reconsidering some aspects of our UI customization options, and I’m of the opinion that the user just doesn’t have the tools they need to make the app as ugly as humanly possible. As a joke, I wanted to randomize all the colors throughout the app just to see what it would look like. That led to an interesting question: is it possible to write an extension for &lt;code&gt;UIColor&lt;/code&gt; that forces all instances to be randomized when they are used?&lt;/p&gt;
&lt;p&gt;This was a surprisingly deep rabbit hole to jump into.&lt;/p&gt;
&lt;h2 id=&quot;first-steps&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#first-steps&quot; aria-label=&quot;first steps permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;First Steps&lt;/h2&gt;
&lt;p&gt;It is not possible to override a property or method inside of a Swift extension. This precludes doing something fishy like overriding &lt;code&gt;UIColor&lt;/code&gt;’s initializer. In any case, we want the color to change every time it is accessed, so we would need to override a property of &lt;code&gt;UIColor&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Interestingly, &lt;code&gt;UIColor&lt;/code&gt;s are not used directly for drawing; instead, they serve a &lt;code&gt;CGColor&lt;/code&gt; instance via their &lt;code&gt;cgColor&lt;/code&gt; property when accessed. If we could override &lt;code&gt;cgColor&lt;/code&gt; in our extension, we could return a random color from there, but this is not allowed. Or at least, it isn’t allowed in pure Swift.&lt;/p&gt;
&lt;p&gt;The Objective-C runtime allows us to perform &lt;em&gt;method swizzling&lt;/em&gt;, which is a technique that replaces the implementation of a selector with another implementation at run time. After a brief read on this topic, I had the following code:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;swift&quot;&gt;&lt;pre class=&quot;language-swift&quot;&gt;&lt;code class=&quot;language-swift&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UIColor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;jc_swizzle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; originalSelector &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token other-directive property&quot;&gt;#selector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;getter&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cgColor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; swizzledSelector &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token other-directive property&quot;&gt;#selector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;randomCGColor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; originalMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;class_getInstanceMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; originalSelector&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; swizzledMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;class_getInstanceMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; swizzledSelector&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
    &lt;span class=&quot;token function&quot;&gt;method_exchangeImplementations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;originalMethod&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; swizzledMethod&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token attribute atrule&quot;&gt;@objc&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;randomCGColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CGColor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CGColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
      colorSpace&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CGColorSpaceCreateDeviceRGB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      components&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CGFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;arc4random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UINT32_MAX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// R&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CGFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;arc4random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UINT32_MAX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// G&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CGFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;arc4random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UINT32_MAX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// B&lt;/span&gt;
        &lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// A&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;In &lt;code&gt;jc_swizzle()&lt;/code&gt;, we swap the getter for &lt;code&gt;UIColor.cgColor&lt;/code&gt; with the extension function &lt;code&gt;randomCGColor()&lt;/code&gt;. This in theory does what we want! Let’s see what it looks like:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1000px; max-width: clamp(200px, calc(0.46210720887245843* 80vh), 462.1px); max-height: 1000px;&quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/174a74a387ad857489e9bf17df33882f/78797/stage1.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 216.39999999999998%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,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&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Slide looking perfectly normal.&quot;
        title=&quot;Slide looking perfectly normal.&quot;
        src=&quot;/static/174a74a387ad857489e9bf17df33882f/00d43/stage1.png&quot;
        srcset=&quot;/static/174a74a387ad857489e9bf17df33882f/63868/stage1.png 250w,
/static/174a74a387ad857489e9bf17df33882f/0b533/stage1.png 500w,
/static/174a74a387ad857489e9bf17df33882f/00d43/stage1.png 1000w,
/static/174a74a387ad857489e9bf17df33882f/78797/stage1.png 1125w&quot;
        sizes=&quot;(max-width: 1000px) 100vw, 1000px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;What?! That looks good! That can’t be right. What happened?&lt;/p&gt;
&lt;h2 id=&quot;class-clusters&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#class-clusters&quot; aria-label=&quot;class clusters permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Class Clusters&lt;/h2&gt;
&lt;p&gt;As it turns out, Apple makes use of an Objective-C pattern called a &lt;em&gt;&lt;a href=&quot;https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/ClassClusters/ClassClusters.html&quot;&gt;class cluster&lt;/a&gt;&lt;/em&gt; in &lt;code&gt;UIColor&lt;/code&gt;. Under the hood, there are many private subclasses of &lt;code&gt;UIColor&lt;/code&gt;, but they’re all hidden from any public interface. That means we just overrode the method of a class that doesn’t actually ever get used.&lt;/p&gt;
&lt;p&gt;So then, let’s find out what class some random &lt;code&gt;UIColor&lt;/code&gt; instance resolves to. For &lt;code&gt;UIColor.red&lt;/code&gt;, that ends up being &lt;code&gt;UICachedDeviceRGBColor&lt;/code&gt;. Let’s work on that:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight has-highlighted-lines&quot; data-language=&quot;swift&quot;&gt;&lt;pre class=&quot;language-swift&quot;&gt;&lt;code class=&quot;language-swift&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UIColor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;jc_swizzle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// This resolves to `UICachedDeviceRGBColor`&lt;/span&gt;
&lt;span class=&quot;gatsby-highlight-code-line&quot;&gt;    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; _class&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnyClass&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;object_getClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;UIColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;red&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; originalMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;class_getInstanceMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_class&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token other-directive property&quot;&gt;#selector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;getter&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cgColor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; swizzledMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;class_getInstanceMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_class&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token other-directive property&quot;&gt;#selector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;randomCGColor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; originalMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; originalMethod&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; swizzledMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; swizzledMethod &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token function&quot;&gt;method_exchangeImplementations&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;originalMethod&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; swizzledMethod&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;dynamic&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;randomCGColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CGColor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CGColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;colorSpace&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CGColorSpaceCreateDeviceRGB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; components&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token class-name&quot;&gt;CGFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;arc4random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UINT32_MAX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// R&lt;/span&gt;
      &lt;span class=&quot;token class-name&quot;&gt;CGFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;arc4random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UINT32_MAX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// G&lt;/span&gt;
      &lt;span class=&quot;token class-name&quot;&gt;CGFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;arc4random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UINT32_MAX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// B&lt;/span&gt;
      &lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// A&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1000px; max-width: clamp(200px, calc(0.46210720887245843* 80vh), 462.1px); max-height: 1000px;&quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/51023eb02737342fe2529f68c4d3fd6f/78797/stage2.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 216.39999999999998%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,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&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Slide with mostly randomized colors.&quot;
        title=&quot;Slide with mostly randomized colors.&quot;
        src=&quot;/static/51023eb02737342fe2529f68c4d3fd6f/00d43/stage2.png&quot;
        srcset=&quot;/static/51023eb02737342fe2529f68c4d3fd6f/63868/stage2.png 250w,
/static/51023eb02737342fe2529f68c4d3fd6f/0b533/stage2.png 500w,
/static/51023eb02737342fe2529f68c4d3fd6f/00d43/stage2.png 1000w,
/static/51023eb02737342fe2529f68c4d3fd6f/78797/stage2.png 1125w&quot;
        sizes=&quot;(max-width: 1000px) 100vw, 1000px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This works. On the highlighted line, we get the class object for &lt;code&gt;UIColor.red&lt;/code&gt; (&lt;code&gt;UICachedDeviceRGBColor&lt;/code&gt;), which we then pass as the first argument to &lt;code&gt;class_getInstanceMethod&lt;/code&gt; instead of &lt;code&gt;UIColor.self&lt;/code&gt;. By swizzling &lt;code&gt;UICachedDeviceRGBColor&lt;/code&gt; we can affect many, many more colors.&lt;/p&gt;
&lt;p&gt;But who knows how many other &lt;code&gt;UIColor&lt;/code&gt; subclasses there are? I couldn’t stop here. I wanted to ruin &lt;em&gt;all&lt;/em&gt; the colors. The code that results from this path of inquiry is horrible and evil and will absolutely get you rejected from the App Store. Apple doesn’t like developers referencing private headers, after all. Let’s do it anyway.&lt;/p&gt;
&lt;p&gt;How can we reference the private internal objc classes that back &lt;code&gt;UIColor&lt;/code&gt;? Well, we can use &lt;code&gt;NSClassFromString()&lt;/code&gt; to get them if we know their names. We know about &lt;code&gt;UICachedDeviceWhiteColor&lt;/code&gt; and &lt;code&gt;UICachedDeviceRGBColor&lt;/code&gt; but who knows how many others there are under the hood?&lt;/p&gt;
&lt;p&gt;Well, I knows. The answer is ten:&lt;/p&gt;
&lt;ul class=&quot;bullet-list&quot;&gt;
&lt;li&gt;&lt;code&gt;UIDeviceRGBColor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UICachedDeviceRGBColor&lt;/code&gt; (derives from &lt;code&gt;UIDeviceRGBColor&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;NSColor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UIDisplayP3Color&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UIPlaceholderColor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UICIColor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UIDeviceWhiteColor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UICachedDeviceWhiteColor&lt;/code&gt; (derives from &lt;code&gt;UIDeviceWhiteColor&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UICGColor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;UICachedDevicePatternColor&lt;/code&gt; (derives from &lt;code&gt;UICGColor&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I found these by grepping through &lt;a href=&quot;https://github.com/nst/iOS-Runtime-Headers&quot;&gt;a dump of the private headers in iOS 11.4&lt;/a&gt;. If you’d like to do this yourself, run &lt;code&gt;grep -r -n &quot;.\+:\s*UIColor&quot;.&lt;/code&gt; in the terminal (you’ll also want to run this again for each subclass you discover, replacing &lt;code&gt;UIColor&lt;/code&gt; with the new class name just in case there are any subclasses of those). Let’s use these:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;swift&quot;&gt;&lt;pre class=&quot;language-swift&quot;&gt;&lt;code class=&quot;language-swift&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UIColor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;StaticVars&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;// Names of classes to swizzle. Derived from dumped private headers.&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; classesToSwizzle&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;String&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;UIColor&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;UIDeviceRGBColor&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;NSColor&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;UIDisplayP3Color&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;UIPlaceholderColor&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;UICIColor&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;UIDeviceWhiteColor&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;UICGColor&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;UICachedDeviceRGBColor&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;UICachedDeviceWhiteColor&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
      &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;UICachedDevicePatternColor&quot;&lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; randomColorBlock&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token attribute atrule&quot;&gt;@convention&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;block&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;AnyObject&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CGColor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token omit keyword&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;CGColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CGColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;colorSpace&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CGColorSpaceCreateDeviceRGB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; components&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CGFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;arc4random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UINT32_MAX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// R&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CGFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;arc4random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UINT32_MAX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// G&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CGFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;arc4random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UINT32_MAX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// B&lt;/span&gt;
        &lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// A&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;jc_swizzle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; className &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;StaticVars&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;classesToSwizzle &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; classFromString &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;NSClassFromString&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;className&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; originalMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;class_getInstanceMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;classFromString&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token other-directive property&quot;&gt;#selector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;getter&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cgColor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;method_setImplementation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;originalMethod&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;imp_implementationWithBlock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token function&quot;&gt;unsafeBitCast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;StaticVars&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;randomColorBlock&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; to&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnyObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
          &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This is much, &lt;em&gt;much&lt;/em&gt; more effective:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1000px; max-width: clamp(200px, calc(0.46210720887245843* 80vh), 462.1px); max-height: 1000px;&quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/3f17c602efdb35d67aae4df67375c418/78797/stage3.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 216.39999999999998%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,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&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Slide with fully randomized colors.&quot;
        title=&quot;Slide with fully randomized colors.&quot;
        src=&quot;/static/3f17c602efdb35d67aae4df67375c418/00d43/stage3.png&quot;
        srcset=&quot;/static/3f17c602efdb35d67aae4df67375c418/63868/stage3.png 250w,
/static/3f17c602efdb35d67aae4df67375c418/0b533/stage3.png 500w,
/static/3f17c602efdb35d67aae4df67375c418/00d43/stage3.png 1000w,
/static/3f17c602efdb35d67aae4df67375c418/78797/stage3.png 1125w&quot;
        sizes=&quot;(max-width: 1000px) 100vw, 1000px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;Note how everything is affected, including the individual drawable elements in the status bar:&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 1000px; max-width: clamp(200px, calc(8.333333333333334* 80vh), 1000px); max-height: 1000px;&quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/43b8a4475ff241c4ef82421932919f9f/78797/stage3-toolbar.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 12%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAACCAYAAABYBvyLAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAV0lEQVQI15XMMQ6AIBAFUW4BrLqAibEwodAYXBbvf6yvnMBYTDHNM84WzCQ4Y8M6VvQnd31nC7yvSFPDwYLMiuAKTAcSCfagWAb5BZJXRL6RuWJjBb/gA/T0OXal79/JAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;A close-up of the system toolbar with mostly randomized colors.&quot;
        title=&quot;A close-up of the system toolbar with mostly randomized colors.&quot;
        src=&quot;/static/43b8a4475ff241c4ef82421932919f9f/00d43/stage3-toolbar.png&quot;
        srcset=&quot;/static/43b8a4475ff241c4ef82421932919f9f/63868/stage3-toolbar.png 250w,
/static/43b8a4475ff241c4ef82421932919f9f/0b533/stage3-toolbar.png 500w,
/static/43b8a4475ff241c4ef82421932919f9f/00d43/stage3-toolbar.png 1000w,
/static/43b8a4475ff241c4ef82421932919f9f/78797/stage3-toolbar.png 1125w&quot;
        sizes=&quot;(max-width: 1000px) 100vw, 1000px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;This is a fine solution, but it doesn’t satisfy the engineer in me. What happens when iOS updates? What if there are classes that I missed?&lt;/p&gt;
&lt;h2 id=&quot;things-get-worse&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#things-get-worse&quot; aria-label=&quot;things get worse permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Things Get Worse&lt;/h2&gt;
&lt;p&gt;Shortly after writing this code, I was made aware of &lt;code&gt;objc_getClassList()&lt;/code&gt;. This creates a list of class objects for &lt;em&gt;every single&lt;/em&gt; class loaded at runtime. In fact, on my phone running iOS 11.3.1, that list contains 25,265 elements. Let’s parse these instead of keeping a list of strings:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;swift&quot;&gt;&lt;pre class=&quot;language-swift&quot;&gt;&lt;code class=&quot;language-swift&quot;&gt;&lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extension&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UIColor&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;struct&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;StaticVars&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; randomColorBlock&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token attribute atrule&quot;&gt;@convention&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;block&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;AnyObject&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CGColor&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token omit keyword&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;CGColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CGColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;colorSpace&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CGColorSpaceCreateDeviceRGB&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; components&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CGFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;arc4random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UINT32_MAX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// R&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CGFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;arc4random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UINT32_MAX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// G&lt;/span&gt;
        &lt;span class=&quot;token class-name&quot;&gt;CGFloat&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;arc4random&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Float&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;UINT32_MAX&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// B&lt;/span&gt;
        &lt;span class=&quot;token number&quot;&gt;1.0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token comment&quot;&gt;// A&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;!&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;static&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;jc_swizzle&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token comment&quot;&gt;// Returns true if the given class has `superclass` anywhere in its class hierarchy&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;func&lt;/span&gt; &lt;span class=&quot;token function-definition function&quot;&gt;isClassSubclassOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token omit keyword&quot;&gt;_&lt;/span&gt; base&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnyClass&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; superclass&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnyClass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;-&gt;&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Bool&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; _class&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnyClass&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; base
        &lt;span class=&quot;token keyword&quot;&gt;while&lt;/span&gt; _class &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; &lt;span class=&quot;token nil constant&quot;&gt;nil&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;&amp;amp;&amp;amp;&lt;/span&gt; _class &lt;span class=&quot;token operator&quot;&gt;!=&lt;/span&gt; superclass &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
            _class &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;class_getSuperclass&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;_class&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; _class &lt;span class=&quot;token operator&quot;&gt;==&lt;/span&gt; superclass
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; classCount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;objc_getClassList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token nil constant&quot;&gt;nil&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; allClasses &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UnsafeMutablePointer&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;AnyClass&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;allocate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;capacity&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;classCount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt; autoreleasingAllClasses &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AutoreleasingUnsafeMutablePointer&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;AnyClass&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;?&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;allClasses&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    classCount &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;objc_getClassList&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;autoreleasingAllClasses&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; classCount&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;for&lt;/span&gt; i &lt;span class=&quot;token keyword&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;..&amp;lt;&lt;/span&gt; classCount &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token keyword&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; currentClass&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnyClass&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; allClasses&lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;Int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;i&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;isClassSubclassOf&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;currentClass&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; superclass&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;UIColor&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;let&lt;/span&gt; originalMethod &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;class_getInstanceMethod&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;currentClass&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token other-directive property&quot;&gt;#selector&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;getter&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; cgColor&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token function&quot;&gt;method_setImplementation&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;originalMethod&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;imp_implementationWithBlock&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
          &lt;span class=&quot;token function&quot;&gt;unsafeBitCast&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token class-name&quot;&gt;StaticVars&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;randomColorBlock&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; to&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;AnyObject&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
      &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Here we use &lt;code&gt;objc_getClassList&lt;/code&gt; to look through &lt;em&gt;every single class&lt;/em&gt; registered at runtime, swizzling the ones that derive from &lt;code&gt;UIColor&lt;/code&gt;. This has two benefits. Firstly, because we’re not directly referencing any private derivatives of &lt;code&gt;UIColor&lt;/code&gt;, we’re probably &lt;em&gt;(probably)&lt;/em&gt; not going to get rejected from the App Store for using this code. Secondly it is better from the standpoint that it will be resistant to changes in iOS in the future. This is guaranteed to replace all &lt;code&gt;UIColor&lt;/code&gt; instance getters with the new random color logic, satisfying my original goal.&lt;/p&gt;
&lt;p&gt;With that, we have an answer to &lt;em&gt;“Can I?”&lt;/em&gt; Perhaps the next article should go into &lt;em&gt;“Should I?”&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Spurious (Spatial) Correlations]]></title><description><![CDATA[We all know you can lie with graphs, but how well can you lie with spatial data? In grad school, I took a course called Spatial Analysis. In…]]></description><link>https://jons.website/blog/spurious-spatial-correlations/</link><guid isPermaLink="false">https://jons.website/blog/spurious-spatial-correlations/</guid><pubDate>Fri, 13 Apr 2018 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;We all know you can lie with graphs, but how well can you lie with spatial data?&lt;/p&gt;
&lt;p&gt;In grad school, I took a course called Spatial Analysis. In it, I learned how to analyze geospatial data and look for trends. For our term project, we were each to take a spatial dataset relevant to our fields and apply our skills. I recalled Tyler Vigen’s &lt;a href=&quot;http://www.tylervigen.com&quot;&gt;Spurious Correlations&lt;/a&gt;, a website that draws correlations between (hopefully) unrelated data sets such as the divorce rate in Maine and margarine sales per capita. There is a wealth of freely available spatial data made available by government agencies and ESRI, so I thought it would be funny to try out similar techniques with these data sets for the state of Maine.&lt;/p&gt;
&lt;p&gt;These are my results.&lt;/p&gt;
&lt;h2 id=&quot;eagles-and-k-cups&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#eagles-and-k-cups&quot; aria-label=&quot;eagles and k cups permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Eagles and K-Cups&lt;/h2&gt;
&lt;p&gt;With the exception of Washington County, eagles seem to make their homes in areas where household K-Cup ownership is at or higher than the national average.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;EaglesAndKCups.png&quot;&gt;Eagles and K-Cups&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;schools-and-aquifers&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#schools-and-aquifers&quot; aria-label=&quot;schools and aquifers permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Schools and Aquifers&lt;/h2&gt;
&lt;p&gt;589 of Maine’s 795 schools are within 3 km of an aquifer. This means that if you are at a school, there is a 74% chance that you are within walking distance of a significant source of groundwater.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 815px; max-width: clamp(200px, calc(0.7716049382716049* 80vh), 771.6px); max-height: 1000px;&quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/9c147009e74113a05d3da1a922391fd9/ef916/SchoolsAndAquifers.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 129.6%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAaCAIAAAA44esqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAEsUlEQVQ4y0WR228bRRTG/R+jSjyWChBSBQKBQkXpJbRQNamjpGnrtHGSJrZje3ftvd/s9XXvu3Of2bS8w9otHJ2HGY1+833fOQ3+uRils9lyuQy5EIKzRQ5TRD4KQRgrMWIEU0o55xBCAABjjHPe2HC8qsQsWHhuwBirKpEDMM3AJEfzEkrLSFlmEcSCs6qqJEm6uuoILj7BoqrSJPO9AGNSVRUleJXDAFVuQSYlCjKYIKqkEGCKIAqCmeO4RVHUcG2jhFGUIow3fpmfArXgC8QjRGOIMWVZUZ7MkxDiG8ElWdYNU1RVDWdZhhCqKrFNDkEZQrrCAjGeQRTkcI2rYQqbszBBRHC2u/u42TzgXDDGG5vkm+CbU5pmZVEgAACACELOmQP4HBI1SrOi/HDzIcvzEgAhBGOswRijlDLGhBBgU7AuRAhFGLsJ8HOc0GpVkjTPBd+sopatkcZWc7uGNMu2y8AIU0IgJmZGpjkqqTABWxVFLbcxuPmitv3pjjFO05RyASBMIIGUQ0LNnI4y6pRMK3CQZltFSilCCGPcQAhRSquqQgglaZYSoS+TcQytdVogbBXMLfAcV3bJw7y8EYIQSgjZpEMNSmtZgrEXpnPEvIL0/ZWVUb8g6zjtL1MjLmPMpbDUpgsAIKGUUfrJdh2A8/k6Godlf53rCbJXiZFhH1VGgpwUSCEYpciKSzssrDCljBKMt2EbhFI/zrVVpsVQyqspqlYFnEEaYqYkUElQZxWP4tKLCj/Ds6TgjG7kuBC8ARHqrUofcDMFalRaJddy6pR07fp2lA1S5ANqJlAKa2VbtQLLAbCeVlmCBibUSeF0lThxIcVAL4gf5fNgHtn+MMqv48JKgJazfso6ayDH4OpaHh6+nM5WpuE2EGFqVM7ifIX5qE6YyIu1tE68sdnWrCfGSJrHUgT7CRujv0328fVwvP/8xWy6rGGCsZVjOUVKmCs57CWw7UzfeoE6XfZV+zJYXqewWz/RI33y6PRy//LasidBsDBNr4adnLxb5mchOJnF2sg4kkbnwbqdwD/H2r6kvjHd5rP9p3vNn+4/PDw41kaGZbiW4Vmm10CU6hmRUiRH2ftF8mY42JeVy1nkevPjw+Mff/7l6c6v7Sd/vX93rquW60xty7dMb9sNQEg/Ktr+8tD2dvuD1mTWHatu69R9tHt69/sfv/r68Xd3pbNL25v9x/wPE0q7MToxgz3DezZb7jSbf9z64vk33z68fefsuHXWaqtjw3GmrjO1TM803M+9gTGhV2H5IogfmMYPv9+7c+vL+7fvnLw66V9L8nCsDEeOPel1+q3W6XAwMnRH12xDd9SxWU+7LOFFWLxeFzut4/17O4ZsGM7UdwPP8qeThW35puEOB8r7i6tudyBLmjQYXfeGiqyZutMghJ4vkueGffnbA3Vs2bb/5rh10Dza2zt4+ODx0eErQ3cM1dZ15+K8c3V5fXF+dXHekSTVNJxGJYS2XLe7/X5vaNsTy/RkSe11Bu3Ti3dvzxRZs01P0V3Z8Hqdfq837HYHmmqpY8PQnYa4uUFx1H15LCv6dg2OPXGdqe/NPDdQZFWR1bGijWV1PNI3Z308qvtf+B8rXSiJMQ2STwAAAABJRU5ErkJggg==&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Schools and Aquifers&quot;
        title=&quot;Schools and Aquifers&quot;
        src=&quot;/static/9c147009e74113a05d3da1a922391fd9/ef916/SchoolsAndAquifers.png&quot;
        srcset=&quot;/static/9c147009e74113a05d3da1a922391fd9/63868/SchoolsAndAquifers.png 250w,
/static/9c147009e74113a05d3da1a922391fd9/0b533/SchoolsAndAquifers.png 500w,
/static/9c147009e74113a05d3da1a922391fd9/ef916/SchoolsAndAquifers.png 815w&quot;
        sizes=&quot;(max-width: 815px) 100vw, 815px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;us-cellular-coverage-and-oil-spill-hotspots&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#us-cellular-coverage-and-oil-spill-hotspots&quot; aria-label=&quot;us cellular coverage and oil spill hotspots permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;U.S. Cellular Coverage and Oil Spill Hotspots&lt;/h2&gt;
&lt;p&gt;US Cellular offers great coverage in areas where hazardous oil spills occur the most.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 815px; max-width: clamp(200px, calc(0.7716049382716049* 80vh), 771.6px); max-height: 1000px;&quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/355ad21c7a272a862beba74734da2958/ef916/OilSpillsAndUSCellularCoverage.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 129.6%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAaCAIAAAA44esqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAE1ElEQVQ4yzVTS08bVxj1L+qyi0qt1H1XXXVRqVWqLCqluyjdkJJFoyi0iUhUQkigCklEMAo2MRjzxgTwY8bzHr/A75m5c99zxyaoD1Vqx1O+xehe6Z7vfOecbxLBVXHGms1Wq9UVQgRB4LouhCgMQ845xohSyjnv9XqWaWmadt46F2GYGOOCMBTNxrltNTjnYSgQQp7ngXE5jjPo930AwjD0fT+fz69n1l3PC2OwCENn4FbtBiE0DENCiO/7QkQtEEIYY8a4CyNyCGGtVpPliuO4QogEQgj6qNdzMCFCCM45AIAxFgshhDAeAB8Y+QMH06EQxWJR0/RYTsJ1XYxxGIpYOYSQUhqfMcY+AOLD5ZmiZO5P1dloxNnCwvxyMhlENEGC8yvDxifHcQEAEMYjo8iP4dA5b+s7+wNMR8PQ9TwfwnjGBOecMcY5F0LAccVKKWUEY9d1EYThMMR//g0QCcbPgkBwHkESMWcs0nXdIAjGYEIJxRjHvVg4PK622o2GGEuNPB7HGTHHd0KI4zixyYRQHgSUUkIIQQiI0ZpcPdNUMRyycWGMCSGJcRIsDEM8HjIIgna7DQDo9fp4/AQREgZBiw1bPh4KQSmLM0MIJ2JajHG/3x8vE7HMKkZR417fAY5DgEcZA67TrNchRDHz/2PHVrfabddxPM+DEHbaXQiREMJxPQD85gD4EAHgI4Q7nU7ES2gsNsEY63Z77XYHAHAVNeKMIcY9iLItlG1Fvg0GTuSo57GrbIUIIs2O4xBCAACu6/Fon3yISXFA187RXHtkkpHnut1uDxLW18rt4jEkUYq+DxOUUtf1/PE/4HkAUQoJq3cHi3X8W+sis7rVMQzEOILQh9Af9G1d29rebdRbmmolKGWDfn8AfHL5hw2o1HbzcJQzzl7IZ6nssfLxR5JigiDACF5eXl58uCyWSq9fvW7GYIIxoLxfa5T3jl51xHSNLq9szG6czHQ+zK3uvnwwk9K6lt0o9fGWpKdTq5l3G5ZZbzTOdc1OEIzOSZCXrKX0/rQFH+teano2uVt67vz1+8vl+4up+YXkw0ezP71M3516mHyzIpU1TbU01YrAjJIOYvkWeHFqP3T/WVlOZyYmp5rD+SZ/mnx369cnk89fP1te3d0+0FXTthqmUdM129CrEZhSCiCq1pvJN+nc9evPtk4fZfL3K4O56aeLtycm7/3y4MHj/b28phoVWVcq0bci67IU8Uc5e45T7XvZ7cPcxMTsZ598dePHHx4t3LlzN7u2kd3cqciaWjGW3rxdSaZOT0qKYhh6VZY0pWJEhrkeMBygXf/61eef3rj23e3Jn9czm6en5UJRLhYk06hVZM0+SOW3d7LZndOTUuFEOj0pR8wgWshOr1Y/+PKL1Vs3S0bN1Gu21TSNer16pmu2plmKrDn3bhbSqZ3Dk4O9/Pq77Pb2wdhtEQ6Oj1rff7t+7ZuiapmqtZZeX0mmlpZW5ubmV9+uaaqlyPrW88WdTC63tXd48F6R9XKxoipmIhhd9KSCNjN19L5gmnVds4sF+ejwZCu3u5ndLhZl06hJkrpatnP7x5uZ3PujgqoYpaIcaQ4vLtxGPTfzpCRrhmbrmm0aNcusV+2mbTVKRblUkGVJVcqViqTKkiqVVamklEvKf8z/ArCLHEAyWyMJAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Oil Spills and U.S. Cellular Coverage&quot;
        title=&quot;Oil Spills and U.S. Cellular Coverage&quot;
        src=&quot;/static/355ad21c7a272a862beba74734da2958/ef916/OilSpillsAndUSCellularCoverage.png&quot;
        srcset=&quot;/static/355ad21c7a272a862beba74734da2958/63868/OilSpillsAndUSCellularCoverage.png 250w,
/static/355ad21c7a272a862beba74734da2958/0b533/OilSpillsAndUSCellularCoverage.png 500w,
/static/355ad21c7a272a862beba74734da2958/ef916/OilSpillsAndUSCellularCoverage.png 815w&quot;
        sizes=&quot;(max-width: 815px) 100vw, 815px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;cemeteries-and-broadband-coverage&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#cemeteries-and-broadband-coverage&quot; aria-label=&quot;cemeteries and broadband coverage permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Cemeteries and Broadband Coverage&lt;/h2&gt;
&lt;p&gt;3875 of Maine’s 3929 cemeteries are located exactly within broadband coverage areas (98.63%).&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 815px; max-width: clamp(200px, calc(0.7716049382716049* 80vh), 771.6px); max-height: 1000px;&quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/2f987a1b2366d8806200948347746128/ef916/CemeteriesAndBroadband.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 129.6%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAaCAIAAAA44esqAAAACXBIWXMAAAsTAAALEwEAmpwYAAAFLklEQVQ4yz2R2W8bVRTG5w8CiRckJF54A96oAKlIVNBWRRSaSm1RUpR0S2jTLSFNSrMobUJb0jhxm4TWjbc0thPbY8++eMbLeMb2jGe5M3dm7DQB3sB2y9HR1b3S/c53zu8g3ttwISyVJElSfN/3PE/TNNOy2u09z3WBqTsQQuj6vm+apq7rvu/5vo90dV6r5ZeKFZ4ruq7bavmWaTZ1vamqilzhcJTM5fSm6nmeIsuxaDwWjddqNQhhR+y3WmpDK/BF23ZarZZt25ZpNSyDKwtUiRNxpkBWsCIHDF0URJblREFgGdZ2HMSyLNOwajUV2Lbv+67r6rruQggcx4SwrqmmBUgO20rHtLqyv3+AolmCIF/v7/ueh2iaBgBotfze5KZpOo7TacfzHBs0DYMXmVwmtr4+r9YVz/fvz88HAiuu57mui7juW2Ddm6pquq6bpmWalmVZrt9CqTRBZyPJP6WKsL9/oGmaYZq9HhHXdTsc3TckzZ7IAo4DbRs0VU2pFPcP/q4qVakstNrtrpHvuh0J0vOEEPbW43leRwps23ZsAFTTqFSq1UoF5/NSWfD9dq/B3jo7zr23bdsNVfU9H9jAkg1oQRc6smHmeDqdT+ymwtWy6Pst2A3QLY8AACCEvQ01m03P96qyrDf1Wq3e+eFAUuRkRcKTO1JFbO+9drrRnQ4g/9tKslJqambTZFDWBBYAoF5v1CSJk0qkyCQTIZohbQCg40AXvmm7h7paraqNRlGparpREouiIrfbex3uTR3nySSL8wWOwwvFYtGxOzh6wyIQQkVRpGrV0JrQhJVmXZJlJsMJRQFnaFwg0rvhDJ4hCgytSJVaze/i6h0IALamasACvCxWhYrI0ukYEY2sLz+bWZ9b3grF0GikUa/XNE3kSjmS5qi8YRi27RiGidiWJdUUTpEwlEdfcjuBzeXF2UfLE4Hgva3d5zuxDBrMN+S64zgNRcbI3NqL4PqTlXJJpkgOAZZJi0KxVk2svhg5NTT54NJm7HE8srq+sfB0Yy64sRBNhfAC3VDVpmVQBeLJs6WZ2elySSYJFrEdW+YkYmc7HF2aCYzcXbiy+mwuEJybfTR6Z/bik+V7ycRGKh3H8Mz84sTY5OjD1T+4olQUKxTFI9BxRBq/Nzt6++7g0Pj3MwvXxucGh6f6Jh4M3ZgaGB07/2Dx17MDR4evnb9862rgRQinCxTB0iRHUzxi21Z6e3P60Ujf9S8Hbh8bnjw9Mnlm/LcLgbXp8anLp85880PfV4NXz0TTGbJQYlmRITmK4uluItC2FwNjFydOnhz+4qcb3/bfPHbh+qnLY33jd36emLo1NNh/fexaAs2JgsR03Wi6wLxNxHfdh8sT3136bHrx6pW7fZ8cef/Dj9853ne4/5cLG6lkKJvB2QKOMZl0HstTBM70EsfoDjAX2AM3jp64eOjsza9Pnz9y+OjnJ84df/7qVaZYyVJsJk8yVCEe314NrqUSaQKnsTzZq4LlScQD7qXJHw+d+2B0qn9h9TEulHlB4gtlluIFvkRTPEWxeJrCM3Q4HI9GtiLheCgUSaWyOEYhe1775tzApz++NzV3i+iQZNaebqwEgktLK7Oz958GNwic4QmuQLCbL6Px2HZ4M5ZKpt84/3Xwz3ro94+OvbubxVhaoCk+m8GS27vhzdjLUATN4gzFZ3AyTdCJrVQysbv9aieHEjhGYXkK2dt7LUul6YU7GCP0FsAyAseKBb7Ec0U0i6FZLI8SeRTP54hctnN2LijxH7B/AVZR41Mw+chaAAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Cemeteries and Broadband Coverage&quot;
        title=&quot;Cemeteries and Broadband Coverage&quot;
        src=&quot;/static/2f987a1b2366d8806200948347746128/ef916/CemeteriesAndBroadband.png&quot;
        srcset=&quot;/static/2f987a1b2366d8806200948347746128/63868/CemeteriesAndBroadband.png 250w,
/static/2f987a1b2366d8806200948347746128/0b533/CemeteriesAndBroadband.png 500w,
/static/2f987a1b2366d8806200948347746128/ef916/CemeteriesAndBroadband.png 815w&quot;
        sizes=&quot;(max-width: 815px) 100vw, 815px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;h2 id=&quot;red-cross-facilities-and-bedrock-formation-eras&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#red-cross-facilities-and-bedrock-formation-eras&quot; aria-label=&quot;red cross facilities and bedrock formation eras permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Red Cross Facilities and Bedrock Formation Eras&lt;/h2&gt;
&lt;p&gt;In what I can only consider to be a deliberate move, Red Cross has built their facilities in Maine on top of bedrock formed before the Devonian era. This means that if you got into a time machine and went back to the period at which the bedrock was formed beneath any Red Cross facility, you would not find sharks, ferns, trees, insects, or land vertebrates.&lt;/p&gt;
&lt;p&gt;&lt;span
      class=&quot;gatsby-resp-image-wrapper&quot;
      style=&quot;position: relative; display: block; margin-left: auto; margin-right: auto; max-width: 816px; max-width: clamp(200px, calc(0.8802816901408451* 80vh), 880.3px); max-height: 1000px;&quot;
    &gt;
      &lt;a
    class=&quot;gatsby-resp-image-link&quot;
    href=&quot;/static/d7e56ee7d80d91d4323cc827b3abe804/b4098/RedCrossAndBedrock.png&quot;
    style=&quot;display: block&quot;
    target=&quot;_blank&quot;
    rel=&quot;noopener&quot;
  &gt;
    &lt;span
    class=&quot;gatsby-resp-image-background-image&quot;
    style=&quot;padding-bottom: 113.6%; position: relative; bottom: 0; left: 0; background-image: url(&apos;data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAXCAIAAACEf/j0AAAACXBIWXMAAAsTAAALEwEAmpwYAAAEgElEQVQ4y2WUW2zbZBTH/c4rPPHGG7zwjMTgASExtMdJaJoQE0KMiYFAmwYUCTbGpoHEtqKNbW3UC51269K0S5usa9O0uTZuajuxkzRXu7ET258/+/MlaVI7i1HKRSv76+g8fNLv/I++c3QwAIC6p3KpxtcFqKpQhzJQFEWBQAEAwH+lqmqv13OfEaYoimEYtSpXLtWQjnSoqRtNHUGkaoKua1DTENIGaZBt294Ha5oq8A2GLqiqZnZNY43bnFeKUmeFdR/dyvAVWjctbU8Iof87i6JYrbJAVoy2ASl+Y7GxSLuPs/3Vk+KDM+e/yh5ECvpbMpBrHAshfPr0qeM4tm1joighpCNLV2tyagYs0v0w5y7NSunT5C+xY6dW3oUIIg3phi7yjWKEFCXJ0A2EUKfTwSCECOmmoVZYcynbD+XcmYVW4Qs8ElKeZKsXFz7ZBhUDmbqh83WewAmW42zbdno923EwAABCCKpaumQvZNtP7sHAO0n8u0og7d71M9/Pf7ktlU1kGZZeLwr4cL5eqbd22q7rdrtdDCgKQlCWnDkK/Bb0eB53Z9d3l1Z7jz4Ojd776UJpSJBruqob7VadpPAjH9WYHLddN00TIR0DQO60u/HtxOHZNz2p1SjuRHI7q9M73vg35xqByeZd1eI1FekI5YuFcf8dUZYMw3TdvuM4mAKhVlev+66PkOuRqVbsNp9I7gYYdbgYOOVHK0ncEhBUoGmgPCue8VVKLC+JIsuyCCEMtHatxLHG4aHosBuarS/n+iHGHYu5Q+HWNWaE+3nxxgygOLljaKWGMrq1w0uKAkCz0dQRwvBJIX/1UubycmRSC2btObI9njYuxKkrW2OResa73HzFK0dY6Fgm32xmqiVFGXywbTuDtsuXSuGLG2ESebO9KwlpTBm/BaaPJt86cv/lS0HPZ2vsB364wYBcTd2uUi3tD47bajQkezAuByt7hWD43sMC72GYm2DqjjnyYfrV9z0vHho/+mu44EvZc3F7RvEvKA/zeNkiNQQ1wzRUqOq6jkVD5Ud8OUB1HzRD/vrSp+TrB2+8dG18ZS7Q3YzYxJodIram0f14/UkpmjfPRYUSJ8piu9VGGsIes8Any9O612dNXKW/Pv/7obURnljpiSMCPiH7SDeaaaZyaZqspBKhWPC4UK+IktzpdAa7nT09lDpxwCufHRVP3/7zx7uTiAtHyfmhRNC8teoupLbzVJYimAyZT1H4muGXFNEyLQBAq9XC2PcOtjGMOPTa2Ohx/Afx2ymteXKRuh2e39RnkzIxwBiSZDJUPrWBrxX8lWpJEiXLMgfOnoh288TbwQMvCJ/PFm9ICw8o7o3l/NQWkWNoIpMhaYpk/gmCFtgmAECWB20Pdvvaknn2whH6io9d5hkim2NoMs+QNJ35j9kLkqDzueKzx6Df72MTS2V86nJlJZEuFEiKJol9zLNwjik6jrPvkjBqaVnayFA5ah9Gk8Reob1HYjO7mc7kc8/BTUGgiX2GGSq3nsTj0WQsmozHkvHYemo9jaeI5+G/AHB9dRz09Px1AAAAAElFTkSuQmCC&apos;); background-size: cover; display: block;&quot;
  &gt;&lt;/span&gt;
  &lt;img
        class=&quot;gatsby-resp-image-image&quot;
        alt=&quot;Red Cross Facilities and Bedrock Formation Eras&quot;
        title=&quot;Red Cross Facilities and Bedrock Formation Eras&quot;
        src=&quot;/static/d7e56ee7d80d91d4323cc827b3abe804/b4098/RedCrossAndBedrock.png&quot;
        srcset=&quot;/static/d7e56ee7d80d91d4323cc827b3abe804/63868/RedCrossAndBedrock.png 250w,
/static/d7e56ee7d80d91d4323cc827b3abe804/0b533/RedCrossAndBedrock.png 500w,
/static/d7e56ee7d80d91d4323cc827b3abe804/b4098/RedCrossAndBedrock.png 816w&quot;
        sizes=&quot;(max-width: 816px) 100vw, 816px&quot;
        style=&quot;width:100%;height:100%;margin:0;vertical-align:middle;position:absolute;top:0;left:0;&quot;
        loading=&quot;lazy&quot;
      /&gt;
  &lt;/a&gt;
    &lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Disclaimer:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;These datasets are in no way scientifically rigorous.&lt;/p&gt;
&lt;h2 id=&quot;sources&quot; style=&quot;position:relative;&quot;&gt;&lt;a href=&quot;#sources&quot; aria-label=&quot;sources permalink&quot; class=&quot;anchor before&quot;&gt;&lt;svg aria-hidden=&quot;true&quot; focusable=&quot;false&quot; height=&quot;16&quot; version=&quot;1.1&quot; viewBox=&quot;0 0 16 16&quot; width=&quot;16&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;Sources&lt;/h2&gt;
&lt;ul class=&quot;bullet-list&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://www.maine.gov/dep/gis/datamaps/&quot;&gt;Maine Department of Environmental Protection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://www.maine.gov/megis/catalog/&quot;&gt;Maine Office of GIS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://usm.maine.edu/gis/digital-atlas&quot;&gt;University of Southern Maine’s Digital Atlas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;ESRI Online Catalog&lt;/li&gt;
&lt;/ul&gt;
&lt;!--
                                __.--&apos;~~~~~`--.
             ..       __.    .-~               ~-.
             ((\     /   `}.~                     `.
              \\\  .{     }               /     \   \
          (\   \\~~       }              |       }   \
           \`.-~ -@~     }  ,-,.         |       )    \
           (___     ) _}  (    :        |    / /      `._
            `----._-~.     _\ \ |_       \   / /-.__     `._
                   ~~----~~  \ \| ~~--~~~(  + /     ~-._    ~-._
                             /  /         \  \          ~--.,___~_-_.
                          __/  /          _\  )
                        .&lt;___.&apos;         .&lt;___/
--&gt;</content:encoded></item></channel></rss>