How NSAnimationContext completionHandler work with Swift Language - swift

i couldn't port this to swift, rest of NSAnimationContext straight forward.
[[NSAnimationContext currentContext] setCompletionHandler:^(void) {
//doSomething here...
}];
in docs it says var completionHandler: (() -> Void)! it did not mean anything to me.
Thank you.

() -> Void is the signature for a Swift closure that takes no parameters and returns nothing. Use it much like you would an ObjC block:
NSAnimationContext.currentContext().completionHandler = {
// do something here
}
Note that since it's declared as a property, you should set it like one -- ObjC getter/setter pairs don't translate to Swift.

Related

Is it possible to Extend functions in swift

I would like to ask if it's possible to extend functions or have some way to use them like this. Because I don't want to open task closure for every async function. I couldnt find any Nominal Type for functions in swift to extend.
func doSometingAsync() async -> Void {
}
// Non - desired
Task {
await doSometingAsync()
}
func makeItAsync() {
Task {
await self()
}
}
// Desired
doSometingAsync().makeItAsync()
// Extending those also not working
typealias Function = () -> Void
typealias AsnyFunction = () async -> Any?
Thank you!
You definitely shouldn't create a Task for every async function. If you are, something else is likely wrong. But your desired syntax is definitely impossible. You cannot attach methods to functions. Swift does not support it. It's not logically impossible (Go uses it regularly). It's just not a Swift feature, and I expect it will never be a Swift feature. It's not the direction Swift is evolving.
The following is legal if you want it:
func makeAsync(_ f: #escaping () async -> Void) {
Task { await f() }
}
makeAsync(doSometingAsync)
This is shorter than your proposed solution by a few characters, if that matters to you.
All said, though, if you need this a lot, you probably have an async design problem, and should investigate that.

Swift Indicate that a closure parameter is retained

