How can i make protocol implementation as argument of function - swift

How do i create Protocol as an argument of function.
In Android java, we can make an argument of interface like this.
Button.setOnClickListener(new View.OnClicklistener()
{
#Override
public void onClick(View v)
{
}
});
But how do i do same thing in Swift.
For example, i have following Protocol, how can i pass protocol while constructing it.
protocol ButtonListener
{
func onClick()
}

It seems that there is a misunderstanding for what you should use to achieve it. Probably you want to pass a closure as a parameter to the function.
Citing from the Swift programming language - Closures:
Closures are self-contained blocks of functionality that can be passed
around and used in your code. Closures in Swift are similar to blocks
in C and Objective-C and to lambdas in other programming languages.
Example:
protocol Foo {
func myFunc(onClick: (_ myView: UIView) -> Void)
}
class MyClass: Foo {
func myFunc(onClick: (UIView) -> Void) {
// ...
}
}
Here we have a Foo protocol contains myFunc which has a closure parameter of type (UIView) -> Void.
Therefore:
let object = MyClass()
object.myFunc { view in
// you can access `view` here as:
view.backgroundColor = ...
view.frame = ...
}

In Swift, these single-method protocols, as event handlers are not necessary. In Swift, you can create any kind of closure type you want.
Your onClick method can be represented by the closure type () -> Void (accepts no parameters and returns Void). Instead of setOnClickListener as a method, you can just declare onClick as a property:
var onClick: (() -> Void)?
And then you can set it just like you would with any other property:
onClick = {
print("I am clicked!")
}
To call onClick, you can unwrap it first to make sure it's not nil:
if let onClick = self.onClick {
onClick()
}
// or
onClick?()
If you are familiar Java 8, closure types are kind of like functional interfaces, except you get more freedom with closure types. Consumer<String> would correspond to (String) -> Void, Function<String, Integer> would correspond to (String) -> Int, etc.

You can give it by protocol.
protocol ButtonListener {}
extension ButtonListener where Self: UIView {
func btnClick() {
// print func
}
}

Related

Why is declaring self not required in structures where it's required in classes?

