Expected Sequence expression swift 3 - ios

I'm using a loop to set the original image for tab bar items so the unselected state isn't gray (my original icons are white). However, it looks like the recent Xcode 8 update broke the code:
for (items in 0 ..< tabBar.items!.count ){
let tabItemIndex = tabBar.items![items]
tabItemIndex.image = tabItemIndex.image!.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
}
}
I'm getting the following errors on the first line: Expected 'in' after for-each pattern, Expected Sequence expression for for-each loop, and Expected pattern.
Can anyone please help me fix this solution? It worked great until today.
Thanks!!

for x in y is an actual expression in Swift. You cannot break it up with parentheses, for (x in y) — that separates the for from the in and causes the expression to seem like nonsense to the compiler.
So, delete the parentheses and all will be well.

You have some issues on how you're creating your loop, and some very unsafe forced unwrapping. Try this:
if let items = tabBar.items {
for tabBarItem in items {
if let image = tabBarItem.image {
tabBarItem.image = image.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
}
}
}
Or even cleaner, like this:
tabBar.items?.forEach { tabBarItem in
if let image = tabBarItem.image {
tabBarItem.image = image.withRenderingMode(UIImageRenderingMode.alwaysOriginal)
}
}

In Swift, unlike in Objective-C, there are no parentheses involved in this structure. Remove the parentheses to fix your syntax error.
However, there are style and safety issues here other than the syntax error: see picciano's answer for a much cleaner and safer way to rewrite the loop.

Related

Return/break out of infinite foreach in kotlin

For class I have to make a program that calculates the birthday problem
Now I'm having trying to learn kotlin at the same time and I'm having trouble with a little snippet of code:
val checkSet = mutableSetOf<Int>()
generateSequence{ Random.nextInt(n)}.forEach {
if(!checkSet.add(it)) {
return#outForeach
}
}
outForeach#
sum += checkSet.size
As you can see I'm trying to do this with an infinite sequence. Kotlin doesn't accept this as outForeach is an unresolved reference. But this doesn't work either:
val checkSet = mutableSetOf<Int>()
generateSequence{ Random.nextInt(n)}.forEach {
if(!checkSet.add(it)) {
return#forEach
}
}
sum += checkSet.size
This will just start the forEach loop again. Is there a way to implement something as a forEachUntil or so?
p.s. I'm aware that this looks a lot like this question: 'return' doesn't jump out of forEach in Kotlin It's just that I don't really get the answers and I don't know if its applicable here. Also a way to implement forEachUntil seems for me to be far more elegant
Alternatives you may want to consider instead of first:
using a simple while without body:
while (checkSet.add(Random.nextInt(n))); // <- that semicolon is required! otherwise you execute what is coming next within the while
using run with a label:
run outForeach#{
generateSequence{ Random.nextInt(n)}.forEach {
if(!checkSet.add(it)) {
return#outForeach
}
}
}
maybe also takeWhile might be helpful. In this specific case however it is surely not (as it would check against the checkSet and leave us with a sequence that isn't consumed... but if the condition would be different, it may make sense to consider something like take, takeWhile, takeLast, etc.):
generateSequence { Random.nextInt(n) }
.takeWhile(checkSet::add) // as said: for this specific condition it doesn't make sense...
.forEach { /* do nothing except consume the sequence */ } // the same values you added to the set would be available in this step of course
I think I found the solution myself:
val checkSet = mutableSetOf<Int>()
generateSequence{ Random.nextInt(n)}.first { !checkSet.add(it) }
sum += checkSet.size
Basically use the function first() and keep returning false until you want to get out of the loop. And just drop the return of the function first()

fatal error: Index out of range (swift)

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)))
}

Swift UIView.animateWithDuration and For-Loops

