I am new to swift and trying to solve a very basic Logical AND problem
if (textField == self.cvv && cvv.text.length == 4 && !string.isEmpty)
{
return false;
}
this is my code
According to this
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/BasicOperators.html
the && does exists however I am getting error
Couldn't find an overload for the &&
What and how can I use logical operations?
It is not a logical && error: compiler confused by an earlier error:
'String' does not have a member named 'length'
count(cvv.text) is not available either:
See #RMenke's answer for Swift 2.0 syntax.
I just tried this:
var textField = UITextField()
var cvv = UITextField()
var string = ""
if (textField == cvv && cvv.text!.characters.count == 4 && string.isEmpty)
{
return false;
}
I couldn't replicate the error, because I have no idea about the types and declarations of all instances involved. However I got an error on the text.length might be a Swift 1.2 => swift 2.0 change. I updated it to text.characters.count
To more fully answer your question...
&& always worked fine for me, exactly the way you use it.
conditon1 operatorA condition2 && condition3 operatorB conditon4 ...
However the "couldn't find an overload" error is often the result of a type mismatch. Checking an Int against a String for example.
Related
I ask this because I suddenly realized today that, since the if/else statement we use to build View in SwiftUI is interpreted by ViewBuilder, it may behave differently than the plain old if/else statement in Swift language. Could it be that, for some (e.g. performance) reason, SwiftUI pre-execute both clauses and cache the result? Does anyone know it for sure?
I remember I observed some confusing behavior in the past, which might be explained by this hypothesis. But unfortunately I can't recall an example.
The way a result builder transforms your code is spelled out in SE-0289: Result builders. Section “Selection statements” describes how if/else statements are transformed. It gives the following example:
Consider the following code:
if i == 0 {
"0"
} else if i == 1 {
"1"
} else {
generateFibTree(i)
}
Under this pattern, the example code becomes something like the
following:
let vMerged: PartialResult
if i == 0 {
var firstVar = "0"
var firstBlock = BuilderType.buildBlock(firstVar)
vMerged = BuilderType.buildEither(first: firstBlock)
} else if i == 1 {
var secondVar = "1"
var secondBlock = BuilderType.buildBlock(secondVar)
vMerged = BuilderType.buildEither(second:
BuilderType.buildEither(first: secondBlock))
} else {
var elseVar = generateFibTree(i)
var elseBlock = BuilderType.buildBlock(elseVar)
vMerged = BuilderType.buildEither(second:
BuilderType.buildEither(second: elseBlock))
}
You can also read a detailed description of the transformation algorithm, but I think the example makes it clear enough that it will only execute one branch of an if/else statement.
I'm doing some work on another developer's code. I had migrated it to Swift 4 successfully, but with the latest Swift upgrade (Swift 4.2?) I started getting Ambigous use of 'filter' errors. I was able to fix most of them by simply breaking complex statements down, but ran into one with nested filters that I'm not sure what to do with. Here's the complete function:
func validateSubmission(_ submissionId: Int) -> ([EntryModel]) {
let realm = try! Realm()
let submissionModel = realm.objects(SubmissionModel.self).filter({ $0.id == submissionId }).first!
let entryModels = submissionModel.entryModels
// Check for all entry details field which are mandatory and are empty and not hidden
let emptyEntryModels = entryModels.filter({ $0.entryDetailArray.filter({ $0.entryDetailValue.isEmpty && $0.isMandatory && !($0.isHidden) }).count > 0 })
return Array(emptyEntryModels)
}
I get the error on the line:
let emptyEntryModels = entryModels.filter({ $0.entryDetailArray.filter({ $0.entryDetailValue.isEmpty && $0.isMandatory && !($0.isHidden) }).count > 0 })
Can anyone tell me how to "rephrase" this into something more manageable, so I can eliminate the ambiguous filter issue?
I tried your code in Swift 4.0.3 and it didn't give me any error. Try it with type annotation maybe it will work
let emptyEntryModels: [EntryModel] = entryModels.filter({ $0.entryDetailArray.filter({ $0.entryDetailValue.isEmpty && $0.isMandatory && !($0.isHidden) }).count > 0 })
// if you want simplified version of it
var result: [EntryModel] = []
for entryModel in entryModels {
for entryDetail in entryModel.entryDetailArray {
if entryDetail.entryDetailValue.isEmpty && entryDetail.isMandatory && !entryDetail.isHidden {
result.append(entryModel)
}
}
}
I'm trying to filter an array in swift, it works great when I'm just trying to filter a few things but when I add to the list I get this error:
Expression was too complex to be solved in reasonable time; consider
breaking up the expression into distinct sub-expressions
Here is my code with the above error:
filteredArray = workArray.filter { $0.stateName.localizedCaseInsensitiveContainsString(searchString!) || $0.firstName.localizedCaseInsensitiveContainsString(searchString!) || $0.lastName.localizedCaseInsensitiveContainsString(searchString!) || $0.countyName.localizedCaseInsensitiveContainsString(searchString!) || $0.cityName.localizedCaseInsensitiveContainsString(searchString!) || $0.communityName.localizedCaseInsensitiveContainsString(searchString!) || $0.sectionName.localizedCaseInsensitiveContainsString(searchString!) || $0.notes.localizedCaseInsensitiveContainsString(searchString!) || $0.email1.localizedCaseInsensitiveContainsString(searchString!) || $0.email2.localizedCaseInsensitiveContainsString(searchString!) || $0.email3.localizedCaseInsensitiveContainsString(searchString!) || $0.title.localizedCaseInsensitiveContainsString(searchString!) || $0.jobsiteID.localizedCaseInsensitiveContainsString(searchString!)}
I have tried to split this process up like this
filteredArray = workArray.filter { $0.stateName.localizedCaseInsensitiveContainsString(searchString!) || $0.firstName.localizedCaseInsensitiveContainsString(searchString!) || $0.lastName.localizedCaseInsensitiveContainsString(searchString!) || $0.countyName.localizedCaseInsensitiveContainsString(searchString!) || $0.cityName.localizedCaseInsensitiveContainsString(searchString!) || $0.communityName.localizedCaseInsensitiveContainsString(searchString!) || $0.sectionName.localizedCaseInsensitiveContainsString(searchString!) || $0.notes.localizedCaseInsensitiveContainsString(searchString!) || $0.email1.localizedCaseInsensitiveContainsString(searchString!)}
and
filteredArray.appendContentsOf(workArray.filter { $0.email2.localizedCaseInsensitiveContainsString(searchString!) || $0.email3.localizedCaseInsensitiveContainsString(searchString!) || $0.title.localizedCaseInsensitiveContainsString(searchString!) || $0.jobsiteID.localizedCaseInsensitiveContainsString(searchString!)})
But I am getting duplicate objects in the array.
I could write something else that would then look for and delete duplicate objects but I would rather not. My question is how should I be filtering all this items.
Thank you for all the help
Factor that behemoth of an expression out to a method on your datatype.
extension MyDataThingy {
func anyFieldContains(searchTerm term: String) -> Bool {
let fieldValues = [self.stateName, self.firstName, /* etc. */]
for value in fieldValues {
if value.localizedCaseInsensitiveContainsString(term) {
return true
}
}
return false
}
}
Then:
filteredArray = workArray.filter { $0.anyFieldContains(searchTerm: searchTerm) }
This will fix the timeout error from the type inference engine. It is also more readable, more understandable, and more maintainable.
Extended syntax
Try the extended syntax
workArray.filter { elm -> Bool in
// put your conditions here
}
this way you are helping the compiler to understand that the closure receive an element of the type of your array and returns a Bool value.
I am new to programming and trying to find a simpler way to do this:
if state[0] != 0 && state[1] != 0 && state[2] != 0 && state[3] != 0 && state[4] != 0 && state[5] != 0 && state[6] != 0 && state[7] != 0 && state[8] != 0 {
gameOverLabel.text = "It's a tie."
gameOverLabel.hidden = false
active = false
}
I tried the code below but it reacted like a OR rather than a AND.
if state[0&1&2&3&4&5&6&7&8] != 0 {
gameOverLabel.text = "It's a tie."
gameOverLabel.hidden = false
active = false
}
Thanks for any help!
Assuming that your intention is to check if all array elements
are different from zero, the easiest approach would be
if !state.contains(0) { ... }
Your code
if state[0&1&2&3&4&5&6&7&8] != 0 { ... }
does not work
as intended because here the bitwise AND 0&1&2&3&4&5&6&7&8
is computed first (with result zero), so that is equivalent to
if state[0] != 0 { ... }
let state = [0,1,2,0,4,5,6,7]
if state.filter{$0 != 0}.count > 0 {
gameOverLabel.text = "It's a tie."
gameOverLabel.hidden = false
active = false
}
Try this one
The general case with an Array of indices
The short version
let indices = [4,2,9,6,5,3,8,0]
if !indices.contains({ state[$0] == 0 }) {
// ...
}
A second version which only shows the possibilities of Swift:
if !indices.lazy.map{ state[$0] }.contains(0) {
// ...
}
The lazy is used since otherwise map would apply the closure to all indices whereas lazy applies it on average only to half the elements (contains determines the number of executions of the closure).
Note: There is probably no performance improvement for a small amount of indices. The first version is certainly (ever so slightly) faster.
A specific range of indices
Just use the approach above with
let indices = 5...9
Or directly operate on the sub sequence of Array which is ArraySlice.
Side note: Even though it seems that ArraySlice (return type of Array[Range<Int>]) is a value type, internally it is a reference type (like Array) which only copies itself on mutation. In addition ArraySlice is only a view into the array (as long none of them is mutated). So it could be even faster than the first approach.
if !state[24...42].contains(0) {
// ...
}
I have a question about Objective C
I want an inverted if statement. Like: if (!example.hidden == YES) {
Here's my code:
if ((randomBallTouch.x>_randomColorBall.center.x-(_randomColorBall.frame.size.width)/2) &&
(randomBallTouch.x<_randomColorBall.center.x+(_randomColorBall.frame.size.width)/2) &&
(randomBallTouch.y>_randomColorBall.center.y-(_randomColorBall.frame.size.height)/2) &&
(randomBallTouch.y<_randomColorBall.center.y+(_randomColorBall.frame.size.height)/2)) {
_randomColorBall.center = CGPointMake(randomBallTouch.x, randomBallTouch.y);
if (_randomColorBall.hidden == NO) {
_redBall.center = CGPointMake(_redBall.center.x, _redBall.center.y - 200);
}
}
But when i do: if(!(randomBallTouch.x>_randomColorBall.center.x)) etc. It does not work.
And I can't do else because that will bug with the other two if statements.
Any help?? I am using Xcode 5.1.
You can't just add an ! at the beginning to invert the condition. You need to wrap the whole expression in a set of parentheses first.
If you have:
if (a && b) {
then the inversion is:
if (!(a && b)) {
You didn't add those parentheses.
Try this, just replace your if with this one.
if(!((randomBallTouch.x > (_randomColorBall.center.x-(_randomColorBall.frame.size.width)/2)) && (randomBallTouch.x < (_randomColorBall.center.x+(_randomColorBall.frame.size.width)/2)) && (randomBallTouch.y > (_randomColorBall.center.y-(_randomColorBall.frame.size.height)/2)) &&(randomBallTouch.y < (_randomColorBall.center.y+(_randomColorBall.frame.size.height)/2)))) {
You are missing a lot of parenthesis to make your statement a valid boolean.