Reputation: 13298
I'm using the following code to find a certain subview inside my view. It works fine, and the for
loop runs only once because it only finds one subview that satisfies the where
clause.
for view in boardView.subviews where (view as? PlayingCardView)?.position.location == source.
&& (view as! PlayingCardView).position.column == source.column
&& (view as! PlayingCardView).position.row >= source.row
However, it seems weird that I'm running a loop here when I'm not actually doing any...loop-y things (know what I mean)?
Is there some other way to "search" like this? Like a way to use subviews.index(of:)
and use the conditions from the where
clause, or something like that?
Also, I know that I could do the same code like this:
for view in boardView.subviews {
if let cardView = view as? PlayingCardView {
if cardView.position.location == source.location
&& (view as! PlayingCardView).position.column == source.column
&& (view as! PlayingCardView).position.row >= source.row {
// Do stuff
}
}
}
Is one of these ways computationally faster?
Upvotes: 0
Views: 263
Reputation: 11539
I believe you're looking for the filter
method.
if let card = (boardView.subviews as? [PlayingCardView])?.filter({
return $0.position.location == source.location
&& $0.position.column == source.column
&& $0.position.row >= source.row
}).first {
// Do stuff
print(card)
}
Or if you want to find the first card that satisfies your arguments, you can use the first
method.
if let card = (boardView.subviews as? [PlayingCardView])?.first(where: {
return $0.position.location == source.location
&& $0.position.column == source.column
&& $0.position.row >= source.row
}) {
// Do stuff
print(card)
}
Upvotes: 1
Reputation: 93191
first(where: )
will give you the first element in the array that satisfies a condition (assuming that you only want to do it on one element since it's not "loopy"):
let view = boardView.subviews.first {
guard let cardView = $0 as? PlayingCardView else { return false }
return cardView.position.location == source.location
&& cardView.position.column == source.column
&& cardView.position.row >= source.row
}
// do stuffs to `view`
It will stop as soon as a match is found so that's about as efficient as you can get. In reality though, it hardly matters as you tend to have only a small number of subviews. Otherwise the GPU will give out first from having to render all of them.
Upvotes: 0