Issue with Binary Operator '-' - swift

I am receiving an odd error stating Binary operator '-' cannot be applied to two CGPoint operands in my newest build of an app I am developing. It is very perplexing as I know it can be applied as I have run the same line of code in a previous build of this app. I have tried to resolve the error by rewriting the project and get the same issue. The line of code that is causing a problem is as such:
func updateRKnobWithPosition(position:CGPoint) {
var positionToCenter = position - baseCenter
var direction: CGPoint
if positionToCenter == CGPointZero {
direction = CGPointZero
} else {
direction = positionTOCenter.normalized()
}
...
delegate?.analogRControlPositionChanged(self, position: relativePosition)
}
where relativePosition is a CGPoint in the class.
Can anyone tell me where I am going wrong here. If it's not my code, does it have something to do with Xcode?
Thanks

Maybe you weren't using it correctly earlier on.
But if you are adamant that it was indeed working correctly before, then maybe someone or some library had an operator function working for CGPoint
You can create an operator function as follows
func - (first: CGPoint, second: CGPoint) -> CGPoint {
return CGPointMake(first.x - second.x, first.y - second.y)
}

Your problem can be quickly explained by looking at the documentation for CGPoint. It is defined as:
struct CGPoint { var x: CGFloat var y: CGFloat init() init(x x: CGFloat, y y: CGFloat) }
So, you are asking it to subtract one structure from another and it has no idea how to do it. :)
The issue is that most of what you do in iOS and the Mac libraries is object oriented but the graphics library is notably mostly C code rather than objects with overloaded operators. :)

Related

Rules for type check in Swift builds?

I’ve wanted to speed up my build times, so one of the steps was using Other Swift Flags and
-Xfrontend -warn-long-function-bodies=100
-Xfrontend -warn-long-expression-type-checking=100
But I’m not really sure how type checks work. For example, here’s a simple func for creating random CGFloat. Type check for it is over 200ms
static func randomColorValue() -> CGFloat {
return CGFloat(Int.random(in: 0...255))/255.0
}
But on changing to something like this
static func randomColorValue() -> CGFloat {
let rnd = Int.random(in: 0...255)
let frnd = CGFloat(rnd)
let result = frnd/255.0
return result
}
or like this
static func randomColorValue() -> CGFloat {
let rnd : Int = Int.random(in: 0...255)
let frnd : CGFloat = CGFloat(rnd)
let result : CGFloat = frnd/255.0
return result
}
type check is still over 200ms.
What's wrong here? Is there any set of rules and best practices for dealing with build times?
My Mac is a bit older (2012), maybe that's the problem?
EDIT:
After turning off -warn-long-function-bodies problematic line appeared, and that is
CGFloat(rnd)
It appears that casting Int to Float, Double or CGFloat shows slowing down of 150ms.
Note that warn-long-function-bodies is unsupported (it was added as an experimental flag). If you remove it, I find that the expression time is often reported as twice as fast, which makes be believe that using the two measurements together is causing interference. Measurement takes time, too. warn-long-expression is a supported option.

Referencing operator function '*' on 'SIMD' requires that '_.Scalar' conform to 'FloatingPoint'

I've just started teaching myself to write in Swift. I'm currently trying to rotate an image when I press a button (just practicing with really simple stuff) and Xcode has thrown two errors at me:
Referencing operator function '*' on 'SIMD' requires that '_.Scalar' conform to 'FloatingPoint'
String interpolation can only appear inside a string literal
I've searched around the web a bit for info on SIMD but I couldn't understand any of it! Can someone break it down for a clueless newbie? This is my code so far. Some of it is from online tutorials, some from Xcode's suggestions, some I just guessed:
#IBAction func spinButton(_ sender: Any) {
if self.rotationDegree != 360 {
self.rotationDegree += 1
//to increase the rotation by 1 degree
} else {
self.rotationDegree -= 360
//to put the rotation back to 0 degrees
}
UIView.animate(withDuration: 1.0, animations: {
self.vortex2.transform = CGAffineTransform(rotationAngle: \(rotationDegree) * .pi / \(rotationDegree))
//this is where both error messages appear
})
}
The string interpolation error results from your use of \(). Just delete the backslashes.
Data types conforming to the SIMD protocol allow the compiler to generate faster code using single-instruction multiple-data instructions (such as SSE and AVX on Intel processors). Assuming rotationDegree is declared with a usual floating-point type, maybe the error results from the incorrect use of the backslash.

