Converting NSPoint to CGPoint using NSPointToCGPoint - swift

How difficult can it be to access x and y coordinates from NSPoint...Can't believe it.
I get an NSPoint from following call:
var mouseLoc = [NSEvent .mouseLocation]
I need to access x and y coordinates. NSPoint does not offer a getter like CGPoint. I learned: I have to cast into CGPoint but nothing that I found seems to work in latest Swift anymore:
var p = (CGPoint)mouseLoc // error: Cannot convert value of type '[NSPoint]' (aka 'Array<CGPoint>') to expected argument type 'NSPoint' (aka 'CGPoint')
var p = NSPointToCGPoint(mouseLoc) // error: Cannot convert value of type '[NSPoint]' (aka 'Array<CGPoint>') to expected argument type 'NSPoint' (aka 'CGPoint')
I am sure it's a complete beginner thing but I just don't get it.

Swift uses a different syntax for calling instance or class methods than Objective-C.
// Objective-C
NSPoint mouseLoc = [NSEvent mouseLocation]
translates to
// Swift
let mouseLoc = NSEvent.mouseLocation
whereas your Swift code creates an array containing a single NSPoint.
Also NSPoint is a type alias for CGPoint:
typealias NSPoint = CGPoint
so you can simply use the same accessors:
// Swift
let mouseLoc = NSEvent.mouseLocation
let xCoord = mouseLoc.x
let yCoord = mouseLoc.y

Here seems what mouseLoc is an array of NSEvent. Iterate through it and convert each point individually or use only one (first or last element).
Iterate like this:
let allPoints = mouseLoc.forEach { NSPointToCGPoint($0) }
But in this case you also will get an array, but now of CGPoint. You probably want to use only one of it, first or last.
But also maybe you have an array with only one element - use .first.

Related

Is there a placeholder for doubles in Swift?

I want to be able to call various doubles from a collection but I'm having trouble setting it up.
" " can be used on the right side of a value/constant declaration as a placeholder for string values, is there a way to do the same for doubles? I Googled but wasn't able to find anything.
For original question
A "nan" "not a number" has a specific meaning of an undefined or unrepresentable number. There are quiet and signaling versions. You can get a nan by multiplying Double.infinity by something.
let alarmTriggeringNotANumber: Double = .signalingNan
let quietNotANumber: Double = .nan
let hero: Double = .zero
let loveLife: Double = -.infinity
Technically, "" isn't a placeholder, but an empty collection. Nil would be a way to indicate the absence of a value.
For the separate question in the comment
I want to get a bunch of latitude and longitude coordinates
and call them from a collection using one name. For example var latitude = x, where x would represent whichever object I call to it.
You can create a Dictionary/Set where the element is of type Coordinates.
struct Coordinates {
let lat: Double
let long: Double
}
let batCavesByCountryID: [UUID : [Coordinates]]
You can create a type alias that allows you to reference a tuple with a specific signature.
You can also create a typealias for Lat/Long.
Typealiases are useful to reduce code maintenance. For example, you might change IDs from UUIDs to Strings. Using a typealias can be more expressive and let you change a whole app with one line of code. However, going overboard will just make this obscure. You can add extensions to type aliases, but tuples are currently not extendable.
typealias Coordinates = (lat: Latitude, long: Longitude)
typealias Latitude = Double
typealias Longitude = Double

I'm confused about value type () in Swift. What is it, and how am I meant to use it?

