How to complete the IF statement with a formula in Xcode? - xcode8

I am very new to Xcode and Swift. I have been trying to complete the if statement with a formula below. I noticed that I cannot copy and paste the Swift if statement into Xcode 8 directly.
It shows a yellow triangle: result of operator '-' is unused.
Please help to complete the code so that the answer will be shown in the 'answer' label. Thank you.
*More information:
This is a simple app I am building. The user will enter 2 numbers (k1 and k2) and click the button (b1) to generate an answer ('answer' label).
The button (b1) will convert the texts (k1 and k2) to integers (p1 and p2) respectively. Then it will decide: if p1 is greater than p2 (say 5 is greater than 2), it will execute p1 - p2 and show the answer (3) in the 'answer' label. Else, it will execute p2 - p1.*
#IBOutlet var k1: UITextField!
#IBOutlet var k2: UITextField!
#IBOutlet var answer: UILabel!
#IBAction func b1(_ sender: AnyObject) {
let p1: Int? = Int(k1.text!)
let p2: Int? = Int(k2.text!)
if p1! > p2! {
p1! - p2! //shows yellow triangle: result of operator '-' is unused.
}
else{
p2! - p1! //shows yellow triangle: result of operator '-' is unused.
}
}
//to show the result of p1 - p2 or p2 - p1 in 'answer'.
}

Related

Calculating the 2D turn movement required given an incoming and outgoing direction

