I have some code which is supposed to find the first and final coordinate in an MGLPolyline. Currently, I am able to find the first and the middle value, but am not able to find the last value. Bellow is my code. In it, you can see how I find the first and middle coordinate.
var arrayOfCoordinates = [CLLocationCoordinate2D]()
var arrayOfPolylines = [MGLPolyline]()
for value in arrayOfPolylines {
mapView.addAnnotation(value)
//This is for the first and last snakehead and tail stuff
let lastLoc = value.coordinate.latitude
let newLoc = value.coordinate.longitude
let firstCor = value.coordinates[0].latitude
let secondCor = value.coordinates[0].longitude
...
I have tried the following to find the value:
value.coordinates[value.coordinates.count] //This does not compile as it says
Value of type 'UnsafeMutablePointer' has no member 'count'
So my question is how can I find the last value (coordinate)?
Well, your code will not work for this. With the current code, you would not be able to find the last value easily, you would have to do a mathematical process to determine the count of coordinates then check if the for loop has run through enough time to reach the last coordinate.
But an easier way is to create instead an array of CLLocation which then you can access with the following code:
let lastLoc = self.arrayOfLocationList.last //last value here
let newLoc = self.arrayOfLocationList.first
Related
I can't understand the in label of utf16Offset(in:) statement
what the use of this label.
And can anyone explain that,
Is the following statement is right or wrong?
let location = textString.range(of: hyperText)?.lowerBound.utf16Offset(in: textString)
you code is correct.it means the offset into a string's code units for this index.
for example:
var textString = "niaddjkdskjdsjdsk"
let location = textString.range(of: "dd")?.lowerBound.utf16Offset(in: textString)
as we know, the bound is (3,_),so the utf16Offset is 3.
Before Swift 4.2,we use encodedOffset,now it replace by utf16Offset, they are same behavior
#IBAction func generateBtn(sender: UIButton) {
let strt = UInt32(strtNum.text!)
let end = UInt32(endNum.text!)
let ttlNums = Int(amtNums.text!)
let x = RandomNum()
var z = 0
while z<ttlNums{
let y = x.rndNumGen(strt!, end: end!)
z += 1
var h = [String]()
h.append(String(y))
let display:String = h.joinWithSeparator(", ")
winningNums.text = display
print (display)
}
}
I don't know what is wrong with this code. I am trying to put the string display into the label and it prints out the last number from the random number generator. When i print it to the console it shows all of the random numbers.
The primary issue here is that your array is created fresh in every loop iteration, and your label is being set in every loop iteration. That means that the array will only ever contain the element made in that iteration, after which it's reset to a new array, and a new element is added. The array needs to be initialized once at the start, and have elements added to it repeatedly in the loop, then put into the label once at the end.
#IBAction func generateBtn(sender: UIButton) {
guard let startText = strtNum.text, let start = UInt32(startText),
let endText = endNum.text, let end = UInt32(endText),
let ttlText = amtNums.text, let ttlNums = UInt32(ttlText) else {
//one of these is nil, handle it gracefully here
return
}
let randomGenerator = RandomNum()
var h = [String]()
h.reserveCapacity(ttlNums)
for _ in 0..<ttlNums {
let randomNum = randomGenerator.rndNumGen(start, end: end)
h.append(String(RandomNum))
}
let display = h.joinWithSeparator(", ")
winningNums.text = display
print(display)
}
I've made a few other changes to bring this code in line with Swift best practices and conventions:
Don't force unwrap. Use an if let or guard let binding to safely handle nil values.
Give your variables meaningful names. Avoid single-letter names except in specific instances.
Don't put spaces beside a function/method name and the proceeding brackets.
Don't use a while loop to iterate over a known range. Instead, use a for in loop.
Dn't type in t3xtspk, it mks ur code look lik an angsty teenagr wrote it. Autocomplete will finish off words for you, so you barely end up typing anyway. Make it easy and readable.
I would suggest you make a few changes yourself:
Rename generateBtn. Functions/methods DO things, they're actions. They should be named with verbs, or verb phrases. Perhaps try something like displayRandomArray.
Refactor the random array generation into its own method.
Rename RandomNum. By the looks of it, it's not a number at all, it's a random number generator. Perhaps try RandomNumberGenerator
Rename h.
Add code to deal with what happens when the .text is nil, or what happens when it contains a string that isn't a UInt32 (thus causing the UInt32 initializer to fail and return nil)
Below is my code in the editor for hackerrank. Im getting a fatoal error index out of range in the language swift. I have similar code on my playground, but instead of taking a readLine im just getting a random number to fill my 2D array. This is working on my playground
//hackerrank
https://ghostbin.com/paste/jtc5k
//xcode where it works
https://ghostbin.com/paste/xqqh4
You can't use ReadLine() in playground file.
See this
So your line: if let input = readLine(),value = Int(input) doesn't execute therefore your second dimension of array doesn't get fill.
You can change your code to be look like this to see the difference:
if let input = readLine(),value = Int(input)
{
array[row].append(value)
} else {
array[row].append(Int(arc4random_uniform(2)))
}
First post here so please be gentle. Am fairly new to coding and am trying to get my head around SWIFT and its optionals. Would really appreciate some advice from the pros!
I am writing a simple app whereby textfields are entered by the user and then some multiplication occurs in app before spitting out an answer into another textfield on the press of a button: "calculateTM".
I am having some trouble with the calculation itself and perhaps it's because I am trying to do too much on one line - take the textfield entry, convert to integer, multiply with another textfield entry converted to an integer, essentially what I wrote in the title:
var someVariable: Int = textfield.text.toInt() * textfield2.text.toInt()
The problem is, Xcode is wanting my to force unwrap and add an ! to the end of both toInt(). This is fine, except of course when the user doesn't enter anything into the boxes and presses calculate, at which point the nil value causes the program to crash, e.g.:
var someVariable: Int = textfield.text.toInt() x textfield2.text.toInt()
var someVariable2: Int = textfield3.text.toInt() x textfield4.text.toInt()
where the user doesn't enter anything into textfield3 or 4
Following this simple arithmetic, the code updates the labels (which are textfields) as such:
label1.text = String(someVariable)
label2.text = String(someVariable2)
So this final conversion back to a string might also create some issues as to how the optionals are treated in the first part of the code.
Apologies for the long-winded explanation, and I hope I've been clear enough, but I imagine I am missing something really basic with the first part of the code. I have tried using the optional ? and also the nil-coalescing operator (to set to 0 in case of nil) but can't get it to work. Please help?
Many thanks in advance!
Use if let for optional binding:
if let var1 = textField.text?.toInt(),
let var2 = textField2.text?.toInt() {
someVariable = var1 * var2 // or directly label1.text = String(var1 * var2)
}
The method toInt() actually returns an optional type 'Int?' that can be nil or integer value, so you need to check if the String->Int cast successful returns an Int or a nil.
For the most basic way:
var intValue: Int? = text.toInt()
if intValue != nil {
// operations using intValue!
}
In swift, you can try:
if let intValue = text.toInt() {
// operations
}
I am working on a very basic (I think) program in Xcode. I am trying to write an app for "drawing straws" where the last person who is chosen is the loser. There are a few things I'd like to do. First, see the code below:
import UIKit
let players = 4
var playerNames: [String] = ["John", "Tyler", "Pete", "Dave"]
var draw = Int(arc4random_uniform(4))
playerNames.removeAtIndex(draw)
print(playerNames)
let round2 = playerNames.count
var draw2 = Int(arc4random_uniform(2))
playerNames.removeAtIndex(draw2)
print(playerNames)
let round3 = playerNames.count
var draw3 = Int(arc4random_uniform(1))
playerNames.removeAtIndex(draw3)
print(playerNames)
The first thing that's wrong is I'm currently hard-coding the random integer being drawn in var draw = Int(arc4random_uniform(4)). When I try to reference players instead of just typing in 4, I get an error. Can someone please help explain the problem there?
I'll stop there for now to see if I can fix that, and I'll wait until that is fixed before posting a new question. Thank you.
The function arc4random_uniform() takes a UInt32, so you need to declare the variable players as UInt32
let players: UInt32 = 4
var draw = (arc4random_uniform(players))
For handling the round variables, you would cast the count to UInt32.
let round2 = UInt32(playerNames.count)
You can also refactor your code
let players: UInt32 = 4
var playerNames: [String] = ["John", "Tyler", "Pete", "Dave"]
println(playerNames)
for loop in 1...players {
RemovePlayer(&playerNames)
println(playerNames)
}
And the code for the RemovePlayer function
func RemovePlayer(inout names: [String]) {
// get the number of names in the array
var maxNames = UInt32(names.count)
var draw = Int((arc4random_uniform(maxNames)))
names.removeAtIndex(draw)
}
As Blackfrog already stated your randomization function requires a UInt32
Since you stated that you just started programing I would like to give you some other advice. Your code can be written as:
var playerNames = ["John", "Tyler", "Pete", "Dave"]
for var index = playerNames.count ; index > 1 ; index -= 1{
var random:Int = Int(arc4random_uniform(UInt32(index)))
playerNames.removeAtIndex(random)
}
println(playerNames[0])
This has a few advantages. At the moment you are hardcoding the values for how many players join a game. You will need to re-write an unnecessary amount of code if you want to add a player.
Let’s see what the above code does:
We start by declaring the playerNames adding a type declaration of [String] isn’t necessary, swift already knows that it is this type by its initial value.
for var index = playerNames.count; index > 1 ; index -= 1{
We create a new variable called index this will be set to the amount of items in the playerNames array (4 in this case)
After this we will declare that we want the loop as long as our index is greater than 1 this will make it run 3 times and make sure we are left with 1 item in our array
The index -=1 will subtract 1 from the index after each iteration through the loop.
var random:Int = Int(arc4random_uniform(UInt32(index)))
Here we declare a new variable random this will be of type Integer. Let’s work from the inside to the outside. UIt32(index) will convert our index which is of type Int to a type of UInt32, this is needed cause our random function requires a UInt32
Next up we request a random value which will lay between the index and 0 (thus between the bounds of the array). We want to remove the player who belongs to this random value in our array. To do this we need to convert our random Uint32 back to an Int we can do this by using Int().
Next we remove the player at the index using
playerNames.removeAtIndex(random)
Lastly we print the first (and only) item left in the array using
println(playerNames[0])