Does the Swift compiler get rid of superfluous type casts when using a typealias?

In my application I can't decide what floating point format will be the best for performance. Its not so much the matter of bits that I am worried about rather how it interfaces with various functions I am using since I am using math libraries and graphics libraries.
As a result I have built everything using typealias EngineDecimal = CGFloat so that at the end I can experiment with changing that to other formats such as GLFloat, Float32 etc.
My question is what does the compiler do if I write a function like this:
func foo(in: EngineDecimal)-> EngineDecimal
{
return Decimal(mathFunction(CGFloat(in)));
}
//foo2 is a library defined function that I have no control over but I'm typing a sample one for this example
func foo2(in: CGFloat) -> CGFloat
{
return sin(in) + cos(in)
}
Will the compiler notice if Decimal is the same type as CGFloat and thus get rid of the casting statements? So in essence would this code run faster if typealias EngineDecimal = CGFloat vs if typealias EngineDecimal = GLFloat ?
A typealias doesn't create a new type, it just allows a new name to be used in place of an existing type. So there is no casting being done and no optimisation needs to occur.

What does "rect1 += rect2" mean in Swift?

Is this the same as UnionRects(rect1, rect2)? I'm trying to translate some Swift code to Objective C. I can't find this in the references or Googling.
After looking at this again, I think I see my problem. It's an array of rects, not a rect. Apparently, the "+=" is for the array.
This is straight out of Apple's sample code for Photos:
fileprivate func differencesBetweenRects(_ old: CGRect, _ new: CGRect) -> (added: [CGRect], removed: [CGRect]) {
if old.intersects(new) {
var added = [CGRect]()
if new.maxY > old.maxY {
added += [CGRect(x: new.origin.x, y: old.maxY, width: new.width, height: new.maxY - old.maxY)]
}
...
}
The edited question makes it clear that you're asking about using += on two Arrays. This appends the contents of the right array to the left array, as you'd imagine. It's described in the docs under "Accessing and Modifying an Array".
Below is my original answer, preserved for anyone who stumbles onto this question looking for += between CGRects.
If rect1 and rect2 are CGRect rectangles, then rect1 += rect2 is invalid in standard Swift.
If you see this in working code, it means that they overloaded the += compound assignment operator (see documentation) to accept CGRects and perform their own custom function. The only way to know what that does is to find it in the code.
Here's what the code looks like to overload += with a function that unions the CGRects:
func += (left: inout CGRect, right: CGRect) {
left = left.union(right)
}
If you search your codebase for "inout CGRect" and various permutations thereof, you'll probably turn up the code responsible, which will help a lot in figuring out what it does.

Swift 3 mutating functions missing ('...inPlace' methods)

In Swift 2.3, we can write something like this:
var rect = CGRect(...)
rect.offsetInPlace(dx: 15, dy: 0)
to move a rect 15pt to the right.
However in Swift 3, it seems like this function does no longer exist.
When inspecting the CGRect interface we can only see the non mutating variant offsetBy(dx:, dy:). This is also true in all the places we've usually used mutating functions (named ...inPlace). I have already searched the Swift evolution repo on GitHub, but couldn't find any notes about this.
Have the mutating variants been removed? Is the remaining function automatically mutating depending on whether or not the return value is used? IMHO, it would be a shame, if they have actually been removed, because they used to be very convenient when doing code based layout, etc.
You can make one for compatibility.
extension CGRect {
mutating func offsetInPlace(dx: CGFloat, dy: CGFloat) {
self = self.offsetBy(dx: dx, dy: dy)
}
}
It seems there is no offsetInPlace anymore. Please see the screen here is all available functions in Instance Methods