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.
Related
TL;DR
I have a class with no public initializers or instances that passes an instance of itself to a closure in another class. It does this through a mirror of the other class. When I go to access that instance from within the closure, I'm getting a EXC_BAD_ACCESS error, but other parameters passed to the closure are clearly accessible and do not result in a bad access error. I have no idea why. See code below for replication in a new project or a playground.
Detailed Explanation
I've been trying to figure out a way to implement class-specific access control, where multiple specific classes have sole access to another class containing variables and functions to be shared between them. All other classes would not have such access. Kind of like a static class, or a Singleton pattern, but with specific, class-named access control.
I thought I had something that would actually work in pure swift, (which is nice for me since I don't know Objective-C, and only started on swift about 16 months ago.) It's done in an almost anti-swift manner, so just bear with me - my goal is to start with something functional and move it towards elegance and beauty from there.
Even though I'm reasonably confident it should all work, I'm encountering a EXC_BAD_ACCESS error in a very unexpected place.
The "class-specific private" class that you are not allowed to access an instance of unless you are on its "okay" list, we can call the Restricted class.
The class(es) that is(are) allowed access to the Restricted class we can call the Accessor class(es).
The programmer must tell the Restricted class to call a function from the Accessor, and "drop in" an instance of the Restricted class by passing it as a parameter to that function. You do this by passing in the name of the function to be called, an instance of the Accessor class on which to call said function, and any parameters that the function would need in addition to the Restricted class instance.
I could make an enormous switch in the Restricted class, each case of which properly calls each function indicated on each of the Accessor classes...but to get around that excessive overhead/setup, I have the name of the function to be called on the Accessor classes passed in as a string, and accessed through a mirror. Since mirrors only reflect properties and not functions, the function must be a property with an assigned closure, instead of a traditional function.
We can call these closures DropClosures, since their purpose is to have the shared, Restricted class dropped into them. In fact we could call this whole pattern the "DropClosure Pattern". (Or maybe anti-pattern, I know it's kind of gruesome as-is.)
The properties of the "shared" instance of the Restricted class are stored internally as a private static dict (as json, basically). To generate an actual instance of itself, the Restricted class uses a private initializer that accepts that dict as a parameter. After a DropClosure runs with said initialized instance, the Restricted class uses a Mirror of that instance to store any changes back in the "shared" dict, and the instance will go out of scope unless a reference is made to it. So after each DropClosure completes its run, the instance passed to it is more or less useless as a representation of the "shared" aspect of the class, intentionally so.
I only do this because there is no way to require that all references to a certain weak reference also be weak. I don't want a class with access to the weak reference to assign a strong reference to the same instance and keep it in memory, that would defeat the access control goal by allowing the instance to be shared outside of its access scope. Since I can't force the instance to expire once the closure has completed, the next best thing is to remove the motivation for doing so by making the object no longer connected to the shared source after the closure completes.
This all theoretically works, and will compile, and will not throw any swift exceptions when run.
The Accessor (or any class that has an instance of an Accessor) calls RestrictedClass.run(), the run code validates the Accessor instance, finds the DropClosure in that instance, and passes in an instance of the Restricted class to that closure.
However, whenever I try to access that instance from within the DropClosure, it gives me the aforementioned bad access error, seemingly on a C or Objective-C level.
As far as I can tell, the instance should be accessible at this point, and none of the variables being used should be dropping out of scope yet.
At this point I'm totally spitballing - is it possible that there is something in the background that prevents a class with no public initializers from being passed through a mirror? Does it have to do with passing it into a closure called from that mirror? Is there some kind of hidden weak reference that's making the instance get ARC'd?
Please note that I've tried discarding the "weak" wrapper object and only passing in the Restricted instance to the closure, and I get the same bad access error. The error is independent of the instance being weakly referenced.
Code:
import Foundation
typealias DropClosureVoid<T: AnyObject & AccessRestricted> = (_ weaklyConnectedInterface: WeaklyConnectedInterface<T>, _ usingParameters: Any?)->Void
typealias DropClosureAny<T: AnyObject & AccessRestricted> = (_ weaklyConnectedInterface: WeaklyConnectedInterface<T>, _ usingParameters: Any?)->Any?
enum AccessError : Error {
case InvalidFunction
case InvalidAccessClass
}
protocol AccessRestricted {
static func run<T:AnyObject>(_ closureName:String, in classObject: T, with parameters:Any?) throws
static func runAndReturn<T:AnyObject>(_ closureName:String, in classObject: T, with parameters:Any?) throws -> Any?
}
///This class contains an instance that should be expected to only temporarily represent the original, even if a strong reference is made that keeps the value in scope.
class WeaklyConnectedInterface<T:AnyObject> {
weak var value:T?
init(_ value: T) {
self.value = value
}
}
class Accessor {
let restrictedClassPassable:DropClosureVoid<RestrictedAccessClass> = { weaklyConnectedInterface, parameters in
print(weaklyConnectedInterface) // **EXC_BAD_ACCESS error here**
//note that the error above happens even if I pass in the instance directly, without the WeaklyConnectedInterface wrapper.
//It's clearly an issue that occurs when trying to access the instance, whether the instance is wrapped in a the class that makes a weak reference to it or not, which means that it is inaccessible even when strongly referenced.
if let parameterDict = parameters as? [String:String] {
print(parameterDict["paramkey"] ?? "nil")
print(weaklyConnectedInterface)
weaklyConnectedInterface.value?.restrictedVariable = "I've changed the restricted variable"
}
}
let anotherRestrictedClassPassable:DropClosureAny<RestrictedAccessClass> = { weaklyConnectedInterface, parameters in
if let parameterDict = parameters as? [String:String] {
print(parameterDict["paramkey"] ?? "nil")
print(weaklyConnectedInterface.value?.restrictedVariable as Any)
return weaklyConnectedInterface.value?.restrictedVariable
}
return nil
}
func runRestrictedClassPassable() throws {
let functionName = "restrictedClassPassable"
print("trying validateClosureName(functionName)")
try validateClosureName(functionName)//this is in case you refactor/change the function name and the "constant" above is no longer valid
print("trying RestrictedAccessClass.run")
try RestrictedAccessClass.run(functionName, in: self, with: ["paramkey":"paramvalue"])
let returningFunctionName = "anotherRestrictedClassPassable"
print("trying validateClosureName(returningFunctionName)")
try validateClosureName(returningFunctionName)
print("trying RestrictedAccessClass.runAndReturn")
let result = (try RestrictedAccessClass.runAndReturn(returningFunctionName, in: self, with: ["paramkey":"ParamValueChanged"]) as! String?) ?? "NIL, something went wrong"
print("result is \(result)")
}
func validateClosureName(_ name:String) throws {
let mirror = Mirror(reflecting: self)
var functionNameIsPresent = false
for child in mirror.children {
if child.label != nil && child.label! == name {
functionNameIsPresent = true
break
}
}
guard functionNameIsPresent else {
print("invalid function")
throw AccessError.InvalidFunction
}
}
}
extension Mirror {
func getChildrenDict() -> [String:Any]
{
var dict = [String:Any]()
for child in children
{
if let name = child.label
{
dict[name] = child.value
}
}
return dict
}
}
class RestrictedAccessClass:AccessRestricted {
private static var shared:[String:Any] = [
"restrictedVariable" : "You can't access me!"
]
private static func validateType<T>(of classObject:T) throws {
switch classObject {
case is Accessor:
return
default:
print("Invalid access class")
throw AccessError.InvalidAccessClass
}
}
var restrictedVariable:String
private init() {
restrictedVariable = "You can't access me!"
}
private init(from json:[String:Any]) {
restrictedVariable = json["restrictedVariable"] as! String
}
static func run<T:AnyObject>(_ closureName:String, in classObject: T, with parameters:Any?) throws {
print("trying validateType(of: classObject) in run")
try validateType(of: classObject)
for child in Mirror(reflecting: classObject).children {
if let childName = child.label {
if childName == closureName {
let dropClosure = child.value as! DropClosureVoid<RestrictedAccessClass>
let selfInstance = RestrictedAccessClass(from:shared)
let interface = WeaklyConnectedInterface(selfInstance)
dropClosure(interface, parameters)
runCleanup(on: selfInstance)//parses any data changed by the end of the drop closure back into the dict for use in future instances. This means you mustn't try using the instance in an async closure. The correct way to do this would be to call run inside of an async closure, rather than putting an anync closure inside of the drop closure.
_ = interface.value
return
}
}
}
}
static func runAndReturn<T:AnyObject>(_ closureName:String, in classObject: T, with parameters:Any?) throws -> Any? {
print("trying validateType(of: classObject) in runAndReturn")
try validateType(of: classObject)
for child in Mirror(reflecting: classObject).children {
if let childName = child.label {
if childName == closureName {
let dropClosure = child.value as! DropClosureAny<RestrictedAccessClass>
let selfInstance = RestrictedAccessClass(from:shared)
let interface = WeaklyConnectedInterface(selfInstance)
let result = dropClosure(interface, parameters)
runCleanup(on: selfInstance)//parses any data changed by the end of the drop closure back into the dict for use in future instances. This means you mustn't try using the instance in an async closure. The correct way to do this would be to call run inside of an async closure, rather than putting an anync closure inside of the drop closure.
_ = interface.value
return result
}
}
}
return nil
}
private static func runCleanup(on instance:RestrictedAccessClass) {
shared = Mirror(reflecting:instance).getChildrenDict()
//once this function goes out of scope(or shortly thereafter), the instance passed will become useless as a shared resource
}
}
Code to encounter error:
I just put this in a new project's AppDelegate.application(didFinishLaunching). You can put all of the code above and below, in order, in a playground and it will break in the same spot, but not as clearly.
let accessor = Accessor()
do {
try accessor.runRestrictedClassPassable()
}
catch {
print(error.localizedDescription)
}
Updates
Whether zombie objects are turned on or off, I'm getting the same error message from Xcode: Thread 1: EXC_BAD_ACCESS (code=1, address=0x1a1ebac696e)
Running an analysis with Command+Shift+B reveals no warnings.
Running with all of the malloc options enabled reveals the following error:
Thread 1: signal SIGABRT, objc[somenumber]: Attempt to use unknown class 0xSomevalue
This just got weird...
Apparently, the "unknown class" is the project. I found this out by selecting the (i) bubble on the inline object inspector for the Restricted instance that was causing the crash. It gives me the following message:
Printing description of weaklyConnectedInterface:
expression produced error: error:
/var/folders/zq/_x931v493_vbyhrfc25z1yd80000gn/T/expr52-223aa0..swift:1:65:
error: use of undeclared type 'TestProject'
Swift._DebuggerSupport.stringForPrintObject(Swift.UnsafePointer<TestProject.RestrictedAccessClass>(bitPattern: 0x103450690)!.pointee)
^~~~~~~~~~~
I thought that maybe this would happen for other classes, so I tested, and it's able to access other project-level classes just fine. Only for this specific instance is the project "namespace" undefined.
Please find below required modifications (not many)... Tested with Xcode 11.2 / iOS 13.2.
1) made interface inout to pass it as-is original, otherwise it somehow copied loosing type information
typealias DropClosureVoid<T: AnyObject & AccessRestricted> =
(_ weaklyConnectedInterface: inout WeaklyConnectedInterface<T>, _ usingParameters: Any?)->Void
typealias DropClosureAny<T: AnyObject & AccessRestricted> =
(_ weaklyConnectedInterface: inout WeaklyConnectedInterface<T>, _ usingParameters: Any?)->Any?
2) fix places of usage (same in two places)
var interface = WeaklyConnectedInterface(selfInstance) // made var
dropClosure(&interface, parameters) // << copy closure args here was a reason of crash
3) ... and that's it - build & run & output
Note: I would recommend to avoid force unwrap and use the following
if let dropClosure = child.value as? DropClosureVoid<RestrictedAccessClass> {
dropClosure(&interface, parameters)
}
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)
Please help me with Swift,
I need singleton with can inheritance.
I can do like this
class A {
var defaultPort: Int
required init() {
self.defaultPort = 404
}
class var defaultClient: A {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: A? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = self.init()
}
return Static.instance!
}
}
but in swift 2.0 we can do like this
static let defaultClient = A() //self.init()
but it creates an instance of the class A any way.
How i can use like this self.init()
static let defaultClient = self.init()
in order to be able to inherit
UPD
best way for now
class A {
class func defaultClient() -> Self {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: A? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = self.init()
}
return instance(Static.instance, asType: self)
}
}
here we need helper as
func instance<T>(instance: Any, asType type: T.Type) -> T {
let reurnValue = instance as! T
return reurnValue
}
because another way cast A to Self not exist, for now.
p.s. crazy swift way!
why i can not do instance as! Self
Your question isn't very clear. You're looking for something like the class constant solution posted in this answer, but which automatically uses "my own class" instead of explicitly creating an instance of a specific class... right?
That is, you want to turn this:
class Singleton {
static let sharedInstance = Singleton()
}
into this:
class Singleton {
static let sharedInstance = SomeMagicThing()
}
class SingletonSubclass {}
where SomeMagicThing automatically creates a Singleton instance when you call Singleton.sharedInstance, and a SingletonSubclass instance when you call SingletonSubclass.sharedInstance. Correct?
Sorry, that can't be done (as of Swift 2.1).
Part of your issue is that static and class mean two different things. The static modifier means that the declaration it modifies is associated only with a specific type declaration. So, the Singleton type owns a pointer to a specific object -- its subclasses don't inherit that pointer. (And if they did, would it point to the same object or a subclass-specific one?)
If you could create a class var or class let, that'd (in theory) give you the kind of dispatch/inheritance you want. But trying that gives you an error (emphasis mine):
class stored properties not yet supported in classes; did you mean static?
So it sounds like this sort of thing might show up someday.
Of course, the other side of the problem is finding a way to dynamically refer to the "current" type responsible for executing some statement. In the context of an instance method, you have self.dynamicType for such things... but there's no equivalent for classes. (Self is a type constraint, not an actual type.) This is a side effect of the type system in Swift being much more strict and static than that of Objective-C (for example, metatypes aren't just a special flavor of otherwise normal objects). File a bug if you'd like to see a change to that effect?
I'm using XLForm, which has a class XLFormDescriptor, which needs to be initialized with init(title: String).
The title I want to use is the return value of my current class's name function (class-level properties aren't a feature yet).
Putting this at a class level, the code to set it up looks like this:
let settingsForm = XLFormDescriptor(title: self.name())
But this gives the error:
'PanelController -> () -> PanelController!' does not have a member
named 'name'
Putting this at the top of the class's init call looks like this:
let settingsForm: XLFormDescriptor
override init() {
self.settingsForm = XLFormDescriptor(title: self.dynamicType.name())
super.init()
}
And doing that gives this error:
'self' used before super.init call
Putting it after super.init() gives this error:
Property 'settingsForm' not initialized at super.init call
Any ideas how I can possibly do this?
EDIT: A workaround is to do this:
let settingsForm = XLFormDescriptor(title: "")
override init() {
super.init()
self.settingsForm = XLFormDescriptor(title: self.dynamicType.name())
}
In swift, self is not available until all class properties have been initialized. There's a check at compilation time for that.
So if you have a class with properties, inherited from another class:
class A {
var prop1: Int
init(val1: Int) {
self.prop1 = val1
}
}
class B : A {
var prop2: String
override int(val1: Int, val2: String) {
// First initialize properties of this class
self.prop2 = val2
// Next call a superclass initializer
super.init(val1: val1)
// From now on, you can use 'self'
}
}
you cannot use self until all (non optional) class properties have been been initialized and a superclass initializer has been invoked (if the class is inherited).
If you initialize a property inline, like this:
let settingsForm = XLFormDescriptor(title: self.name())
you are explicitly using self before the class instance has been properly initialized - that's the reason of the compilation error.
The solution you found yourself is not a workaround, but the right way of doing it. You first initialize the property with a value not referencing self, then once the class has been initialized, you assign that property a new value.
Note that this is the only case where you are allowed to assign a new value to an immutable property, as long as it is done from within an initializer.
For a better understanding of how initialization works, I recommend reading the corresponding documentation: Initialization
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