Is there any way to indicate to a "client" of a specific method that a closure parameter is going to be retained?
For instance, having the following code:
import Foundation
typealias MyClosureType = () -> Void
final class MyClass {
private var myClosure: MyClosureType?
func whatever(closure: MyClosureType?) {
myClosure = closure
}
}
Anyone could start using this class and passing closures to the method whatever without any idea about if it is actually being retained or not. Which is error prone and could lead to memory leaks.
For instance, a "client" doing something like this, would be never deallocated
final class MyDummyClient {
let myInstance = MyClass()
func setUp() {
myInstance.whatever {
self.whateverHandler()
}
}
func whateverHandler() {
print("Hey Jude, don't make it bad")
}
}
That is why I would like to know if there is any way to prevent this type of errors. Some type of paramater that I could add to the definition of my method whatever which gives a hint to the client about the need to weakify to avoid leaks
Whether the closure parameter is escaping or non-escaping is some indication to the caller whether it might be retained. In particular, a non-escaping closure param cannot be retained by a function call.
Per SE-0103, non-escaping closures (currently marked #noescape) will become the default in Swift 3, and you'll have to write #escaping if you want to save the closure, so situations like this will become a little more obvious.
Otherwise, there is no language feature to help you here. You'll have to solve this problem with API design and documentation. If it's something like a handler, I'd recommend a property, obj.handler = { ... }, or a method like obj.setHandler({ ... }) or obj.addHandler({ ... }). That way, when reading the code, you can easily tell that the closure is being saved because of the = or set or add.
(In fact, when compiling Obj-C, Clang explicitly looks for methods named set...: or add...: when determining whether to warn the user about retain cycles. It's possible a similar diagnostic could be added to the Swift compiler in the future.)
With the specific case you're presenting the closure itself is the only thing that will be retained, so if you correctly add [weak self] to your closure when you call it there shouldn't be any issues.
I'm not sure what issue you're trying to protect against, but you might also thing about using delegation (protocols) rather than a closure.

How do I resolve "ambiguous use of" compile error with Swift #selector syntax?

[NOTE This question was originally formulated under Swift 2.2. It has been revised for Swift 4, involving two important language changes: the first method parameter external is no longer automatically suppressed, and a selector must be explicitly exposed to Objective-C.]
Let's say I have these two methods in my class:
#objc func test() {}
#objc func test(_ sender:AnyObject?) {}
Now I want to use Swift 2.2's new #selector syntax to make a selector corresponding to the first of these methods, func test(). How do I do it? When I try this:
let selector = #selector(test) // error
... I get an error, "Ambiguous use of test()." But if I say this:
let selector = #selector(test(_:)) // ok, but...
... the error goes away, but I'm now referring to the wrong method, the one with a parameter. I want to refer to the one without any parameter. How do I do it?
[Note: the example is not artificial. NSObject has both Objective-C copy and copy: instance methods, Swift copy() and copy(sender:AnyObject?); so the problem can easily arise in real life.]
[NOTE This answer was originally formulated under Swift 2.2. It has been revised for Swift 4, involving two important language changes: the first method parameter external is no longer automatically suppressed, and a selector must be explicitly exposed to Objective-C.]
You can work around this problem by casting your function reference to the correct method signature:
let selector = #selector(test as () -> Void)
(However, in my opinion, you should not have to do this. I regard this situation as a bug, revealing that Swift's syntax for referring to functions is inadequate. I filed a bug report, but to no avail.)
Just to summarize the new #selector syntax:
The purpose of this syntax is to prevent the all-too-common runtime crashes (typically "unrecognized selector") that can arise when supplying a selector as a literal string. #selector() takes a function reference, and the compiler will check that the function really exists and will resolve the reference to an Objective-C selector for you. Thus, you can't readily make any mistake.
(EDIT: Okay, yes you can. You can be a complete lunkhead and set the target to an instance that doesn't implement the action message specified by the #selector. The compiler won't stop you and you'll crash just like in the good old days. Sigh...)
A function reference can appear in any of three forms:
The bare name of the function. This is sufficient if the function is unambiguous. Thus, for example:
#objc func test(_ sender:AnyObject?) {}
func makeSelector() {
let selector = #selector(test)
}
There is only one test method, so this #selector refers to it even though it takes a parameter and the #selector doesn't mention the parameter. The resolved Objective-C selector, behind the scenes, will still correctly be "test:" (with the colon, indicating a parameter).
The name of the function along with the rest of its signature. For example:
func test() {}
func test(_ sender:AnyObject?) {}
func makeSelector() {
let selector = #selector(test(_:))
}
We have two test methods, so we need to differentiate; the notation test(_:) resolves to the second one, the one with a parameter.
The name of the function with or without the rest of its signature, plus a cast to show the types of the parameters. Thus:
#objc func test(_ integer:Int) {}
#nonobjc func test(_ string:String) {}
func makeSelector() {
let selector1 = #selector(test as (Int) -> Void)
// or:
let selector2 = #selector(test(_:) as (Int) -> Void)
}
Here, we have overloaded test(_:). The overloading cannot be exposed to Objective-C, because Objective-C doesn't permit overloading, so only one of them is exposed, and we can form a selector only for the one that is exposed, because selectors are an Objective-C feature. But we must still disambiguate as far as Swift is concerned, and the cast does that.
(It is this linguistic feature that is used — misused, in my opinion — as the basis of the answer above.)
Also, you might have to help Swift resolve the function reference by telling it what class the function is in:
If the class is the same as this one, or up the superclass chain from this one, no further resolution is usually needed (as shown in the examples above); optionally, you can say self, with dot-notation (e.g. #selector(self.test), and in some situations you might have to do so.
Otherwise, you use either a reference to an instance for which the method is implemented, with dot-notation, as in this real-life example (self.mp is an MPMusicPlayerController):
let pause = UIBarButtonItem(barButtonSystemItem: .pause,
target: self.mp, action: #selector(self.mp.pause))
...or you can use the name of the class, with dot-notation:
class ClassA : NSObject {
#objc func test() {}
}
class ClassB {
func makeSelector() {
let selector = #selector(ClassA.test)
}
}
(This seems a curious notation, because it looks like you're saying test is a class method rather than an instance method, but it will be correctly resolved to a selector nonetheless, which is all that matters.)
I want to add a missing disambiguation: accessing an instance method from outside the class.
class Foo {
#objc func test() {}
#objc func test(_ sender: AnyObject?) {}
}
From the class' perspective the full signature of the test() method is (Foo) -> () -> Void, which you will need to specify in order to get the Selector.
#selector(Foo.test as (Foo) -> () -> Void)
#selector(Foo.test(_:))
Alternatively you can refer to an instance's Selectors as shown in the original answer.
let foo = Foo()
#selector(foo.test as () -> Void)
#selector(foo.test(_:))
In my case (Xcode 11.3.1) the error was only when using lldb while debugging. When running it works properly.

Completion Handlers in Swift

I'm fairly new at swift development and trying to get a handle on closures and completion handlers. I have a function with the following declaration inside a struct called ObjectData
func getData(id1:Int, id2:Int, completion: (dataObject? -> Void))
I am trying to call this function like
ObjectData.getData(1, id2: 2){
(let myObject) in
}
but i get the following error
Cannot invoke 'getData' with an argument list of type '(NSNumber, id2:
NSNumber, (_) -> _)'
Please can someone help
For better readability, change the header to this. Remember that you have to declare types, not variable names:
func getData(id1:Int, id2:Int, completion: (ObjectData?) -> (Void))
Now I personally use this syntax to use closures:
self.getData(1, id2: 1) { (data) -> (Void) in
// Some code executed in closure
}
If you want to study further, you can find full syntax of closures here (notice appropriate name of the website).
Hope it helps!
Far away from my Mac now, so I can't test, but try this:
ObjectData.getData(1, id2: 2, (dataObject) -> {
...code...
});
Also can't check now, but I think this also should work:
ObjectData.getData(1, id2: 2)(dataObject){
...code...
}
try to initialize your class first (ex. var objectData = ObjectData()) , and then call function with objectData.getData... it should work that way ..
In SWIFT 3,It is known as completion closure.
func getData(id1:Int, id2:Int, completion:#escaping(dataObject?) -> (Void)) {
//Do the stuff before calling completion closure
completion(value as? dataObject)
}
ObjectData.getData(id1:1, id2: 2,completion:{(data) -> (Void) in
//Do the completion stuff here
}

dispatch_async in Swift

I am really new to this programming language called swift.
I use
dispatch_async(dispatch_get_main_queue(), ^{
});
this method for async-dispatch-queue in xcode 5.
I want implement it in swift language.
how do i implement dispatch queue in or swift?
For those of you viewing this post three years later as I did, the Swift functions have been improved. Now you can write:
DispatchQueue.main.async(execute: { () -> Void in
// Your code here
})
You can use this syntax:
dispatch_async(dispatch_get_main_queue(), {
println("hello")
})
However, when the last argument is a block, Swift lets you put it outside the parentheses. This makes the function seem more like a control structure (like a for or if statement). Thus you can do this:
dispatch_async(dispatch_get_main_queue()) {
println("hello")
}
Xcode gives you an easy help with that....
Just type in
dispatch_async and hit enter... Than XCode gives you something like this...
dispatch_async(queue: dispatch_queue_t!, block: dispatch_block_t! () -> Void)
now take your mouse and double-click on block: dispatch_block_t! () -> Void and XCode will automatically change this to a working closure expression :-)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
//Your Code here
})