What does "rect1 += rect2" mean in Swift? - 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.

Related

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.

Writing multiple nested for...in loops in Swift

Is there a tidier or better way to write the below nested for...in loops in Swift please? Or is using for...in even the correct way to populate my cards?
for cardNumber in 1...3 {
for cardSymbolIdentifier in 1...3 {
for cardColorIdentifier in 1...3 {
for cardShadingIdentifier in 1...3 {
let card = Card(cardNumber: cardNumber, cardSymbolIdentifier: cardSymbolIdentifier, cardColorIdentifier: cardColorIdentifier, cardShadingIdentifier: cardShadingIdentifier)
deckOfCards.append(card)
}
}
}
}
It definitely does the job, but I can't find anything in the documentation about writing multiple nested loops.
Many thanks in advance,
Andy
There is absolutely nothing wrong with your for loops. They are excellent, well-written Swift. The only problem with your code is that it forces deckOfCards to be mutable (var), which may be undesirable. If it is, you could use a map, but I don't consider this particularly better Swift, just slightly different.
let d = (1...3).flatMap { number in
(1...3).flatMap { symbol in
(1...3).flatMap { color in
(1...3).map { shading in
Card.init(cardNumber: number,
cardSymbolIdentifier: symbol,
cardColorIdentifier: color,
cardShadingIdentifier: shading
)}}}}
I would probably write it this second way, but only for stylistic reasons. Your for loops are absolutely fine.
Note #user28434's comment below. My original version of this had a major bug (it returned the wrong type). I've been writing Swift since the day it was released. I teach Swift. I teach functional programming in Swift. And I screwed it up when writing it on the fly. I would never have made that mistake with a simple for loop. There's a major lesson in there.
If you Do that in a single loop, then it become arithmetically complex
for i in 0..<81 {
deckOfCards.append(
Card(cardNumber: i / 27, cardSymbolIdentifier: i/9 % 3,
cardColorIdentifier: i/3 % 3, cardShadingIdentifier: i % 3)
)
}
or
let deckOfCards = (0..<81).map {
Card(cardNumber: $0 / 27, cardSymbolIdentifier: $0/9 % 3,
cardColorIdentifier: $0/3 % 3, cardShadingIdentifier: $0 % 3)
}
In both example - indexing start with 0, so your class init function should shift indexing little
or
add +1 in every parameter before/after passing
Your code has no optimisation issues at all according to the need but you can make it a little more elegant or swifty (:p)
let values = [1,2,3]
values.forEach { (cardNumber) in
values.forEach { (cardSymbolIdentifier) in
values.forEach { (cardColorIdentifier) in
values.forEach { (cardShadingIdentifier) in
let card = Card(cardNumber: cardNumber, cardSymbolIdentifier: cardSymbolIdentifier, cardColorIdentifier: cardColorIdentifier, cardShadingIdentifier: cardShadingIdentifier)
deckOfCards.append(card)
}
}
}
}

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.

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

Issue with Binary Operator '-'

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. :)