Closure trailing variable - swift

I have this closure as variable:
public var cellClicked: (name: String, number: Int)?
How can I make it a trailing closure, so I can do something like:
cell.cellClicked!{
(str: String, n: Int) in
}

What you have declared is tuple not the closure, If you want to make closure declared it like this.
public var cellClicked: ((String,Int) -> ())?
And make call like this
cell.cellClicked = { (name, value) in
}

SWIFT 3.0
Try this.
public var cellClicked = (String, Int) -> Void
cell.cellClicked = {(str,n) in
}

You can use as below :
func myMethod(completionHandler: #escaping (_ param : type, _ param2 : type) -> Void)
Description of #escaping -> https://cocoacasts.com/what-do-escaping-and-noescaping-mean-in-swift-3/

Related

Understand swift Dictionary syntax

I work with legacy code and i find following code:
let actions = [PrinterReportType.z: {
printer.printZReport($0)
DeviceFabric.lifehubTerminal().reconciliation()
}, .x: printer.printXReport, .openSession: printer.openSession}]
"Actions" is declared like this:
let actions: [PrinterReportsModel.PrinterReportType : ((String?) -> ()) -> ()]
Key is enum value, but i can't figure out what is value here.
I have new enum type of PrinterReportsModel.PrinterReportType, and i simply want to add new value to that dictionary. I suppose this is some kind of function. So, i want to declare that function, add it here, but i can't figure out how. And i can't figure out wha type is - ((String?) -> ()) -> ()
String is a collection of characters.
String? means the same as Optional<String>, so it is either Optional.none or Optional.some(String).
(String?) -> () is a function that takes a String? and returns nothing (() also called Void, the zero-element tuple). Let's call this as a String?-consumer: it takes a String? and does something with it. Maybe it just throws the String? away. Maybe it prints it. Maybe it stores the String? in a variable or a database or sends it over the network.
You could define a String?-consumer closure like this:
let action: (String?) -> () = { (_ s: String?) -> () in
print(s ?? "(none)")
}
(I'm fully specifying the types above, but you could omit some of the types and let the compiler infer them.)
You could define a String?-consumer function like this:
func test(_ s: String?) -> () { print(s ?? "(none)" }
And pass it around like this:
let action: (String?) -> () = test
You could define a String?-consumer method in a class (or struct) like this:
class MyObject {
func test(_ s: String?) -> () { print(s ?? "(none)") }
}
And pass it around like this:
let myObject = MyObject()
let action: (String?) -> () = myObject.test
((String?) -> ()) -> () is a function that takes a String?-consumer and returns nothing. You can think of this as a String?-consumer-consumer. Maybe it throws the String?-consumer away. Maybe it stores the String?-consumer in a variable for later. Maybe it calls the String?-consumer once, or ten times, or once for each element in some array of strings. Maybe it schedules a call to the String?-consumer every second until the program exits.
You could define a String?-consumer-consumer closure like this:
let action: ((String?) -> ()) -> () = { (_ sc: (String?) -> ()) -> () in
sc("hello")
sc(nil)
sc("world")
}
You could call the closure like this:
action({ (_ s: String?) -> () in print(s ?? "(none)")}
Or like this:
let printString: (String?) -> () = { print($0) }
action(printString)
You could define a String?-consumer-consumer function like this:
func test(_ sc: (String?) -> ()) -> () {
sc("hello")
sc(nil)
sc("world")
}
And pass it around like this:
let action: ((String?) -> ()) -> () = test
You could define a String?-consumer-consumer method in a class (or struct) like this:
class MyObject {
func test(_ sc: (String?) -> ()) -> () {
sc("hello")
sc(nil)
sc("world")
}
}
And pass it around like this:
let myObject = MyObject()
let action: ((String?) -> ()) -> () = myObject.test

Pass a closure in a function

I have a little experience in Swift and facing a problem to pass a closure in a function as a parameter.
//1.
public func changeMyStatus(to f:?, _ completion:#escaping (_ isSucced:Bool)->()){
//
}
//2.
func goLive(_ completion:#escaping (_ isSucced:Bool)->()){
}
//3.
func goNonLive(_ completion:#escaping (_ isSucced:Bool)->()){
}
Now , I want to use first function in my controller and wants to pass second/third function as a parameter. Closure in first will return true/false depending on what returned by closure in second/third.
i)What will be the type I should put in first function?
Also I want to call first function from my class like this
changeMyStatus(to: goNonLive) { (isSuccess) in
}
please help
You need to change the changeMyStatus function signature and implementation like:
public func changeMyStatus(to f: (#escaping (Bool) -> ()) -> () , _ completion:#escaping (_ isSucced:Bool)->()){
f { (status) in
completion(status)
}
}
You can call these function like:
// goLive
changeMyStatus(to: goLive(_:)) { (status) in
print(status)
}
// goNonLive
changeMyStatus(to: goNonLive(_:)) { (status) in
print(status)
}
Your second and third function has a completion parameter with a type of : (Bool -> Void) -> Void
So in order to pass it to your first function, try this way :
public func changeMyStatus(to f: ((Bool) -> ()), _ completion:#escaping (_ isSucced:Bool)->()) { // Your body}
In Swift, you need to see a function as a type like Int, Double, String...

Cannot convert value of type '(T) -> Void'

Example:
struct Wrapper<T> {
var key: Int = 0
var listeners: [Int: (T) -> Void] = Dictionary()
mutating func add(_ handler:#escaping (T) -> Void) {
self.key += 1
self.listeners[self.key] = handler
}
func get(key: Int) -> (T) -> Void {
return self.listeners[key]!
}
}
Test protocol:
protocol CommonProtocol {
}
Class that create Wrapper of test class
class C {
var wrapper: Wrapper = Wrapper<CommonProtocol>()
func add<T: CommonProtocol>(_ handler: #escaping (T) -> Void) {
self.wrapper.add(handler) //Cannot convert value of type '(T) -> Void' to expected argument type '(CommonProtocol) -> Void'
}
}
Image with error
I get error:
Cannot convert value of type '(T) -> Void' to expected argument type '(CommonProtocol) -> Void'
Question:
Why (T) -> Void can't be casted to (CommonProtocol) -> Void ? The T
is explicitly declared as <T: CommonProtocol>
This is my first question, if you have some suggestions please don't hesitate to contact me
You don't need to make func add generic.
When you specify in func add<T: CommonProtocol>... you explicitly telling the compiler that your function accepts all Types that inherit CommonProtocol but your Wrapper specifies that accepts CommonProtocol not inherited types.
Solution
Either type-erase class C:
Class C<T: CommonProtocol> {
var wrapper: Wrapper<T>
....
}
or if type T doesn't actually matter to you then:
func add(_ handler: #escaping (CommonProtocol) -> Void)
but second one doesn't make sense at all. You have to downcast it every-time you'll use this method (and downcasts are very bad :D)
Note: It's actually not related to this question, but one of your options is to type-erase the CommonProtocol too.

How to pass closure with argument as argument and execute it?

Initializer of class A takes an optional closure as argument:
class A {
var closure: ()?
init(closure: closure()?) {
self.closure = closure
self.closure()
}
}
I want to pass a function with an argument as the closure:
class B {
let a = A(closure: action(1)) // This throws the error: Cannot convert value of type '()' to expected argument type '(() -> Void)?'
func action(_ i: Int) {
//...
}
}
Class A should execute the closure action with argument i.
I am not sure about how to write this correctly, see error in code comment above. What has to be changed?
Please make your "what-you-have-now" code error free.
Assuming your class A like this:
class A {
typealias ClosureType = ()->Void
var closure: ClosureType?
init(closure: ClosureType?) {
self.closure = closure
//`closure` would be used later.
}
//To use the closure in class A
func someMethod() {
//call the closure
self.closure?()
}
}
With A given above, you need to rewrite your class B as:
class B {
private(set) var a: A!
init() {
//initialize all instance properties till here
a = A(closure: {[weak self] in self?.action(1)})
}
func action(i: Int) {
//...
}
}
The problem is that closure()? is not a type. And ()? is a type, but it is probably not the type you want.
If you want var closure to have as its value a certain kind of function, you need to use the type of that function in the declaration, e.g.
var closure: (Int) -> Void
Similarly, if you want init(closure:) to take as its parameter a certain kind of function, you need to use the type of that function in the declaration, e.g.
init(closure: (Int) -> Void) {
Types as Parameters
In Swift, every object has a type. For example, Int, String, etc. are likely all types you are extremely familiar with.
So when you declare a function, the explicit type (or sometimes protocols) of any parameters should be specified.
func swallowInt(number: Int) {}
Compound Types
Swift also has a concept of compound types. One example of this is Tuples. A Tuple is just a collection of other types.
let httpStatusCode: (Int, String) = (404, "Not Found")
A function could easily take a tuple as its argument:
func swallowStatusCode(statusCode: (Int, String)) {}
Another compound type is the function type. A function type consists of a tuple of parameters and a return type. So the swallowInt function from above would have the following function type: (Int) -> Void. Similarly, a function taking in an Int and a String and returning a Bool would have the following type: (Int, String) -> Bool.
Function Types As Parameters
So we can use these concepts to re-write function A:
class A {
var closure: (() -> Void)?
init(closure: (() -> Void)?) {
self.closure = closure
self.closure()
}
}
Passing an argument would then just be:
func foo(closure: (Int) -> Void) {
// Execute the closure
closure(1)
}
One way to do what I think you're attempting is with the following code:
class ViewController: UIViewController {
override func viewDidLoad() {
let _ = A.init(){Void in self.action(2)}
}
func action(i: Int) {
print(i)
}
}
class A: NSObject {
var closure : ()?
init(closure: (()->Void)? = nil) {
// Notice how this is executed before the closure
print("1")
// Make sure closure isn't nil
self.closure = closure?()
}
}

Swift - Overloading Static Methods

I have been trying to overload a static method for a public class in Swift 2.
How is that possible? This is similar to what I want to achieve:
static func test(message: String) -> Void)?) { ### }
static func test(message: String, number: Int) -> Void)?) { ### }
It's unclear what you're trying to do exactly, but there are two extra closing parenthesis. It looks like maybe you're trying to take a closure argument?
If the intent is to take a String argument in the first method (and a String & Int in the second) and return Void, then your syntax should look like this:
static func test(message: String) { /* implementation */ }
static func test(message: String, number: Int) { /* implementation */ }
However, if the intent is to take an optional closure which takes a String and returns nothing, then the syntax looks like this:
static func test(closure: ((String) -> Void)?) {
// implementation
}
And then if the closure also takes an Int:
static func test(closure: ((String, Int) -> Void)?) {
// implementation
}