I'm trying to convert height in feet with a decimal to height in feet and inches.
I'm trying to use the .round(.down) method to get the feet, and multiply the decimal by 12 for the inches. I'm getting all kinds of errors, like so:
var heightInFeet: Float = 5.45
let feetRounded = heightInFeet.round(.down) // feetRounded is "type ()." What is that?
percentToNextFoot = heightInFeet - feetRounded // Error: Binary operator '-' cannot be applied to operands of type 'Float' and '()'
I tried the following and got another error:
percentToNextFoot = heightInFeet - Float(feetRounded) // Cannot invoke initializer for type 'Float' with an argument list of type '(())'
I finally got it working by avoiding the .round() method, but I'm still really confused by the value type (). Can anyone explain what's going on here?:
var heightInFeet: Float = 5.45
var feet = Int(heightInFeet) // 5
var percentToNextFoot = heightInFeet - Float(feet) // 0.45
let heightInFeetAndInches = "\(feet)ft \(Int(percentToNextFoot * 12))in" // 5ft 5in
() is shorthand for void. It means "no value is possible here".
In this example, it means that the .round() method does not return anything - it is a mutating function called on its receiver. So assigning its void return to a var causes that var's type to be inferred to be void. Void vars can be useful, sometimes, rarely*, but not in this case.
Methods on value types often come in pairs: a verb like round, and a passive verb e.g. rounded. The first operates directly on, and modifies, its target; the second returns a modified version of its target. For another example, see sort() and sorted() on collections, or append(_) and appending(_) on strings, etc.
(* note: filter is an annoying exception; it means "filtered", and there is no handy "filter in place".)
To get the effect you were going for in the first example, rounded() is what you want.
--
(* To answer the tangential question in your title: how would one actually use a void variable? Well, here's a way I use them sometimes:
In an object with some setup that I would like to happen sometime after init, but guaranteed at most once per instance, I used to use Objective-C's dispatch_once. That's not available in Swift, so now I'll make a lazy void member like so:
class Foo {
lazy var setup: () = {
// do some complicated stuff I couldn't do in `init` for some reason
// this will only run once
}()
func doSomethingUseful() {
_ = setup // runs the setup initializer just the first time we get here
// do useful things that depend on setup having happened
}
}
I'll leave it to the comments to judge whether we're "meant to" use such a technique. :)
Welcome to stack overflow!
Double has two rounding methods:
Double.round(), which rounds a Double value by mutating it in-place. This is one you called. It doesn't return anything, which strictly speaking means it returns Void, a.k.a. (), the empty tuple.
Double.rounded(), which rounds a Double value by returning a new Double. This is the one you probably intended to call.
By calling the first, and trying to assign the value to a variable, you end up with a variable of type Void, whose value is ().
This is a common Swift convention: "object.foo" edits it in place. "object.fooed" returns a mutated copy.
That said, in your case, I would recommend doing this using the existing Measurement API:
import Foundation
extension Measurement where UnitType == UnitLength {
func toFeetAndInches() -> (feet: Measurement<UnitLength>, inches: Measurement<UnitLength>) {
let numberOfWholeFeet = self.converted(to: .feet).value.rounded(.towardZero)
return (
feet: Measurement(value: numberOfWholeFeet, unit: UnitLength.feet),
inches: Measurement(value: self.value - numberOfWholeFeet, unit: UnitLength.feet).converted(to: .inches)
)
}
}
let heightInFeet = Measurement(value: 5.5, unit: UnitLength.feet)
let (feet, inches) = heightInFeet.toFeetAndInches()
let mf = MeasurementFormatter()
mf.unitOptions = .providedUnit // force the use of feet/inches, rather than the unit appropriate for the user's locale.
mf.unitStyle = .medium
print(mf.string(for: feet)!, mf.string(for: inches)!) // => "5 ft. 6 in."
If you look at the reference for the round function of Float type, you will see that it returns nothing. It just mutate the float you called this method on.
You can do
var feetRounded = heightInFeet
feetRounded.round(.down)
Please take a look at the documentation. The method
mutating func round(_ rule: FloatingPointRoundingRule)
has no return value (aka Void aka ())
If you need a result you have to use rounded(_:) which has a return value
func rounded(_ rule: FloatingPointRoundingRule) -> Float
round changes the value in place; you use it like this:
var heightInFeet: Float = 5.45
heightInFeet.round(.down)
You notice that no value is returned; there is no = in the second line. We do not need to set anything to the result of the round call, because it has no result.
If, as in your code, you accidentally do capture the "result", it is expressed as type (). So () is the "result" type of a method call that has no result.
When we accidentally write this:
var heightInFeet: Float = 5.45
let x = heightInFeet.round(.down)
we get this error: "Constant 'x' inferred to have type '()', which may be unexpected." That is just a fancy way of saying, "You've taken a method call that has no result and captured its 'result'. You probably didn't mean to do that!" And indeed, you didn't.

What is the syntax for casting a reference to a variable in Swift?

