Why this code capturing self inside this block compile in swift?
The compiler has never complained about this. But it should (and I have filed a bug on this point), because the code you've written won't work: the button will not actually do anything when tapped. (The app might even crash, but then again it might not.)
The reason (for both phenomena) is that the compiler misinterprets the term self
here to mean the class — which does exist before initialization of the instance.
The solution is to replace let
by lazy var
. That does work, because now the code will not actually be called until some later, when the instance does exist.
What is self used for in Swift?
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 lets 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 lets mutate it
z.squareMe()
println(z) // 9
// now lets 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 lets change myString1
myString1.replicateMe(3)
println(myString1) // "AbcAbcAbc"
Why Self.self print Self
This is the bug SR-14564 ""\(Self.self)"
causes issue on Xcode 12.5 when Swift is optimized", and it has already been fixed in Swift 5.5. You are probably using Xcode 12.5, which uses Swift 5.4. Try updating to the Xcode 13 Beta. You can download it here.
Using type as a value, why is the self keyword required here?
Self-answering, with help of comments, I was able to find out the reason:
Using .self
after the type name is called Postfix Self Expression:
A postfix self expression consists of an expression or the name of a
type, immediately followed by.self
. It has the following forms:expression.self
type.self
The first form evaluates to the value of the expression. For example,
x.self
evaluates tox
.The second form evaluates to the value of the type. Use this form to access a type as a value. For example, because SomeClass.self evaluates to the SomeClass type itself, you can pass it to a function or method that accepts a type-level argument.
Thus, the .self
keyword is required to consider the type as a value capable of being passed as an argument to functions.
What is `self` in swift?
self
is a keyword and normally you cannot use keywords and reserved words in places outside their context. However, that sometimes creates problems. For that reason there is a special syntax to make the keyword to be a normal identifier, e.g.:
enum MyEnum: String {
case `default`
}
(also see Swift variable name with ` (backtick))
Historically self
was not allowed as as a constant name inside guard-let-else
and therefore backticks were commonly (ab)used.
They are no longer needed since Swift 4.2.
The code will still work correctly since you can wrap any identifier in backticks and it will just be a normal identifier.
Why does Swift give me a compiler error when my convenience initializer runs self.init inside if an if-let statement?
The error message is perhaps misleading. You must explicitly return nil
if the initialization fails, as stated in
the documentation "Failable Initializers":
You write
return nil
within a failable initializer to indicate a point
at which initialization failure can be triggered.
Which means in your case that you have to add an else case
if the optional binding fails:
convenience init?(data: [String: String]) {
if let name = data["name"], region = data["region"] {
self.init(name: name, season: region)
} else {
return nil
}
}
Alternatively with guard
:
convenience init?(data: [String: String]) {
guard let name = data["name"], region = data["region"] else {
return nil
}
self.init(name: name, season: region)
}
Using useless object.self.self.. or Class.self.self.. is ever need?
This is a Postfix Self Expression according to the Swift reference:
A postfix self expression consists of an expression or the name of a type, immediately followed by
.self
The first form evaluates to the value of the expression. For example, x.self evaluates to x.
The fact that you can write .self
indefinitely is just a side effect of this definition. Since x.self
is an expression itself, you can add .self
to it too. And you can do this forever.
That doesn't mean you should though.
These do the same thing:
let x = 10
let x = 10
Hopefully you'd agree that the second one reads better. Similarly, .self
is generally redundant. According to this discussion, it seems like .self
is really just a legacy from Objective-C. IMO it also makes syntaxes like the identity key path (\.self
) "make more sense".
Swift: Overriding Self-requirement is allowed, but causes runtime error. Why?
Yes, there seems to be a contradiction. The Self keyword, when used as a return type, apparently means 'self as an instance of Self'. For example, given this protocol
protocol ReturnsReceived {
/// Returns other.
func doReturn(other: Self) -> Self
}
we can't implement it as follows
class Return: ReturnsReceived {
func doReturn(other: Return) -> Self {
return other // Error
}
}
because we get a compiler error ("Cannot convert return expression of type 'Return' to return type 'Self'"), which disappears if we violate doReturn()'s contract and return self instead of other. And we can't write
class Return: ReturnsReceived {
func doReturn(other: Return) -> Return { // Error
return other
}
}
because this is only allowed in a final class, even if Swift supports covariant return types. (The following actually compiles.)
final class Return: ReturnsReceived {
func doReturn(other: Return) -> Return {
return other
}
}
On the other hand, as you pointed out, a subclass of Return can 'override' the Self requirement and merrily honor the contract of ReturnsReceived, as if Self were a simple placeholder for the conforming class' name.
class SubReturn: Return {
override func doReturn(other: Return) -> SubReturn {
// Of course this crashes if other is not a
// SubReturn instance, but let's ignore this
// problem for now.
return other as! SubReturn
}
}
I could be wrong, but I think that:
if Self as a return type really means 'self as an instance of
Self', the compiler should not accept this kind of Self requirement
overriding, because it makes it possible to return instances which
are not self; otherwise,if Self as a return type must be simply a placeholder with no further implications, then in our example the compiler should already allow overriding the Self requirement in the Return class.
That said, and here any choice about the precise semantics of Self is not bound to change things, your code illustrates one of those cases where the compiler can easily be fooled, and the best it can do is generate code to defer checks to run-time. In this case, the checks that should be delegated to the runtime have to do with casting, and in my opinion one interesting aspect revealed by your examples is that at a particular spot Swift seems not to delegate anything, hence the inevitable crash is more dramatic than it ought to be.
Swift is able to check casts at run-time. Let's consider the following code.
let sm = SuperMario()
let ffm = sm as! FireFlowerMario
ffm.throwFireballs()
Here we create a SuperMario and downcast it to FireFlowerMario. These two classes are not unrelated, and we are assuring the compiler (as!) that we know what we are doing, so the compiler leaves it as it is and compiles the second and third lines without a hitch. However, the program fails at run-time, complaining that it
Could not cast value of type
'SomeModule.SuperMario' (0x...) to
'SomeModule.FireFlowerMario' (0x...).
when trying the cast in the second line. This is not wrong or surprising behaviour. Java, for example, would do exactly the same: compile the code, and fail at run-time with a ClassCastException. The important thing is that the application reliably crashes at run-time.
Your code is a more elaborate way to fool the compiler, but it boils down to the same problem: there is a SuperMario instead of a FireFlowerMario. The difference is that in your case we don't get a gentle "could not cast" message but, in a real Xcode project, an abrupt and terrific error when calling throwFireballs().
In the same situation, Java fails (at run-time) with the same error we saw above (a ClassCastException), which means it attempts a cast (to FireFlowerMario) before calling throwFireballs() on the object returned by queryFriend(). The presence of an explicit checkcast instruction in the bytecode easily confirms this.
Swift on the contrary, as far as I can see at the moment, does not try any cast before the call (no casting routine is called in the compiled code), so a horrible, uncaught error is the only possible outcome. If, instead, your code produced a run-time "could not cast" error message, or something as gracious as that, I would be completely satisfied with the behaviour of the language.
Property initializers run before 'self' is available
As correctly pointed out by vadian you should create an init
in such scenarios:
class MyOwn {
let myUser: User
var life: Int
init() {
self.myUser = User(name: "John", age: 100)
self.life = myUser.age
}
}
You can't provide a default value for a stored property that depends on another instance property.
Related Topics
How to Sum the Numbers(Int16) of Stored Core Data - Swift 3
Swift-Setting a Physics Body Velocity by Angle
How to Make a Segue to Second Item of Tab Bar
Firebase iOS Receive Data from Push Notification
How to Add 3D Shapes in Swift Ui
How to Use the "Handler" of Uialertaction to Call Another Uialertaction
Compile Latex Code Using Swift
Custom Annotation Showing Same Image for All Different Types of Poi'S
Adding Index List and Section Headers to Translated Tableview
Adding Animation to Tabviews in Swiftui When Switching Between Tabs
Convert Optional String to Int in Swift
File Couldn't Be Opened Because You Don't Have Permission to View It Error
Compile Time Key Path Checking in Swift
How to Insert a Sublayer in Swift
Swift Struct with Lazy, Private Property Conforming to Protocol
Running Swift Build in Terminal Leading to "Platform Path" Errors