title: Swift numerics and CGFloat (CGPoint, CGRect, etc.)
body: <p>I'm finding Swift numerics particularly clumsy when, as so often happens in real life, I have to communicate with Cocoa Touch with regard to CGRect and CGPoint (e.g., because we're talking about something's <code>frame</code> or <code>bounds</code>).</p>
  
  <h3>CGFloat vs. Double</h3>
  
  <p>Consider the following innocent-looking code from a UIViewController subclass:</p>
  
  <pre><code>let scale = 2.0
  let r = self.view.bounds
  var r2 = CGRect()
  r2.size.width = r.size.width * scale
  </code></pre>
  
  <p>This code fails to compile, with the usual mysterious error on the last line:</p>
  
  <blockquote>
    <p>Could not find an overload for '*' that accepts the supplied arguments</p>
  </blockquote>
  
  <p>This error, as I'm sure you know by now, indicates some kind of impedance mismatch between types. <code>r.size.width</code> arrives as a CGFloat, which will interchange automatically with a Swift Float but cannot interoperate with a Swift Double variable (which, by default, is what <code>scale</code> is).</p>
  
  <p>The example is artificially brief, so there's an artificially simple solution, which is to cast <code>scale</code> to a Float from the get-go. But when many variables drawn from all over the place are involved in the calculation of a proposed CGRect's elements, there's a lot of casting to do.</p>
  
  <h3>Verbose Initializer</h3>
  
  <p>Another irritation is what happens when the time comes to create a new CGRect. Despite the documentation, there's no initializer with values but without labels. This fails to compile because we've got Doubles:</p>
  
  <pre><code>let d = 2.0
  var r3 = CGRect(d, d, d, d)
  </code></pre>
  
  <p>But even if we cast <code>d</code> to a Float, we don't compile:</p>
  
  <blockquote>
    <p>Missing argument labels 'x:y:width:height:' in call</p>
  </blockquote>
  
  <p>So we end up falling back on <code>CGRectMake</code>, which is no improvement on Objective-C. And sometimes CGRectMake and CGSizeMake are no improvement. Consider this actual code from one of my apps:</p>
  
  <pre><code>let kSEP : Float = 2.0
  let intercellSpacing = CGSizeMake(kSEP, kSEP);
  </code></pre>
  
  <p>In one of my projects, that works. In another, it mysteriously fails — the exact same code! — with this error:</p>
  
  <blockquote>
    <p>'NSNumber' is not a subtype of 'CGFloat'</p>
  </blockquote>
  
  <p>It's as if, sometimes, Swift tries to "cross the bridge" by casting a Float to an NSNumber, which of course is the wrong thing to do when what's on the other side of the bridge expects a CGFloat. I have not yet figured out what the difference is between the two projects that causes the error to appear in one but not the other (perhaps someone else has).</p>
  
  <p><strong>NOTE:</strong> I may have figured out that problem: it seems to depend on the Build Active Architecture Only build setting, which in turn suggests that it's a 64-bit issue. Which makes sense, since Float would not be a match for CGFloat on a 64-bit device. That means that the impedance mismatch problem is even worse than I thought. </p>
  
  <h3>Conclusion</h3>
  
  <p>I'm looking for practical words of wisdom on this topic. I'm thinking someone may have devised some CGRect and CGPoint extension that will make life a lot easier. (Or possibly someone has written a boatload of additional arithmetic operator function overloads, such that combining CGFloat with Int or Double "just works" — if that's possible.)  </p>