I have a group of UIImageViews that are stored in an array. I want to animate a certain amount of these ImageViews in the same way. Thus, I have been trying to use the following code:
var lowerViews: [UIImageView] = [imageView1, imageView2, imageView3, imageView4]
var startingIndex = 1;
UIView.animateWithDuration(0.3, delay: 0.1, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
for index in startingIndex..< lowerViews.count {
lowerViews[index].frame.origin.y += 100
}
}, completion: nil)
However at this line:
for index in startingIndex..< lowerViews.count {
Xcode gives me the error:
Expected '{' to start the body of each for-loop
However, I don't believe that this is really the issue. This seems to me that it is an arbitrary syntax error that Xcode gets because I am using the for-loop inside the 'animation' parameter. Since I am still learning a lot about Swift I do not know why this wouldn't work, and so if this assumption is correct, I would like to know why and how I can get around this.
If this is not the case, please let me know, because either way I need to get around the problem.
Thanks in advance
This is a tricky error (note spaces around ..<).
for index in startingIndex ..< lowerViews.count {
will work or
for index in startingIndex..<lowerViews.count {
will work but:
for index in startingIndex..< lowerViews.count {
won't work.
The reason for this is the fact that when startingIndex..< is used, then ..< is considered to be a postfix (unary) operator (not an infix operator). Therefore the whole expression stops making sense and you start getting strange errors.
Also see what are the rules for spaces in swift

Enumerating with a for-in loop

I've got a loop that's throwing an error "Int is not convertible to Range< Int >":
var summaryValues:[Int]=[Int]();
for (dayIndex,valuesPerDay) in enumerate(allValuesPerDay){
if (valuesPerDay>0){
while summaryValues[dayIndex]==nil{ // ERROR
summaryValues.append(0);
}
summaryValues[dayIndex]++
}
}
That fourth line should simply be checking if there is a value at summaryValues in position dayIndex, but I'm a little unclear on the Swift syntax. Any ideas on how to fix this? Thanks for reading.
EDIT:
The work-around I've implemented is to replace the error line with
while cohortRetension.count<dayIndex+1 but I'd still like to better understand why summaryValues[dayIndex] was incorrect.
while summaryValues[dayIndex]==nil{ // ERROR
summaryValues is an array and array[i] won't return nil. It will either return the element or it will crash if your index is out of range. First, the compiler is probably confused from comparing Int and nil. Second, trying to access summaryValues[dayIndex] here will crash, because at the time you are checking it the array is empty and the index does not exist.
Repeatedly appending to an array is inappropriate when you know the size up front. Initialize your summaryValues as:
var summaryValues = [Int](count: allValuesPerDay.count, repeatedValue: 0)
then iterate over your allValuesPerDay simply with:
for dayIndex in 0..<allValuesPerDay.count {
if allValuesPerDay[dayIndex] > 0 {
summaryValues[dayIndex]++
}
}

Swift: Random number arrays inside images and variables with a for loop

I am creating a game in which, depending on the number of 'swipes' chosen to do, (let's say 3), 3 different patterns show on the screen, one by one. I am working on developing the first pattern.
So I have this:
if (swipes.no_of_swipes) == 3 {
swipeArray = Array<UInt32>(count: 3, repeatedValue: 0)
for i in 0 ..< 3 {
swipeArray[i] = arc4random_uniform(84)}
}
As far as I am aware, this code creates an array with three UInts which can be accessed by doing swipeArray[0], swipeArray[1], and swipeArray[2]. My first question is how long will this swipeArray stay the same? Until the close the view? Should I have a 'refresh button' when the user loses - and if so, how would I make one?
Then I have a property observer. You will notice the for loop, which I am using to keep code concise. I understand that I could do something like x++ somewhere in here so that it will go through each one.
var playBegin: Bool = false{
didSet {
if playBegin == true {
println("\(playBegin)")
var swipes = Menu()
if (swipes.no_of_swipes) == 3 {
for i in 0 ..< 3 {
patternRoom.image = UIImage(named: "pattern\(swipeArray[x])")
//rest of code
}
}
}
The pattern image comes from a set of 84 images named like pattern7 and pattern56. My second question is, how could I code the for loop to go through each swipeArray[x].
Thank you in advance,
Will
how long will this swipeArray stay the same?
This is a bit too open ended. It’ll stay the same until you assign a new value to it, either from this same bit of code or a different part. Only you can know when that will be, by looking at your code.
Since you express an interest in keeping the code concise, here’s a couple of code tips.
You might think about writing your first snippet’s loop like this:
swipeArray = (0..<swipes.no_of_swipes).map { _ in
arc4random_uniform(84)
}
This combines creating a new array and populating the values. By the way, just in case you don’t realize, there’s no guarantee this array won’t contain the same value twice.
It’s also probably better to make swipeArray of type [Int] rather than [UInt32], and to convert the result of arc4random to an Int straight away:
Int(arc4random_uniform(84))
Otherwise the UInt32s will probably be a pain to work with.
For your second for loop, you can do this:
for i in swipeArray {
patternRoom.image = UIImage(named: "pattern\(i)")
// rest of code
}
When writing Swift, usually (but not always), when you find yourself using array[x] there’s a better more expressive way of doing it.

Resources