Consider a 2D square tiled grid (chess board like) which contains conveyor belt like structures that can curve and move game pieces around.
I need to calculate the turn movement (TURN_LEFT, TURN_RIGHT or STAY), depending on
the direction from which a piece moves onto the field
the direction from which the underlying belt exits the field
Example:
1 2
1 |>X>|>v |
2 | | v |
The belt makes a RIGHT turn. As such, the result of calcTurn(LEFT, DOWN) should be TURN_RIGHT. Meaning the X game piece will be rotated 90° right when it moves over the curve at (1,2).
I already implemented a function but it only works on some of my test cases.
enum class Direction {
NONE,
UP,
RIGHT,
DOWN,
LEFT;
fun isOpposite(other: Direction) = this == UP && other == DOWN
|| this == DOWN && other == UP
|| this == LEFT && other == RIGHT
|| this == RIGHT && other == LEFT
}
data class Vec2(val x: Float, val y: Float)
fun Direction.toVec2() = when (this) {
Direction.NONE -> Vec2(0f, 0f)
Direction.UP -> Vec2(0f, 1f)
Direction.RIGHT -> Vec2(1f, 0f)
Direction.DOWN -> Vec2(0f, -1f)
Direction.LEFT -> Vec2(-1f, 0f)
}
fun getTurnMovement(incomingDirection: Direction, outgoingDirection: Direction): Movement {
if (incomingDirection.isOpposite(outgoingDirection) || incomingDirection == outgoingDirection) {
return Movement.STAY
}
val incVec = incomingDirection.toVec2()
val outVec = outgoingDirection.toVec2()
val angle = atan2(
incVec.x * outVec.x - incVec.y * outVec.y,
incVec.x * outVec.x + incVec.y * outVec.y
)
return when {
angle < 0 -> Movement.TURN_RIGHT
angle > 0 -> Movement.TURN_LEFT
else -> Movement.STAY
}
}
I can't quite figure out what's going wrong here, especially not because some test cases work (like DOWN+LEFT=TURN_LEFT) but others don't (like DOWN+RIGHT=STAY instead of TURN_LEFT)
You're trying to calculate the angle between two two-dimensional vectors, but are doing so incorrectly.
Mathematically, given two vectors (x1,y1) and (x2,y2), the angle between them is the angle of the second to the x-axis minus the angle of the first to the x-axis. In equation form: arctan(y2/x2) - arctan(y1/x1).
Translating that to Kotlin, you should instead use:
val angle = atan2(outVec.y, outVec.x) - atan2(incVec.y, incVec.x)
I'd note that you could achieve also your overall goal by just delineating the cases in a when statement as you only have a small number of possible directions, but perhaps you want a more general solution.
It's not answering your question of why your code isn't working, but here's another general approach you could use for wrapping ordered data like this:
enum class Direction {
UP, RIGHT, DOWN, LEFT;
companion object {
// storing thing means you only need to generate the array once
private val directions = values()
private fun getPositionWrapped(pos: Int) = directions[(pos).mod(directions.size)]
}
// using getters here as a general example
val toLeft get() = getPositionWrapped(ordinal - 1)
val toRight get() = getPositionWrapped(ordinal + 1)
val opposite get() = getPositionWrapped(ordinal + 2)
}
It's taking advantage of the fact enums are ordered, with an ordinal property to pull out the position of a particular constant. It also uses the (x).mod(y) trick where if x is negative, putting it in parentheses makes it wrap around
x| 6 5 4 3 2 1 0 -1 -2 -3 -4 -5
mod 4| 2 1 0 3 2 1 0 3 2 1 0 3
which makes it easy to grab the next or previous (or however far you want to jump) index, acting like a circular array.
Since you have a NONE value in your example (which obviously doesn't fit into this pattern) I'd probably represent that with a null Direction? instead, since it's more of a lack of a value than an actual type of direction. Depends what you're doing of course!

Swift ReverseGeocode CLPlacemark areasOfInterest almost always nil. Should I be using something else?

I am using CLGeocoder and reverseGeocodeLocation to get my CLPlacemark. How come the name mostly comes back as an address and areasOfInterest come back as nil? For example... the areasOfInterest appear for really major things like apple HQ and airports, things of that sort but stores such as Walmart, Publix blah blah are nil. Should I be searching another way? Am I expecting more information than is available with this method? I mean, Apple has these points of interest on their maps, is there another way I should be trying to get this information?
Here are a few location lat longs that I've tried in my area that aren't bringing back the store names. These came from google and when put into apple maps, it beings you right on top of the correct location but it doesn't associate either... This makes me think I should be doing something different to being back the name of the store. Other info like a description or category would be nice as well.
Note: I am only wanting the information, I am not trying to place it on a map or anything.
Walmart: 35.0944° N, 85.3319° W
Aquarium: 35.0558° N, 85.3111° W
Publix: 35.0651° N, 85.3083° W
Small bit of my code. All works just wanted to give you an adea of what im bringing back and how.
CLGeocoder().reverseGeocodeLocation(manager.location!, completionHandler: {(placemarks, error)->Void in
if placemarks != nil
{
if error == nil && placemarks!.count >= 1 {
let thePlacemarks = placemarks![0] as CLPlacemark
print(placemarks)
print(thePlacemarks.areasOfInterest?.description)
print(thePlacemarks.administrativeArea?.description)
print(thePlacemarks.areasOfInterest?.description)
print(thePlacemarks.country?.description)
print(thePlacemarks.inlandWater?.description)
print(thePlacemarks.isoCountryCode?.description)
print(thePlacemarks.locality?.description)
print(thePlacemarks.location?.description)
print(thePlacemarks.name?.description)
print(thePlacemarks.ocean?.description)
print(thePlacemarks.subAdministrativeArea?.description)
print()
}
}
})
Any help would be great!
Thanks!
So... Not necessarily ideal but by using mapkit I was able to do a MKLocalSearch to get what I wanted. This only works because I have an array in my code of the specific locations I am interested in. See me code below.
Import Mapkit
let listArr = ["Walmart", "Publix","Game Stop"]
Then somewhere in your ViewController
func searchArr() //This function will iterate through the array and see if any of the locations are within 30 meters
{
for element in listsArr
{
let request = MKLocalSearchRequest()
request.naturalLanguageQuery = "\(element)"
request.region = MKCoordinateRegionMakeWithDistance(currentCoordinates, 3200, 3200)
MKLocalSearch(request: request).start { (response, error) in
guard error == nil else {print()return}
guard let response = response else {return}
guard response.mapItems.count > 0 else {return}
print(response.mapItems[0])
let coord1 = currentCoordinates
let coord2 = response.mapItems[0].placemark.coordinate
let distance = self.calculateDistance(fromlat: currentCoordinates.latitude, fromlon: currentCoordinates.longitude, tolat: response.mapItems[0].placemark.coordinate.latitude, tolon: response.mapItems[0].placemark.coordinate.longitude)
if distance > 30
{
print("the distance between the two points is: \(distance) meters")
}
}
}
Here is a little function I found to get the distance between two coordinates.
func calculateDistance(fromlat : Double, fromlon : Double, tolat : Double, tolon : Double) -> Double {
let DEG_TO_RAD = 0.017453292519943295769236907684886
let EARTH_RADIUS_IN_METERS = 6372797.560856
let latitudeArc : Double = (fromlat - tolat) * DEG_TO_RAD
let longitudeArc : Double = (fromlon - tolon) * DEG_TO_RAD
var latitudeH : Double = sin(latitudeArc * 0.5)
latitudeH *= latitudeH
var lontitudeH : Double = sin(longitudeArc * 0.5)
lontitudeH *= lontitudeH
let tmp : Double = cos(fromlat*DEG_TO_RAD) * cos(tolat*DEG_TO_RAD)
return EARTH_RADIUS_IN_METERS * 2.0 * asin(sqrt(latitudeH + tmp*lontitudeH))
}

Variable contains nil value in Swift 2

I declared a variable destinationID on top of my class. The first print shows the right content of the variable while the second one has a nil value.
Does anyone know what the problem is?
import UIKit
class ViewController: UIViewController,UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate{
var destinationUserID = String()
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath){
//Opzoeken wat het bijhorende ID is
let query = PFQuery(className:"_User")
query.whereKey("username", equalTo:selectedUsername)
query.findObjectsInBackgroundWithBlock {
(objects: [PFObject]?, error: NSError?) -> Void in
// Do something with the found object
for object in objects! {
self.destinationUserID = object.objectId!
print(self.destinationUserID)
}
print("try 1 : " + self.destinationUserID)
}
print("try 2 : " + self.destinationUserID)
}
}
The print("try 1... statement is inside the block. The print("try 2... is outside the block. The block is executed in the background which means that the search might not have completed when you get to print("try 2....

Count colors in image: `NSCountedSet` and `colorAtX` are very slow

I'm making an OS X app which creates a color scheme from the main colors of an image.
As a first step, I'm using NSCountedSet and colorAtX to get all the colors from an image and count their occurrences:
func sampleImage(#width: Int, height: Int, imageRep: NSBitmapImageRep) -> (NSCountedSet, NSCountedSet) {
// Store all colors from image
var colors = NSCountedSet(capacity: width * height)
// Store the colors from left edge of the image
var leftEdgeColors = NSCountedSet(capacity: height)
// Loop over the image pixels
var x = 0
var y = 0
while x < width {
while y < height {
// Instruments shows that `colorAtX` is very slow
// and using `NSCountedSet` is also very slow
if let color = imageRep.colorAtX(x, y: y) {
if x == 0 {
leftEdgeColors.addObject(color)
}
colors.addObject(color)
}
y++
}
// Reset y every x loop
y = 0
// We sample a vertical line every x pixels
x += 1
}
return (colors, leftEdgeColors)
}
My problem is that this is very slow. In Instruments, I see there's two big bottlenecks: with NSCountedSet and with colorAtX.
So first I thought maybe replace NSCountedSet by a pure Swift equivalent, but the new implementation was unsurprisingly much slower than NSCountedSet.
For colorAtX, there's this interesting SO answer but I haven't been able to translate it to Swift (and I can't use a bridging header to Objective-C for this project).
My problem when trying to translate this is I don't understand the unsigned char and char parts in the answer.
What should I try to scan the colors faster than with colorAtX?
Continue working on adapting the Objective-C answer because it's a good answer? Despite being stuck for now, maybe I can achieve this later.
Use another Foundation/Cocoa method that I don't know of?
Anything else that I could try to improve my code?
TL;DR
colorAtX is slow, and I don't understand how to adapt this Objective-C answer to Swift because of unsigned char.
The fastest alternative to colorAtX() would be iterating over the raw bytes of the image using let bitmapBytes = imageRep.bitmapData and composing the colour yourself from that information, which should be really simple if it's just RGBA data. Instead of your for x/y loop, do something like this...
let bitmapBytes = imageRep.bitmapData
var colors = Dictionary<UInt32, Int>()
var index = 0
for _ in 0..<(width * height) {
let r = UInt32(bitmapBytes[index++])
let g = UInt32(bitmapBytes[index++])
let b = UInt32(bitmapBytes[index++])
let a = UInt32(bitmapBytes[index++])
let finalColor = (r << 24) + (g << 16) + (b << 8) + a
if colors[finalColor] == nil {
colors[finalColor] = 1
} else {
colors[finalColor]!++
}
}
You will have to check the order of the RGBA values though, I just guessed!
The quickest way to maintain a count might just be a [Int, Int] dictionary of pixel values to counts, doing something like colors[color]++. Later on if you need to you can convert that to a NSColor using NSColor(calibratedRed red: CGFloat, green green: CGFloat, blue blue: CGFloat, alpha alpha: CGFloat)

Operations based on user input Swift

long question, so bear with me...
I am attempting to create a bitcoin ticker and converter written in Swift. I am using the code below (bits not related to conversion are removed - let me know if I left out anything important)
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var USD: UITextField! //Amount of USD. Originally equals 1 bitcoin, can be changed by user.
#IBOutlet weak var BTC: UILabel! //Amount of bitcoins the entered amount of USD is worth. Originally 1.
func handler(response: NSURLResponse!, data : NSData!, error : NSError!) { //To fetch Bitcoin Price. This is functional.
if ((error) != nil) {
self.USD.text = "No Internet" // in case of error
} else {
var price = NSString(data:data, encoding:NSUTF8StringEncoding)
self.USD.text = price //set USD to be equal to price of 1 Bitcoin
}
override func viewDidLoad() {
//Sets up view
self.update() //Fetches Bitcoin Price. This works.
self.convert() //Begins convert method
var timer = NSTimer.scheduledTimerWithTimeInterval(120, target: self, selector: Selector("update"), userInfo: nil, repeats: true)
}
func convert() {
var url = NSURL(string:"https://api.bitcoinaverage.com/ticker/USD/last")
var request = NSURLRequest(URL: url)
NSURLConnection.sendAsynchronousRequest(request, queue: NSOperationQueue(), completionHandler:handler)
var data = NSData(contentsOfURL:url);
while true {
if USD.text != data {
BTC.text = USD.text / NSString(data:data, encoding:NSUTF8StringEncoding)// Attempts to determine amount of bitcoin the USD amount is worth. ERROR HERE!
}
}
On the line with the comment "ERROR HERE", I get the error
/Users/[My User]/Documents/dev/Newest Stuff/CryptoCoinTicker/CryptoCoinTicker/ViewController.swift:95:32: 'String' is not convertible to 'UInt8'
In case the code doesn't tell the story, I want BTC.text to change to be equal in value to the amount entered by the user in USD.text (so if a bitcoin is worth $500, and the user entered 250.00, BTC.text would say 0.5.
What do I need to do? Apologies for a (probably) basic question, I am but a newbie. Let me know if you ned more info.
Thanks in advance!
When you get that error, it usually means that you are trying to assign a wrong type to a variable or that you are using the wrong types for function parameters.
In your case, you are trying to divide two Strings. The compiler doesn't know what to do, since the division of Strings is not defined. You can only divide Int, Float and Double and you can't even mix them!
So for that line you can substitute this:
let value = NSString(string: USD.text).doubleValue / NSString(data:data, encoding:NSUTF8StringEncoding).doubleValue
BTC.text = "\(value)"
This first "converts" the USD.text to NSString and then converts both NSStrings to Doubles, which you can then divide.
It then creates a String from that value, which can be assigned to the BTC.text property.