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