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

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

Related

swift opaque type keyword some doesn't seem to make a difference

In Apple's swift 5.1 language guide example the keyword "some" doesn't seem to make a difference.
func makeTrapezoid() -> some Shape {
let top = Triangle(size: 2)
let middle = Square(size: 2)
let bottom = FlippedShape(shape: top)
let trapezoid = JoinedShape(
top: top,
bottom: JoinedShape(top: middle, bottom: bottom)
)
return trapezoid
}
let trapezoid = makeTrapezoid()
//print(trapezoid.draw())
let sh:Shape = trapezoid
print("type:\(type(of:sh))")
This prints type:JoinedShape<Triangle, JoinedShape<Square, FlippedShape<Triangle>>> with or without the "some" keyword.
I thought the point of "some" was to hide the type???
You said:
I thought the point of some was to hide the type???
The point is that the caller doesn’t need to be exposed to how we created the trapezoid (i.e., that makeTrapezoid returns a JoinedShape<Triangle, JoinedShape<Square, FlippedShape<Triangle>>> is irrelevant). The caller really shouldn’t care how it was implemented. All it needs to be aware of is that the returned object conforms to Shape.
Just like when you return a standard protocol-as-type value, this doesn’t change the object that is actually returned at run-time. In this case, it is still that messy JoinedShape type. All it means is that at compile-time, we’ve told the caller to not worry about the implementation details and to only rely upon the fact that it will conform to Shape.
You ask:
What is the difference then between
func someFunc() -> some SomeProtocol
and
func someFunc() -> SomeProtocol
The main difference is that if the protocol has Self or associated type requirements, you’re simply not permitted to do the latter. Opaque return types now allows us to easily do what used to require cumbersome work-arounds.
According to “Limitations of Returning a Protocol Type” in What’s New in Swift, this new opaque return type allows the compiler to do additional optimizations and preserves type identity, too.
FWIW, if you’re interested in greater detail about the rationale behind the opaque return types, it’s outlined in greater detail in Swift Evolution SE-0244. And, for the sake of future readers, the high level summary is available in The Swift Language: Opaque Types.

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.

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

Initialize 4 CGFloats at once

I am trying to use the getRed(green:blue:alpha:) function on UIColor in Swift. For this, I need 4 CGFloat variables (r,g,b,a). Currently, for this, I need to type this code:
var r: CGFloat = 0
var g: CGFloat = 0
var b: CGFloat = 0
var a: CGFloat = 0
Is there a simpler way to write this, possibly more concise?
Yes you can use a tuple to declare and initialize them:
var (a: CGFloat, r: CGFloat, g: CGFloat, b: CGFloat) = (0, 0, 0, 0)
Personally, I'm not sure there's a way of declaring those that's any clearer than your original, or that's involves typing that much less. The currently accepted answer is only nine characters shorter, if I've counted them right...
If it's just typing you're worried about, you could use Xcode's built in code snippet library. It allows you to add custom snippets, and assign autocomplete shortcuts.
For this case I'd add your code as a completion snippet, by selecting it in the editor and dragging it to the Code Snippet library (bottom right of the sidebar; go straight to it with View->Utilities->Show Code Snippet Library from Xcode's main menu.) Then I'd probably assign a completion shortcut like "rgba" or something.
Now you're down to typing just a few characters, and you've not used any software outside Xcode to achieve it. Trigger code completion, type "rgba", hit return, and you're done.