Being new to Swift (and having some issues with Swift's pointer handling) I'm unable to properly parse the errors Xcode gives me. Any tips on getting a reference into a variable?
RGBA is a just struct of 4 UInt8s
var data: UnsafeMutablePointer<RGBA> = UnsafeMutablePointer<RGBA>(CGBitmapContextGetData(bitmapContext))
var pixel = &data[offset] // [1] this is the trouble statement
// use the pixel struct to read *and* write
[1] Errors
'myclass.RGBA' is not convertible to 'UnsafeMutablePointer'
Type 'inout myclass.RGBA' of variable is not materializable
How come I am able to access the memory using the subscript operator (data[offset].r = 0) but I have use the memory property after setting the element reference (var pixel = data[offset])? Surely there must be a Swift way for storing a reference in a local?
I can also accomplish the same through an inout parameter function, ie;
func setPixel(inout pixel: RGBA, var r: UInt8, var g: UInt8, var b: UInt8, var a: UInt8) {
pixel.r = r // I can use pixel directly without '.memory'
}
You can simply add an offset to the pointer:
let data = UnsafeMutablePointer<RGBA>(CGBitmapContextGetData(bitmapContext))
let pixel = data + offset
Then you can read/write the memory pointed to by pixel:
let red = pixel.memory.red
pixel.memory.blue = 123
After doing a bit of research (including talking to the #swift folks), it appears that Swift deliberately prohibits this kind of variable reference (reference to an array element).
One solution is to use a function to scope the reference:
func setElem(inout elem: T, var value: T {
elem = value
}
// can then be used like (which works for address-of array element):
self.setElem(&data[index], elemValue)

Swift Dictionary confusion

Say I have
var dict = parseJSON(getJSON(url)) // This results in an NSDictionary
Why is
let a = dict["list"]![1]! as NSDictionary
let b = a["temp"]!["min"]! as Float
allowed, and this:
let b = dict["list"]![1]!["temp"]!["min"]! as Float
results in an error:
Type 'String' does not conform to protocol 'NSCopying'
Please explain why this happens, note that I'm new to Swift and have no experience.
dict["list"]![1]! returns an object that is not known yet (AnyObject) and without the proper cast the compiler cannot know that the returned object is a dictionary
In your first example you properly cast the returned value to a dictionary and only then you can extract the value you expect.
To amend the answer from #giorashc: use explicit casting like
let b = (dict["list"]![1]! as NSDictionary)["temp"]!["min"]! as Float
But splitting it is better readable in those cases.

What function does "as" in the Swift syntax have?

Recently I stumbled upon a syntax I cannot find a reference to: What does as mean in the Swift syntax?
Like in:
var touch = touches.anyObject() as UITouch!
Unfortunately, it's hard to search for a word like as, so I didn't find it in the Swift Programming Language handbook by Apple. Maybe someone can guide me to the right passage?
And why does the element after as always have an ! to denote to unwrap an Optional?
Thanks!
The as keyword is used for casting an object as another type of object. For this to work, the class must be convertible to that type.
For example, this works:
let myInt: Int = 0.5 as Int // Double is convertible to Int
This, however, doesn't:
let myStr String = 0.5 as String // Double is not convertible to String
You can also perform optional casting (commonly used in if-let statements) with the ? operator:
if let myStr: String = myDict.valueForKey("theString") as? String {
// Successful cast
} else {
// Unsuccessful cast
}
In your case, touches is (I'm assuming from the anyObject() call) an NSSet. Because NSSet.anyObject() returns an AnyObject?, you have to cast the result as a UITouch to be able to use it.
In that example, if anyObject() returns nil, the app will crash, because you are forcing a cast to UITouch! (explicitly unwrapping). A safer way would be something like this:
if let touch: UITouch = touches.anyObject() as? UITouch {
// Continue
}
A constant or variable of a certain class type may actually refer to
an instance of a subclass behind the scenes. Where you believe this is
the case, you can try to downcast to the subclass type with the type
cast operator (as).
from Swift Programming Language, Type Casting
And why does the element after as always have an ! to denote to unwrap an Optional?
It is not. It is trying to downcast to "Implicitly Unwrapped Optionals", see Swift Programming Language, Types
as is an operator that cast a value to a different type.
For example:
Suppose you have an NSSet instance with some elements that have a type Car.
Then if you want to get any object:Car from this set, you should call anyObject().
var someCar = set.anyObject() //here someCar is Optional with type AnyObject (:AnyObject?), because anyObject() -> AnyObject?
Let's imagine the situation when you need to get an object from the set with type Car.
var realCar: Car = someCar as Car //here realCar is Optional with type Car (:Car?)
Than if you exactly know that someCar is not an Optional ( someCar != nil) you can do follow:
var realCarAndNotAnOptional = someCar as Car! //here realCarAndNotAnOptional just have a type == Car
More info here: Swift: Type Casting