Last active
April 26, 2016 07:15
-
-
Save isoiphone/c729437bfaa10e4450ea to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extension UIView { | |
func forEachSubviewOfType<V: UIView>(type: V.Type, @noescape apply block: V -> Void) { | |
for view in subviews { | |
if let view = view as? V { | |
block(view) | |
} else { | |
view.forEachSubviewOfType(V.self, apply: block) | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
searchController.searchBar.forEachSubviewOfType(UITextField.self) { textField in | |
textField.textColor = .whiteColor() | |
} |
Edit: Hah! iosdevzone chimed in while I was away and said something very similar.
I think you should split up the mapping logic and the forEach logic. Then you can recur over anything you like.
extension SequenceType {
/// Recursively map, and stop recurring at the first non-nil element in a branch
///
///- Parameter recursed: the next level of children
///- Parameter map: transform the non-nil elements
func flatMapped<Mapped>(
@noescape recursed recursed: Generator.Element -> Self,
@noescape _ map: Generator.Element -> Mapped?
) -> [Mapped] {
return reduce([]){
if let mapped = map($1) {return $0 + [mapped]}
return $0 + recursed($1).flatMapped(recursed: recursed, map)
}
}
}
UISearchBar().subviews.flatMapped(recursed: {$0.subviews}){$0 as? UITextField}
.forEach{$0.textColor = .whiteColor()}
struct Branch {
let datum: Int
let branches: [Branch]
}
let branch1 = Branch(datum: 1, branches: [])
let branch2 = Branch(datum: 2, branches: [branch1])
let branch3 = Branch(datum: 3, branches: [branch2])
let branches = [branch1, branch2, branch3].flatMapped(recursed: {$0.branches})
{$0.datum < 2 ? $0 : nil}
// branch1, thrice
branches
Here's iosdevzone's code as an extension:
extension SequenceType {
func recursed(recursed: Generator.Element -> Self) -> [Generator.Element] {
return flatMap{[$0] + recursed($0).recursed(recursed)}
}
}
UISearchBar().subviews.recursed{$0.subviews}.flatMap{$0 as? UITextField}
.forEach{$0.textColor = .whiteColor()}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Seems like you're doing two things at one: flattening the tree and operating on it. If the hierarchy was huge this might make sense (memory allocation time). In your case it probably isn't so I think I would do something like this.
Note: this is a free function not in an extension.
Then use
filter
andforEach
as above.If you're going to have a flatten routine, you might as well make it generic. All we need is the type and how to get children.
Then your extension method looks like this: