Swift Generic function call another Generic function - ios

I am using Swift 2.2 on XCode 7.3.1 and trying to call a Generic function from another Generic function.
Code
class Thing1 {
let variable: SomeProtocol
init<A: SomeProtocol>(variable: A) {
self.variable = variable
self.add1(self.variable)
}
func add1<A: SomeProtocol>(stuff: A) {
let thing: Thing2 = Thing2()
thing.add2(stuff)
}
}
class Thing2 {
func add2<A: SomeProtocol>(stuff: A) {
}
}
protocol SomeProtocol { }
add1("a") // Cannot invoke 'add1' with an argument list of type '(String)'
add1(4) // Cannot invoke 'add1' with an argument list of type '(Int)'
I get the error.
'Cannot invoke add with an argument of list type '(Whatever type I used to call the function)''

The problem is that abstract types in Swift don't necessarily conform to themselves – therefore you cannot use a SomeProtocol typed thing as a concrete typed thing that conforms to SomeProtocol (which is what your add1 generic function expects as an argument).
The simplest solution in your case therefore is just to use the generic variable argument, rather than the variable property, as because it's a generic, it's typed as a concrete thing that conforms to SomeProtocol, which can therefore be passed into your add1 function:
init<A: SomeProtocol>(variable: A) {
self.variable = variable
add1(variable)
}
However in order to prevent these kind of issues later down the line, you may want to consider making your class generic, assuming that your variable property should be of constant type throughout the lifetime of a given Thing1 instance:
class Thing1<A:SomeProtocol> {
let variable: A
init(variable: A) {
self.variable = variable
add1(variable)
}
func add1(stuff: A) {
let thing = Thing2()
thing.add2(stuff)
}
}
Or, you could refactor your code to use the abstract type SomeProtocol, which will allow you to work with any type that conforms to SomeProtocol (e.g allowing you to mix different Thing1 instances with different variable types in an array):
class Thing1 {
let variable: SomeProtocol
init(variable: SomeProtocol) {
self.variable = variable
add1(variable)
}
func add1(stuff: SomeProtocol) {
let thing = Thing2()
thing.add2(stuff)
}
}
class Thing2 {
func add2(stuff: SomeProtocol) {
}
}
Although you should always be aware of the extra costs that come with using abstract types, see this great WWDC talk for more info.

Adding the extensions to String and Int and constructing Thing1 objects makes it work:
extension String: SomeProtocol{}
extension Int: SomeProtocol{}
Thing1(variable: "a").add1("a")
Thing1(variable: 2).add1(4)

Related

Why can't I use a Color as a ShapeStyle? [duplicate]

I have a generic class that I want to be able to use with a default type. Right now I can initialize it with any type, but I have to be explicit.
//Initialize with a type
MyManager<MyCustomerObject>()
// Initialize with NSObject (what I want to be my default type)
MyManager<NSObject>()
// This doesn't work, but I want this kind of functionality
class MyManager<T = NSObject> {}
// So I can create my manager like so and it inserts the default type as NSObject
MyManager() //Or MyManager<>()
Is this possible in Swift?
There's no support for default generic arguments, but you can fake it by defining the default init() on a type-constrained extension, in which case the compiler will be smart enough to use that type. E.g.:
class MyManager<T> {
let instance: T
init(instance: T) {
self.instance = instance
}
}
extension MyManager where T == NSObject {
convenience init() {
self.init(instance: NSObject())
}
}
And now you can initialize the type with no argument and it will default to MyManager<NSObject>:
let mm1 = MyManager(instance: "Foo") // MyManager<String>
let mm2 = MyManager(instance: 1) // MyManager<Int>
let mm3 = MyManager() // MyManager<NSObject>
SwiftUI uses this technique quite a lot.
No, this currently isn't possible – although it is a part of the Generics Manifesto, so might be something that the Swift team will consider for a future version of the language.
Default generic arguments
Generic parameters could be given the ability to provide default
arguments, which would be used in cases where the type argument is not
specified and type inference could not determine the type argument.
For example:
public final class Promise<Value, Reason=Error> { ... }
func getRandomPromise() -> Promise<Int, Error> { ... }
var p1: Promise<Int> = ...
var p2: Promise<Int, Error> = p1 // okay: p1 and p2 have the same type Promise<Int, Error>
var p3: Promise = getRandomPromise() // p3 has type Promise<Int, Error> due to type inference
In the meantime however, a somewhat unsatisfactory compromise would be the use of a typealias:
class MyManager<T> {}
typealias MyManagerDefault = MyManager<NSObject>
let defaultManager = MyManagerDefault()
Not nearly as slick as just being able to say MyManager(), but it does show up next to MyManager in auto-complete, which is pretty handy.
If T is always a NSObject subclass, you can use a generic constraint in Swift 5.3:
class MyManager<T: NSObject> {
let t = T()
}
class MyCustomerObject: NSObject { }
let a = MyManager()
let b = MyManager<MyCustomerObject>()

