What is the swift equivalent of makeObjectsPerformSelector?
Updated for Swift 2.0 (Xcode 7)
Use forEach
:
self.view.subviews.forEach { subview in
subview.removeFromSuperview()
}
Or like this:
view.subviews.forEach { $0.removeFromSuperview() }
bridgeToObjectiveC and makeObjectsPerformSelector in Swift beta 5
The bridgeToObjectiveC
and bridgeFromObjectiveC
functions are not available in Xcode 6.0 beta 5. Instead, cast to/from the appropriate Foundation type when you need to use that type's API on a Swift object. For example:
var arr = ["One", "Two"]
(arr as NSArray).indexOfObject("One")
Apple has warned against (or explicitly made unavailable) using performSelector
and related methods since the first Swift beta. Presumably any such API that were still available before beta 5 were unintentionally so.
As the question you cited notes, you can use map
to call a function/method on every element of an array. You can also use filter
, find
or a for
-in
loop, or after casting to NSArray
, one of the enumerateObjects
methods. Note that many consider it bad style to use the functional-programming constructs (map
, filter
, reduce
, find
) for tasks that aren't "functional" -- that is, to run code that has side effects. So a for
-in
loop might be the cleanest way to do what you're after.
How can I execute the same function for all objects of a collection in Swift?
You can try
observers.forEach { $0.update(message: "updated") }
Remove all the subviews from a UIScrollView?
Let scrollView
be an instance of UIScrollView
.
In Objective-C, it's pretty easy. Just call makeObjectsPerformSelector:
, like so:
Objective-C:
[scrollView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)];
In Swift, you don't get that runtime access, so you have to actually handle the iteration yourself.
Swift:
A concise version, from here:
scrollview.subviews.map { $0.removeFromSuperview() }
A more descriptive way to do this (from here) assumes scrollview.subviews
:
let subviews = self.scrollView.subviews
for subview in subviews{
subview.removeFromSuperview()
}
bridgeToObjectiveC not available on Swift Beta 5
Use as
to cast to NSString
for the same effect:
("string" as NSString).localizedCaseInsensitiveCompare("other string")
Or like this with optional chaining:
("string" as NSString?)?.localizedCaseInsensitiveCompare("other string")
How to update an array with WritableKeyPath in Swift 4.0
Mutating into a member of an array requires an l-value. Swift's mechanism for l-values is the subscript, so we can use that:
for i in people.indices {
people[i][keyPath: \Person.name] = updated
// or more simply, just:
// people[i].name = "updated"
// This even works too, but I can't see any reason why it would be desirable
// over the other 2 approaches:
// people[keyPath: \[Person].[i].name] = "update"
}
You could also use forEach
, but I generally only recommend that over for
in cases where you have an existing closure/function to pass in which has type (Index) -> Void
:
// meh
people.indices.forEach {
people[$0][keyPath: \Person.name] = "updated"
}
Obj C and makeObjectsPerformSelector - am I overlooking something?
To bypass the problem of int to be a C type and not an object, use KVC (Key-Value Coding). If you call setValue:forKey: on a NSArray object, the method setValue:forKey: is call on each of the objects of the array. And with a bonus, KVC is managing all the primitive stuff.
[_stepper setValue:@0 forKey:@"value"];
[_fields setValue:@"0" forKey:@"text"];
bridgeToObjectiveC() not available for Array in Swift
Note that Swift has a 'find' function that you can use to see if an element is in an array or not:
find(array,element):C.Index?
It will return nil
if the item is not found. You should probably use this instead of contains.
When to use forEach(_:) instead of for in?
There is no performance benefit offered by forEach
. In fact, if you look at the source code, the forEach
function actually simply performing for
-in
. For release builds, the performance overhead of this function over simply using for
-in
yourself is immaterial, though for debug builds, it results in an observable performance impact.
The main advantage of forEach
is realized when you are doing functional programming, you can add it to a chain of functional calls, without having to save the prior result into a separate variable that you'd need if you used for
-in
syntax. So, instead of:
let objects = array.map { ... }
.filter { ... }
for object in objects {
...
}
You can instead stay within functional programming patterns:
array.map { ... }
.filter { ... }
.forEach { ... }
The result is functional code that is more concise with less syntactic noise.
FWIW, the documentation for Array, Dictionary, and Sequence all remind us of the limitations introduced by forEach
, namely:
You cannot use a
break
orcontinue
statement to exit the current
call of thebody
closure or skip subsequent calls.Using the
return
statement in thebody
closure will exit only from
the current call tobody
, not from any outer scope, and won't skip
subsequent calls.
Related Topics
Returning Object from Callback in Swift
How to Force a Uitableview to Hide the Separator Between Empty Cells
Nsuserdefaults Losing Its Keys & Values When Phone Is Rebooted But Not Unlocked
No Suitable Records Were Found Verify Your Bundle Identifier Is Correct
Parsing JSON Within JSON in Objective-C
Leaking Views When Changing Rootviewcontroller Inside Transitionwithview
Proper Usage of Intrinsiccontentsize and Sizethatfits: on Uiview Subclass with Autolayout
When to Use Static Constant and Variable in Swift
Swift UI Remove Extra List Empty Cells Without Navigation Controller
Ui Testing Failure - Neither Element Nor Any Descendant Has Keyboard Focus on Securetextfield
How to Change the Blue Highlight Color of a Uitableviewcell
How to Determine Which Textfield Is Active Swift
Issue with Uitableview: Action Only Works Every Second Time