Why is declaring self not required in structures where it's required in classes? I don't know if there are other examples where this is the case but with escaping closures, it is. If the closure is non-optional (and thus non-escaping), there is no requirement to declare self in either of the two.
class SomeClass {
let someProperty = 1
func someMethod(completion: (() -> Void)?) {}
func anotherMethod() {
someMethod {
print(self.someProperty) // declaring self is required
}
}
}
struct SomeStruct {
let someProperty = 1
func someMethod(completion: (() -> Void)?) {}
func anotherMethod() {
someMethod {
print(someProperty) // declaring self is not required
}
}
}
The purpose of including self when using properties inside an escaping closure (whether optional closure or one explicitly marked as #escaping) with reference types is to make the capture semantics explicit. As the compiler warns us if we remove self reference:
Reference to property 'someProperty' in closure requires explicit use of 'self' to make capture semantics explicit.
But there are no ambiguous capture semantics with structs. You are always dealing with a copy inside the escaping closure. It is only ambiguous with reference types, where you need self to make clear where the strong reference cycle might be introduced, which instance you are referencing, etc.
By the way, with class types, referencing self in conjunction with the property is not the only way to make the capture semantics explicit. For example, you can make your intent explicit with a “capture list”, either:
Capture the property only:
class SomeClass {
var someProperty = 1
func someMethod(completion: #escaping () -> Void) { ... }
func anotherMethod() {
someMethod { [someProperty] in // this captures the property, but not `self`
print(someProperty)
}
}
}
Or capture self:
class SomeClass {
var someProperty = 1
func someMethod(completion: #escaping () -> Void) { ... }
func anotherMethod() {
someMethod { [self] in // this explicitly captures `self`
print(someProperty)
}
}
}
Both of these approaches also make it explicit what you are capturing.
For classes, closures provide a mechanism to increment a reference count, thus "keeping the object alive".
Maybe you're okay with just capturing someProperty. Maybe not! The compiler doesn't know if you're using a closure in order to increment the reference, so it makes you be explicit about your intentions.
Not only is that a non-issue with structs, but so is the possibility of mutation, which is strictly disallowed.
Let's say you wanted anotherMethod to allow mutation of any kind, in a struct. You could start by marking it as mutating…
struct SomeStruct {
func someMethod(completion: (() -> Void)?) {}
mutating func anotherMethod() {
someMethod {
self
}
}
}
…but no, that's an error:
Escaping closure captures mutating 'self' parameter
Capture self, though…
mutating func anotherMethod() {
someMethod { [self] in
self
}
}
…and that's fine.
And it's also the only option Swift allows. When you use an escaping closure from within a struct, you can only use an immutable capture of an instance. i.e. [self] in is implicit, for nonmutating methods.
This can yield unexpected results. Be careful.
struct SomeStruct {
var someProperty = 1
func anotherMethod() {
DispatchQueue.global().asyncAfter(deadline: .now() + 1) {
print(someProperty)
}
}
}
var s = SomeStruct()
s.anotherMethod() // 1, even though it's printed after the following reassignment
s.someProperty = 2
s.anotherMethod() // 2
I think it helps to think about what method syntax is shorthand for.
s.anotherMethod()
is really
SomeStruct.anotherMethod(s)()
You can visualize the immutability there, because there's no &.

Swift 3: Inheritance from non-named type

I have the following SSCIE:
protocol Foo {
associatedtype Bar
associatedtype Baz: (Self.Bar) -> Void
var currentValue: Bar { get }
}
That I want to use like this:
func call<T: Foo>(foo: T, callback: #escaping T.Baz) {
DispatchQueue.main.async {
callback(foo.currentValue)
}
}
But it fails to compile, with the error:
Inheritance from non-named type '(`Self`.Bar)'
This also fails to compile when I use (Bar) -> Void and (Foo.Bar) -> Void.
Sadly, Googling this didn't come up with any useful results.
Does anyone have any idea what this error means, what I'm doing wrong, and how to correct it?
Associated types in Swift 3 can only be "is-a"-constrained. So your Bar is required to be an Any. Which, by the way, is not much of a constraint ;). In other words, you can remove it.
However, (Self.Bar) -> Void is a function type and you can't constrain an associated type like this.
If you want to define a callback type, you can use a typealias:
protocol Foo
{
associatedtype Bar
typealias Callback = (Self.Bar) -> Void
var currentValue: Bar { get }
func f(callback: Callback) -> Void
}
Using #escaping does not currently work in a typealias (see SR-2316 and its various duplicates). This is a bug that was supposed to have a fix soon (as of August 2016). So you will have to spell it out for now:
func call<T: Foo>(foo: T, callback: #escaping (T.Bar) -> Void) {
DispatchQueue.main.async {
callback(foo.currentValue)
}
}
Update: As Hamish suggested, I filed SR-4967. I'll update this post as soon as there is any news about it.
As already mentioned, function types can't be used as associated types.
Try this instead:
func call<T: Foo>(foo: T, callback: #escaping (T.Bar) -> Void) {
...
}
and using this design you can mix-and-match function types (for the callback arg) for each specific helper function (call in your example) you come up with.

Swift: Generic Protocols

I have some swift structs for which protocol compliance is generated with individual extensions with equal methods names which just differ in their return types which are struct dependent. On top of That I want to use them in a generic function which Calls a protocol conforming function for a generic type).
I tried to accomplish this like that:
//: Playground - noun: a place where people can play
import UIKit
protocol FooProt {
typealias T;
static func createMe<T>()->T;
}
struct FooStruct{
}
extension FooStruct: FooProt{
typealias T = FooStruct;
static func createMe () -> FooStruct{
return FooStruct();
}
}
class Creator{
fun createOne<T where T:FooProt>(type:T.Type){
let instance = T.createMe();
}
}
Unfortunately I get the following error :
/var/folders/sn/78_zvfd15d74dzn01mdv258h0000gq/T/./lldb/3741/playground6.swift:7 :17: note: protocol requires function 'createMe()' with type ' () -> T' (aka '<τ_1_0> () -> τ_1_0')
static func createMe()->T;
What exactly doesn't comply here and is there a workaround ?
There are several problems with your code. On the one hand you have defined a protocol with an associated type. However, you define your createMe() method as a generic which uses some other type. I don't think that was your intent. I think your intent was to have a createMe() method that returns the same type as the protocol's associated type. In this case you need to remove the from the createMe() method. Also, the name createMe() implies that you aren't just returning any type, but the type of the object on which this method is being called. In this case, you don't even need an associated type protocol. You just need a protocol with a Self constraint which allows your code to be a bit simpler. In your Creator's createOne method, your type constraint is more complex than needed.
I think you want the following code:
protocol FooProt {
static func createMe()->Self;
}
struct FooStruct{
}
extension FooStruct: FooProt {
static func createMe() -> FooStruct {
return FooStruct();
}
}
class Creator{
func createOne<T:FooProt>(type: T.Type) -> T {
return T.createMe()
}
}
let foo = Creator().createOne(FooStruct.self)
Here is an alternate solution using an initializer in the protocol instead of a static method.
protocol FooProt {
init()
}
struct FooStruct{
}
extension FooStruct: FooProt {
}
class Creator{
func createOne<T:FooProt>(type: T.Type) -> T {
return T.init()
}
}
let foo = Creator().createOne(FooStruct.self)

Wrapping a callback type with Swift protocols

Let's say I'm dealing with a library I don't control and I'm trying to wrap a class that defines a callback type to decouple my code for testing purposes. Here's the class, inside module AXSwift:
public class Application {
public typealias Callback = (element: UIElement) -> ()
public func createObserver(callback: Callback) -> Observer? {
// ...
}
}
Here's the wrapper protocol for testing:
protocol UIElementProtocol {}
extension AXSwift.UIElement: UIElementProtocol {}
protocol ApplicationProtocol {
func createObserver(callback: (element: UIElementProtocol) -> ()) -> Observer?
}
extension AXSwift.Application: ApplicationProtocol {}
I get Type 'Application' does not conform to protocol 'ApplicationProtocol'. If I change UIElementProtocol inside the ApplicationProtocol callback back to UIElement, it works. But UIElement conforms to UIElementProtocol, so why doesn't this work?
Second question: Is there a better way to design the library API to allow for this sort of thing?
The solution was really simple, just implement the protocol in the extension with a method that calls the original method:
extension AXSwift.Application: ApplicationProtocol {
func createObserver(callback: (element: UIElementProtocol) -> ()) -> Observer? {
return createObserver(callback as Callback)
}
}
Where Callback is the expected type. Apparently you have to be explicit about passing a general function type as a more specific type.

How to define a function with a function type parameter in Swift

I could define a function like this
func doWithAction(action: ()-> void) {
// something
}
However, when I use the function, the auto-completion of Xcode give me a block/closure
self.addPullToRefreshControllerWithAction { () -> void in
}
I know closure and function are something same in Swift, but I want to lead the one who use this function to pass a function in, not a block. The reason why I do this is I want this function to behave like a selector and a delegation
yes, closure and functions are practically the same in swift, so if the function expects a closure, you can pass a function with the same signature as a parameter instead. like this
func iAmAFunc(() -> Void) -> Void {
//do stuff
}
func funcThatTakesVoidAndReturnsVoid() -> Void {
//do stuff
}
var closureThatTakesVoidAndReturnsVoid: () -> Void = { }
iAmAFunc(funcThatTakesVoidAndReturnsVoid)
iAmAFunc(closureThatTakesVoidAndReturnsVoid)