Swift: Protocol and Base Class with same function name

So I was just playing with the protocols and just got confused with the following behaviour.
I have a protocol with the function and a base class with the same function name. Now, another class is inheriting from a base class and implementing a protocol. But it is not producing error in some scenarios.
For example:
protocol P {
func greetings()
}
class Base {
func greetings() {
print("Hello Base")
}
}
class A: Base {
override func greetings() {
print("Hello Class")
}
}
extension A: P {
}
let a = A()
print(a.greetings()) // print: Hello Class
let b:Base = A()
print(b.greetings()) // print: Hello Class
let p:P = A()
print(p.greetings()) // print: Hello Class
So, how is the conformance of the class to the protocol happening?
Also in the following case, when protocol function has default implementation, it compiles without any error and always opt from base class function.
protocol P {
func greetings()
}
extension P {
func greetings() {
print("Hello Protocol")
}
}
class Base {
func greetings() {
print("Hello Base")
}
}
class A: Base {
}
extension A: P {
}
let a = A()
print(a.greetings()) // print: Hello Base
let b:Base = A()
print(b.greetings()) // print: Hello Base
let p:P = A()
print(p.greetings()) // print: Hello Base
Why it always opt for a base class function? And Why no compile time error because of ambiguous function call?
The type of the variable you assign an object to does not control how functions are dispatched on that object. When looking for a function, the computer starts at the object and walks "up" through the class hierarchy looking for an implementation. ie. It starts at A and if it doesn't find a function, it goes up to Base (A's superclass) and looks there. If still not found it goes up to the next superclass (which there isn't one in this case). If the function isn't found then you get an error.
In your first example you have an instance of A and A overrides the base greetings so that is that implementation that will always be used. This is related to an important concept in Object Oriented Programming - Substitutability.
In this case you can declare a variable of type Base but assign an instance of a more specialised class - A, but the program still operates correctly.
Remember that type inference as shown in your first assignment (let a = A()) is not present in all languages. In many cases you need to explicitly declare a variable's type. If declaring a variable of type Base meant that the Base function was called instead of subclass, it would defeat the purpose of subclassing.
With regard to your question
how is the conformance of the class to the protocol happening?
A protocol is a specification but not an implementation (we will look at your question around default implementations next). Your protocol says that all things that conform to P must provide a greeting function. Clearly both Base and A provide a greeting function. Your extension merely adds the stipulation that A conforms to P. It doesn't need to add the implementation of P because the greeting method already exists.
If you removed the extension A: P then let p:P = A() would give an error because the compiler no longer knows that A conforms to P.
This brings us to your last two questions:
Why it always opt for a base class function?
And Why no compile time error because of ambiguous function call?
From The Swift Programming Language
You can use protocol extensions to provide a default implementation to any method or computed property requirement of that protocol. If a conforming type provides its own implementation of a required method or property, that implementation will be used instead of the one provided by the extension.
In your second example block, A doesn't override the Base implementation of greeting, so the Base implementation is always called.
The default implementation of greeting that you added to P will only be used in the case where a class that conforms to P doesn't provide an implementation.
Default implementations can make it easier to conform to a protocol by supplying implementation where there is some behaviour that will apply to all or a majority of cases. Default implementations are always ignored if the conforming class provides an implementation
Consider the following example:
Protocol Vehicle {
func soundHorn()
var numberOfDoors: Int
}
extension Vehicle {
func soundHorn() {
print("Beep")
}
}
class SportsCar: Vehicle {
var numberOfDoors: Int {
return 2
}
}
class Sedan: Vehicle {
var numberOfDoors: Int {
return 4
}
}
class Truck: Vehicle {
var numberOfDoors: Int {
return 2
}
func soundHorn() {
print("**HONK**")
}
}
Here we have defined a simple protocol, Vehicle, that says that a Vehicle has a number of doors and can sound its horn. We provided a default soundHorn that prints "Beep". We then declared classes that implement this protocol. The two different types of car have different numbers of doors but we are happy with the default horn. For a Truck we have a bigger, louder horn, so we implement soundHorn rather than using the default:
var v: Vehicle = SportsCar()
v.soundHorn() // Prints "beep"
v = Truck()
v.soundHorn() // Prints "**HONK**"
Note how v is of type Vehicle but we get the correct horn based on the object that is actually assigned to v. The compiler is happy because it knows that all Vehicles can soundHorn; it doesn't need to know the specific vehicle type.

How to use generic protocol as a variable type

Let's say I have a protocol :
public protocol Printable {
typealias T
func Print(val:T)
}
And here is the implementation
class Printer<T> : Printable {
func Print(val: T) {
println(val)
}
}
My expectation was that I must be able to use Printable variable to print values like this :
let p:Printable = Printer<Int>()
p.Print(67)
Compiler is complaining with this error :
"protocol 'Printable' can only be used as a generic constraint because
it has Self or associated type requirements"
Am I doing something wrong ? Anyway to fix this ?
**EDIT :** Adding similar code that works in C#
public interface IPrintable<T>
{
void Print(T val);
}
public class Printer<T> : IPrintable<T>
{
public void Print(T val)
{
Console.WriteLine(val);
}
}
//.... inside Main
.....
IPrintable<int> p = new Printer<int>();
p.Print(67)
EDIT 2: Real world example of what I want. Note that this will not compile, but presents what I want to achieve.
protocol Printable
{
func Print()
}
protocol CollectionType<T where T:Printable> : SequenceType
{
.....
/// here goes implementation
.....
}
public class Collection<T where T:Printable> : CollectionType<T>
{
......
}
let col:CollectionType<Int> = SomeFunctiionThatReturnsIntCollection()
for item in col {
item.Print()
}
As Thomas points out, you can declare your variable by not giving a type at all (or you could explicitly give it as type Printer<Int>. But here's an explanation of why you can't have a type of the Printable protocol.
You can't treat protocols with associated types like regular protocols and declare them as standalone variable types. To think about why, consider this scenario. Suppose you declared a protocol for storing some arbitrary type and then fetching it back:
// a general protocol that allows for storing and retrieving
// a specific type (as defined by a Stored typealias
protocol StoringType {
typealias Stored
init(_ value: Stored)
func getStored() -> Stored
}
// An implementation that stores Ints
struct IntStorer: StoringType {
typealias Stored = Int
private let _stored: Int
init(_ value: Int) { _stored = value }
func getStored() -> Int { return _stored }
}
// An implementation that stores Strings
struct StringStorer: StoringType {
typealias Stored = String
private let _stored: String
init(_ value: String) { _stored = value }
func getStored() -> String { return _stored }
}
let intStorer = IntStorer(5)
intStorer.getStored() // returns 5
let stringStorer = StringStorer("five")
stringStorer.getStored() // returns "five"
OK, so far so good.
Now, the main reason you would have a type of a variable be a protocol a type implements, rather than the actual type, is so that you can assign different kinds of object that all conform to that protocol to the same variable, and get polymorphic behavior at runtime depending on what the object actually is.
But you can't do this if the protocol has an associated type. How would the following code work in practice?
// as you've seen this won't compile because
// StoringType has an associated type.
// randomly assign either a string or int storer to someStorer:
var someStorer: StoringType =
arc4random()%2 == 0 ? intStorer : stringStorer
let x = someStorer.getStored()
In the above code, what would the type of x be? An Int? Or a String? In Swift, all types must be fixed at compile time. A function cannot dynamically shift from returning one type to another based on factors determined at runtime.
Instead, you can only use StoredType as a generic constraint. Suppose you wanted to print out any kind of stored type. You could write a function like this:
func printStoredValue<S: StoringType>(storer: S) {
let x = storer.getStored()
println(x)
}
printStoredValue(intStorer)
printStoredValue(stringStorer)
This is OK, because at compile time, it's as if the compiler writes out two versions of printStoredValue: one for Ints, and one for Strings. Within those two versions, x is known to be of a specific type.
There is one more solution that hasn't been mentioned on this question, which is using a technique called type erasure. To achieve an abstract interface for a generic protocol, create a class or struct that wraps an object or struct that conforms to the protocol. The wrapper class, usually named 'Any{protocol name}', itself conforms to the protocol and implements its functions by forwarding all calls to the internal object. Try the example below in a playground:
import Foundation
public protocol Printer {
typealias T
func print(val:T)
}
struct AnyPrinter<U>: Printer {
typealias T = U
private let _print: U -> ()
init<Base: Printer where Base.T == U>(base : Base) {
_print = base.print
}
func print(val: T) {
_print(val)
}
}
struct NSLogger<U>: Printer {
typealias T = U
func print(val: T) {
NSLog("\(val)")
}
}
let nsLogger = NSLogger<Int>()
let printer = AnyPrinter(base: nsLogger)
printer.print(5) // prints 5
The type of printer is known to be AnyPrinter<Int> and can be used to abstract any possible implementation of the Printer protocol. While AnyPrinter is not technically abstract, it's implementation is just a fall through to a real implementing type, and can be used to decouple implementing types from the types using them.
One thing to note is that AnyPrinter does not have to explicitly retain the base instance. In fact, we can't since we can't declare AnyPrinter to have a Printer<T> property. Instead, we get a function pointer _print to base's print function. Calling base.print without invoking it returns a function where base is curried as the self variable, and is thusly retained for future invocations.
Another thing to keep in mind is that this solution is essentially another layer of dynamic dispatch which means a slight hit on performance. Also, the type erasing instance requires extra memory on top of the underlying instance. For these reasons, type erasure is not a cost free abstraction.
Obviously there is some work to set up type erasure, but it can be very useful if generic protocol abstraction is needed. This pattern is found in the swift standard library with types like AnySequence. Further reading: http://robnapier.net/erasure
BONUS:
If you decide you want to inject the same implementation of Printer everywhere, you can provide a convenience initializer for AnyPrinter which injects that type.
extension AnyPrinter {
convenience init() {
let nsLogger = NSLogger<T>()
self.init(base: nsLogger)
}
}
let printer = AnyPrinter<Int>()
printer.print(10) //prints 10 with NSLog
This can be an easy and DRY way to express dependency injections for protocols that you use across your app.
Addressing your updated use case:
(btw Printable is already a standard Swift protocol so you’d probably want to pick a different name to avoid confusion)
To enforce specific restrictions on protocol implementors, you can constrain the protocol's typealias. So to create your protocol collection that requires the elements to be printable:
// because of how how collections are structured in the Swift std lib,
// you’d first need to create a PrintableGeneratorType, which would be
// a constrained version of GeneratorType
protocol PrintableGeneratorType: GeneratorType {
// require elements to be printable:
typealias Element: Printable
}
// then have the collection require a printable generator
protocol PrintableCollectionType: CollectionType {
typealias Generator: PrintableGenerator
}
Now if you wanted to implement a collection that could only contain printable elements:
struct MyPrintableCollection<T: Printable>: PrintableCollectionType {
typealias Generator = IndexingGenerator<T>
// etc...
}
However, this is probably of little actual utility, since you can’t constrain existing Swift collection structs like that, only ones you implement.
Instead, you should create generic functions that constrain their input to collections containing printable elements.
func printCollection
<C: CollectionType where C.Generator.Element: Printable>
(source: C) {
for x in source {
x.print()
}
}

What is "self" used for in Swift?

I am new to Swift and I'm wondering what self is used for and why.
I have seen it in classes and structures but I really don't find them essential nor necessary to even mention them in my code. What are they used for and why? In what situations it's necessary to use it?
I have been reading lots of questions and answers for this question but none of them fully answers my questions and they always tend to compare it with this as in Java, with which I'm not familiar whatsoever.
Yes it is the same as this in Java and self in Objective-C, but with Swift, self is only required when you call a property or method from a closure or to differentiate property names inside your code, such as initializers. So you can use almost all of your class components safely without using self unless you are making the call from a closure.
“The self Property Every instance of a type has an implicit property
called self, which is exactly equivalent to the instance itself. You
use the self property to refer to the current instance within its
own instance methods.
The increment() method in the example above could have been written
like this:
func increment() {
self.count += 1
}
In practice, you don’t need to write self in your code very often.
If you don’t explicitly write self, Swift assumes that you are
referring to a property or method of the current instance whenever you
use a known property or method name within a method. This assumption
is demonstrated by the use of count (rather than self.count)
inside the three instance methods for Counter.
The main exception to this rule occurs when a parameter name for an
instance method has the same name as a property of that instance. In
this situation, the parameter name takes precedence, and it becomes
necessary to refer to the property in a more qualified way. You use
the self property to distinguish between the parameter name and the
property name.
Here, self disambiguates between a method parameter called x and
an instance property that is also called x:”
Excerpt From: Apple Inc. “The Swift Programming Language (Swift 2 Prerelease).”
This is how Ray Wenderlich recommends the use of self in Swift for their tutorials:
Use of Self
For conciseness, avoid using self since Swift does not require it to access an object's properties or invoke its methods.
Use self when required to differentiate between property names and arguments in initializers, and when referencing properties in closure expressions as required by the compiler:
class BoardLocation {
let row: Int, column: Int
init(row: Int, column: Int) {
self.row = row
self.column = column
let closure = {
println(self.row)
}
}
}
And this is GitHub's recommendations on self for their applications:
Only explicitly refer to self when required
When accessing properties or methods on self, leave the reference to self implicit by default:
private class History {
var events: [Event]
func rewrite() {
events = []
}
}
Only include the explicit keyword when required by the language — for example, in a closure, or when parameter names conflict:
extension History {
init(events: [Event]) {
self.events = events
}
var whenVictorious: () -> () {
return {
self.rewrite()
}
}
}
Rationale: This makes the capturing semantics of self stand out more in closures, and avoids verbosity elsewhere.
You will also use self a lot when creating your extensions, example:
extension Int {
func square() -> Int {
return self * self
}
// note: when adding mutating in front of it we don't need to specify the return type
// and instead of "return " whatever
// we have to use "self = " whatever
mutating func squareMe() {
self = self * self
}
}
let x = 3
let y = x.square()
println(x) // 3
printlx(y) // 9
now let's say you want to change the var result itself
you have to use the mutating func to make change itself
var z = 3
println(z) // 3
now let's mutate it
z.squareMe()
println(z) // 9
// now let's see another example using strings :
extension String {
func x(times:Int) -> String {
var result = ""
if times > 0 {
for index in 1...times{
result += self
}
return result
}
return ""
}
// note: when adding mutating in front of it we don't need to specify the return type
// and instead of "return " whatever
// we have to use "self = " whatever
mutating func replicateMe(times:Int){
if times > 1 {
let myString = self
for index in 1...times-1{
self = self + myString
}
} else {
if times != 1 {
self = ""
}
}
}
}
var myString1 = "Abc"
let myString2 = myString1.x(2)
println(myString1) // "Abc"
println(myString2) // "AbcAbc"
now let's change myString1
myString1.replicateMe(3)
println(myString1) // "AbcAbcAbc"
In what situations it's necessary to use it
It is necessary to use it only when the name of a local variable overshadows the name of a property.
However, as a matter of style (and readability), I always use it:
I use it with property names, because otherwise I am left wondering what this variable is (since it is neither locally declared nor an incoming parameter).
I use it as the receiver of function (method) calls, in order to differentiate such methods from top-level or local functions.
This is why we need self.
When we define a class, like:
class MyClass {
func myMethod()
}
We are creating a "Class Object". Yes, Class is an object too.
Then no matter how many instances are created using the class, all instances will have a reference pointer to its Class Object.
You can imagine that all instance methods defined by the Class are in the Class Object, and there will be only one copy of them.
That means all instances created using the Class are sharing the same method.
Now imagine you are the myMethod in the Class Object, and because you are shared for all instances, you must have a way to tell which instance you are working on.
When someone says instance1.myMethod(), it means "Hi! myMethod, please do your work and instance1 is the object you are working on".
To reference the object that the caller sent to you, use self.
“In practice, you don’t need to write self in your code very often. If
you don’t explicitly write self, Swift assumes that you are referring
to a property or method of the current instance whenever you use a
known property or method name within a method.”
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks.
https://itun.es/tw/jEUH0.l
The reserved word self in Swift is similar to this but it's not the same as in Java or JavaScript.
As #Dave Gomez correctly quoted:
Every instance of a type has an implicit property called self, which is exactly equivalent to the instance itself.
Here lies one of the main differences, because:
"Every instance" in Swift (at least for now) is almost every-thing.
In Java, for example, you can only use the word this inside an instance scope, in Swift you can use it almost every-where.
Here are a few examples:
//Example 1:
var x="foo"
x.self="bar".self//compiles and run
//Example 2:
print.self(x);//compiles and run
//Example 3:
func myOther(self otherSelf:Person){}
myOther(self: personObject);//compiles and run
//Example 4:
class Foo{
var bar=""
init(){
self.addSome()//this would be the same in Java
}
func addSome(){
//But definitely not this:
self.self.bar.self.self="some".self.self
}
}
//Guess what - also compiles and run...
let f=Foo()
print(f.bar)
See : Why 'self.self' compiles and run in swift for more information.
I arrived at this question while searching for self as a class function, which looks like this: Int.self, String.self, or YourClass.self
Previously, as near as I can tell, only Dmitri Pavlutin's answer touches on this, when he said:
When self is accessed in a type method (static func or class func), it refers to the actual type (rather than an instance).
When self is used this way, it actually returns what in Swift is called a Metatype. You can read the Swift documentation page on Types for more information.
There is also an article with more details about using and understanding metatypes called "What's .self, .Type and .Protocol? Understanding Swift Metatypes" on swiftrocks.com.
"How to use correctly 'self' keyword in Swift" explains self in detail.
self is a property on the instance that refers to itself. It's used to access class, structure and enumeration instance within methods.
When self is accessed in a type method like static func or class func, it refers to the actual type rather than an instance.
Swift allows omitting self when you want to access instances properties.
When a method parameter has the same name as an instance property, you have to explicitly use self.myVariable = myVariable to make a distinction.
Notice that method parameters have a priority over instance properties.
I'm a total noob at coding in general - and whilst these answers are great, from the perspective of a total noob who just wants it answered as practically as possible without all these difficult words and concepts, here's my Super Noob dumbed down version:
'self' is used because the coding application doesn't know which variable to use if you type the variable in the scope of your functions. It's all about the scope and making it clear which variable you're using if some other variable has the same name. Scope is the area inside the curly {} brackets. so for example:
{ scope1 {scope2} }
Here you don't need to use self:
class example {
private var exampleVar = “this is the class scope variable”
func x() {
//You don't have to use self here
print(exampleVar)
}
}
Here you do need to use self:
class example {
private var exampleVar = “this is the class scope variable”
func x(_ exampleVar: String) {
//It would be confusing which exampleVar is used here so you should use self
print(exampleVar)
print(self.exampleVar)
}
}
There's also this situation:
class example {
private var exampleVar = “this is the class scope variable”
func x() {
randomMethod { _ in
//This is not the class scope here, so we need to use self here.
//You will be flagged during build time of this if you don't use self.
print(self.exampleValue)
}
}
}
self is a property on the instance that refers to itself. It's used to access the class, structure and enumeration instance within methods.
When a method parameter has the same name as an instance property, you have to explicitly use self.myVariable = myVariable to make a distinction.
Notice that method parameters have a priority over instance properties.
struct Weather {
let windSpeed: Int
let chanceOfRain: Int
init(windSpeed: Int, chanceOfRain: Int) {
self.windSpeed = windSpeed
self.chanceOfRain = chanceOfRain
}
func isDayForWalk() -> Bool {
let comfortableWindSpeed = 5
let acceptableChanceOfRain = 30
return self.windSpeed <= comfortableWindSpeed
&& self.chanceOfRain <= acceptableChanceOfRain
}
}
// A nice day for a walk
let niceWeather = Weather(windSpeed: 4, chanceOfRain: 25)
print(niceWeather.isDayForWalk()) // => true
I have an elegant case for using self in Swift. I use it in blocks like this:
class MyBase {
private var baseValue: Int = 100
var block: ((Int)->())? = nil
func baseMethod(anotherValue: Int) {
guard let b = block else { return }
b(baseValue + anotherValue)
}
...
}
class MyClass {
init()
{
// Define base class block.
// This may hold self in block causing memory leaks
// if self is a strong reference
block = {
// indicate self is a weak reference
[weak self] (para) in
// guaranty self existence
guard let this = self else {return}
let value = this.value1 + para
// this call passes value to other obj's method
this.obj.method(value)
return
}
}
func callBaseBlock(otherValue: Int) {
baseMethod(otherValue)
}
private var value1: Int = 1 // ini value
private var obj: OtherClass // another class with method defined
...
...
}
This way, I guarantee that there will be no strong references to self in the block. The syntax is very clear. I use this way to prevent memory leaks.

Lazy/inline implement a protocol in Swift

I want to lazy/inline implement a protocol in Swift.
So in the point of the implementation I will have access to variables outside the protocol scope ,
Same as implementing a interface in Java without declaring a class:
class MyClass:UIView {
var someComponent:SomeInnerComponent = SomeInnerComponent();
var count:Int = 0;
var a = :SomeProtocol { //<----- IS THIS POSSIBLE, IF YES HOW ?
func a0() {MyClass.count--}
func a1() {MyClass.count++}
}
someComponenet.delegate = a;
}
protocol SomeProtocol {
func a0()
func a1()
}
editing----
thanks i look at this solution, and i didn't see how to access a variable of the parent class.
all the examples show an Anonymous class but no one of the examples is accessing the parent variables .
What you're looking for is an inner class (not necessarily an anonymous one), declared in a scope that lets it access the count variable of a MyClass instance, and that adopts a protocol defined at a different scope. Right now Swift has a few of those pieces, but it doesn't look like you can put them all together in any way that's as concise as what you might be looking for.
You might think about declaring an inner class:
class MyView: UIView {
let someComponent = SomeInnerComponent() // type SomeInnerComponent is inferred
var count = 0 // type Int is inferred
class Helper: SomeProtocol {
func a0() { count-- } // ERROR
// ...
}
init() {
someComponent.delegate = Helper()
}
}
But that won't work, because count is implicitly self.count, where self is a Helper instance, not the MyView instance that "owns" the Helper instance. And there isn't a way to reference that MyView instance (or its properties) from within a Helper's methods, because you could just as well construct a MyView.Helper() without having an existing MyView instance. Inner classes (or nested types in general) in Swift nest only in lexical scope, not in existential ownership. (Or to put it another way, since you referenced Java: all inner classes in Swift are like static inner classes in Java. There's no non-static inner class.) If that's a feature you'd like, though, it's probably worth telling Apple you want it.
You could also try declaring Helper inside MyView.init() -- in Swift you can nest type definitions anywhere, including inside functions or methods of other types. Defined there, it can refer to MyView's properties. However, now the type information for Helper is only visible inside of MyView.init(), so when you assign it to someComponent.delegate (whose type is just SomeProtocol), you can't make use of it... this crashes the compiler, even. (That's another bug to report, but it's hard to say whether the bug is really "compiler crashes on valid usage" or "code is bad, but compiler crashes instead of producing error".)
The closest solution I can come up with looks something like this:
class SomeInnerComponent {
var delegate: SomeProtocol?
}
protocol SomeProtocol {
func a0()
func a1()
}
class MyClass {
var someComponent = SomeInnerComponent()
var count = 0
struct Helper: SomeProtocol {
var dec: () -> ()
var inc: () -> ()
func a0() { dec() }
func a1() { inc() }
}
init() {
someComponent.delegate = Helper(
dec: { self.count -= 1 }, // see note below
inc: { self.count += 1 }
)
}
}
How it works:
Helper is an inner struct (could be a class, but a struct is simpler)
It implements the a0 and a1 methods, satisfying the requirements of SomeProtocol
The implementations of a0 and a1 call through to the closures dec and inc, which are stored properties (aka instance variables) of the Helper struct
You write (or otherwise specify) these closures when you construct a Helper instance (using the default member-wise initializer, Helper(dec: (Void -> Void), inc: (Void -> Void)))
Because you can write the closures when initializing a Helper, those closures can capture variables where you're calling the initializer, including the implicit self that refers to the MyClass instance creating the Helper.
You need both a0/a1 and dec/inc because you need closures (the latter), not methods, for capturing the enclosing state. And even though closures and funcs/methods are in many ways interchangeable, you can't create a method/func implementation by assigning a closure to a method/func name. (It'd be a different story if SomeProtocol required closure properties instead of methods, but I'm assuming SomeProtocol isn't something under your control.)
Anyway, this is kind of a lot of boilerplate and a layer of abstraction that you might not really need, so it's probably worth looking into other ways to architect your code.
Note: my example uses the closure { self.count -= 1 } where you might expect { self.count-- }. The latter doesn't work because that's an expression with a value, so Swift will interpret it as shorthand for the closure's return value. Then it'll complain that you assigned a () -> Int closure to a property that expects a () -> () (aka Void -> Void) closure. Using -= 1 instead works around this issue.
I would go for a different approach, I know this a pretty old topic but just in case someone else struggles with this issue:
class MyClass:UIView {
var someComponent:SomeInnerComponent = SomeInnerComponent();
var count:Int = 0;
init(){
// Assign the delegate or do it somewhere else to your preference:
someComponenet.delegate = ProtocolImplementation(myClass: self);
}
private class ProtocolImplementation: SomeProtocol {
let selfReference: MyClass
init(myClass: MyClass){
selfReference = myClass
}
public func a0(){
selfReference.count--
}
public func a1(){
selfReference.count++
}
}
}
protocol SomeProtocol {
func a0()
func a1()
}
By following this approach it's also possible to include the same protocol multiple times, lets say your Protocol supports a generic and you want to implement it twice. SomeProtocol< SomeObject > and SomeProtocol< OtherObject > could be both used this way if needed.
Kind regards

Resources