Check if a function is available in Swift?
A proper check for availability has been added in Swift 2. This is recommended over other options mentioned here.
var shouldApplyMotionEffects = true
if #available(iOS 8.0, *) {
shouldApplyMotionEffects = !UIAccessibilityIsReduceMotionEnabled()
}
Check existence of global function in Swift
Swift currently does not support looking up global functions.
For C functions (most global functions from Apple's frameworks are C functions) there are at least two ways:
- using a weakly linked symbol
- the dynamic linker API:
dlopen
Both check dynamically (at runtime) if a symbol can be found.
Here's an example that checks if UIGraphicsBeginImageContextWithOptions
(introduced with iOS 4) is available:
void UIGraphicsBeginImageContextWithOptions(CGSize size, BOOL opaque, CGFloat scale) __attribute__((weak));
static inline BOOL hasUIGraphicsBeginImageContextWithOptions() {
return UIGraphicsBeginImageContextWithOptions != NULL;
}
Here's the same check, using dlsym
:
#import <dlfcn.h>
static inline BOOL hasUIGraphicsBeginImageContextWithOptions() {
return dlsym(RTLD_SELF, "UIGraphicsBeginImageContextWithOptions") != NULL;
}
The advantage of using dlsym
is that you don't need a declaration and that it's easily portable to Swift.
Cocoa check if function exists
Assuming you are talking about a C function, you can do this with the dlopen
function:
#include <dlfcn.h>
int main() {
void *lib = dlopen("/System/Library/Frameworks/ApplicationServices.framework/ApplicationServices", RTLD_LAZY);
void *function = dlsym(lib, "CGColorGetConstantColor");
// cast the function to the right format
CGColorRef (*dynamic_getConstantColor)(CFStringRef colorName) = function;
NSLog(@"%@", dynamic_getConstantColor(CFSTR("kCGColorBlack")));
dlclose(lib);
}
Output:
2013-06-20 12:43:13.510 TestProj[1699:303] [ (kCGColorSpaceICCBased; kCGColorSpaceModelMonochrome; Generic Gray Profile)] ( 0 1 )
You will need to figure out the dylib in which the function you want resides, first, though.
This will break the sandbox limitations on iOS, and Mac most likely as well. It is the price you pay for trying to get around the linker.
Check if variable is a block / function / callable in Swift
You can check the String representation of .dynamicType
of the callable for existence of substring ->
. Not super-elegant, but it works:
func isAClosure<T>(foo: T) -> Bool {
return String(foo.dynamicType).containsString("->")
}
var a : () -> () = { print("Foobar") }
var b : (Double) -> (Bool) = { $0 > 0 }
var c : Int = 1
isAClosure(a) // true
isAClosure(b) // true
isAClosure(c) // false
Of course, as Marcus Rossel points out in the comment above, you still wouldn't know anything about the parameters of the callable (but perhaps that could be next step to find out, given that you know it's a callable).
Addition with regard to OPs questions below: just a technical discussion, and not recommended techniques.
You use the same approach as above to check if the function argument is a closure without arguments (() -> (...)
) or one with neither arguments nor return type (() -> ()
), and so on. Using this approach, you can define a generic function that call the argument sent to the function only if it is of a certain closure type. For this "in-function-call", you'll have to make use of type conversion to expected closure type, much as you've described in your Q above. It'll probably be difficult to circumvent this "non-generic" approach w.r.t. calling the closures. A few examples follow below.
/* Example functions */
func isAVoidParamClosure<T>(foo: T) -> Bool {
let bar = String(foo.dynamicType).componentsSeparatedByString(" -> ")
return bar.count > 1 && (bar.first?.characters.count ?? 0) == 2
}
func callIfVoidVoidClosure<T>(foo: T) {
let bar = String(foo.dynamicType).componentsSeparatedByString(" -> ")
if bar.count > 1 && !(bar.map{ $0 == "()" }.contains(false)) {
if let foo = foo as? () -> () {
foo()
}
}
}
func isASingleDoubleReturnTypeClosure<T>(foo: T) -> Bool {
let bar = String(foo.dynamicType).componentsSeparatedByString(" -> ")
return bar.count > 1 && bar[1] == "Double"
/* rhs of '&&' lazily evaluated: [1] ok */
}
func printTwoTimesResultOfVoidDoubleClosure<T>(foo: T) {
if isAVoidParamClosure(foo) && isASingleDoubleReturnTypeClosure(foo) {
if let foo = foo as? () -> Double {
let a: Double = 2*foo()
print(a)
}
}
}
Example calls:
/* Example calls */
let a : () -> () = { print("Foobar") }
let b : (Double) -> (Bool) = { $0 > 0 }
let c : () -> Double = { 21.0 }
let d : Int = 1
isAVoidParamClosure(a) // true
isAVoidParamClosure(b) // false
isAVoidParamClosure(c) // true
isAVoidParamClosure(d) // false
callIfVoidVoidClosure(a) // Prints "Foobar"
callIfVoidVoidClosure(b)
callIfVoidVoidClosure(c)
callIfVoidVoidClosure(d)
printTwoTimesResultOfVoidDoubleClosure(a)
printTwoTimesResultOfVoidDoubleClosure(b) // Prints "42.0"
printTwoTimesResultOfVoidDoubleClosure(c)
printTwoTimesResultOfVoidDoubleClosure(d)
Swift - Check if object is of a given type (where the type has been passed as function argument)
I don't know where you are taking myArray
. You probably need to create an extension to Array for MyBaseClass. Like this:
extension Array where Element: MyBaseClass {
func myFilter<T: MyBaseClass>(objectType: T.Type) -> [T] {
var filteredArray: [T] = []
for object in self {
if let object = object as? T {
filteredArray.append(object)
}
}
return filteredArray
}
}
Then you can call:
// Example call
let array = [SubclassA(), SubclassA(), SubclassC(), SubclassD()]
array.myFilter(objectType: SubclassD.self) // == [SubclassD()]
EDIT:
Easy solution if you want a return type of myFilter
to be just MyBaseClass
and you don't want to change the original array would be this:
array.filter { $0 is SubclassD }
Check if the element exists in the array, and then replace between two arrays Swift
If the order of the collection doesnt matter you should use a set to make sure there is no duplicated players in your collection:
var mainPlayers: Set = ["player1", "player2", "player3"]
var secondaryPlayers: Set = ["player4", "player5", "player6"]
let oldPlayer = "player1"
let newPlayer = "player4"
if mainPlayers.contains(oldPlayer),
secondaryPlayers.contains(newPlayer),
let oldMember = mainPlayers.remove(oldPlayer),
let newMember = secondaryPlayers.remove(newPlayer),
mainPlayers.insert(newMember).inserted,
secondaryPlayers.insert(oldMember).inserted {
print("oldMember", oldMember) // player1
print("newMember", newMember) // player4
print(mainPlayers) // ["player3", "player4", "player2"]
print(secondaryPlayers) // ["player1", "player5", "player6"]
}
If the order of the collection matters the array approach should look like this:
var mainPlayers = ["player1", "player2", "player3"]
var secondaryPlayers = ["player4", "player5", "player6"]
if let oldMemberIndex = mainPlayers.firstIndex(of: "player1"),
let newMemberIndex = secondaryPlayers.firstIndex(of: "player4"),
case let oldMember = mainPlayers.remove(at: oldMemberIndex),
case let newMember = secondaryPlayers.remove(at: newMemberIndex) {
mainPlayers.insert(newMember, at: oldMemberIndex)
secondaryPlayers.insert(oldMember, at: newMemberIndex)
print("oldMember", oldMember) // player1
print("newMember", newMember) // player4
print(mainPlayers) // ["player4", "player2", "player3"]
print(secondaryPlayers) // ["player1", "player5", "player6"]
}
Swift extension of Sequence to check if an intersection exists
Well I found the correct syntax, not sure why the other syntax would not work tho :/
If someone could still explain why the other way does not work, it'd be interesting /p>
extension Sequence where Element:Equatable {
func intersects<T:Sequence>(with anotherSequence:T) -> Bool
where T.Element == Self.Element {
return self.contains(where: anotherSequence.contains)
}
}
Related Topics
Play Mp4 Using Mpmovieplayercontroller() in Swift
Compile Latex Code Using Swift
Adding Animation to Tabviews in Swiftui When Switching Between Tabs
How to Capture Multiple Arguments Weakly in a Swift Closure
Why Are Properties of an Immutable Object Mutable in Swift
How to Detect Text View Begin Editing and End Editing in Swift 3
Behaviour of Protocols with Self
Integer Literal Overflows When Stored into 'Int'
Swift Unit Testing with Xctassertthrows Analogue
How to Set Priority on Constraints in Swift
Mfmailcomposeviewcontroller Error [Mc] Filtering Mail Sheet Accounts for Bundle Id
Background Upload with Share Extension
Calling Stop() on Avaudioplayernode After Finished Playing Causes Crash
Distributednotificationcenter - How to Pass Data Between Applications