Which do you use 'obj' or 'self.obj'? [duplicate] - swift

This question already has answers here:
When should I access properties with self in swift?
(6 answers)
Closed 7 years ago.
I have a trivial question.
Which do you use A or B in this case? Why?
obj and self.obj are exactly the same.
let obj = MyClass()
func sampleFunction(obj: MyClass) {
// A
obj.xxx()
// B
self.obj.xxxx()
}

self.obj refers to the instance of the class you are in and access the obj instance variable defined. Referring to obj will refer to the named parameter within the scope of the function.
class Test {
let obj = "Global"
func sampleFunction(obj: String) {
// A
print(obj)
// B
print(self.obj)
}
}
var t = Test()
t.sampleFunction("Internal")
Paste this into a Playground for a demo of this to aid the explanation.
It is subjective whether or not to use self to refer to instance variables, but if there is another local variable or named parameter with the same name as the instance variable in that scope - you must use self to differentiate like in the example.
It is a good rule-of-thumb to always use self to refer to instance variables, this improves readability and decreases the chance of bugs relating to conflicting local variable names in scope occurring.

Related

Difference between using class() and class.init() in swift [duplicate]

This question already has answers here:
Is there difference between using a constructor and using .init?
(2 answers)
Closed 3 years ago.
Why we need to use init method explicitly while we can create an object without it
class Details {
}
var obj = Details()
var obj = Details.init()
What's the difference between these two instance creations
Both are allowed and are equivalent. As The Swift Programming Language says:
If you specify a type by name, you can access the type’s initializer without using an initializer expression. In all other cases, you must use an initializer expression.
let s1 = SomeType.init(data: 3) // Valid
let s2 = SomeType(data: 1) // Also valid
let s3 = type(of: someValue).init(data: 7) // Valid
let s4 = type(of: someValue)(data: 5) // Error
So, when you’re supplying the name of the type when instantiating it, you can either use the SomeType(data: 3) syntax or SomeType.init(data: 3). Most Swift developers would favor SomeType(data: 3) as we generally favor brevity unless the more verbose syntax lends greater clarity, which it doesn’t in this case. That having been said, SomeType.init(data: 3) is permitted, though it is less common in practice.
Class() is just a shorthand for Class.init()
Both are interpreted by the compiler as exactly the same statements with no difference at all.

Cannot use instance member 'ie' within property initializer [duplicate]

This question already has answers here:
How to initialize properties that depend on each other
(4 answers)
Closed 5 years ago.
The code:
class man: human {
var ie = "ie/1/3/1///"
let pe = "pe/1/3/3///"
let ol = "ol/1/1/1///"
let sejong = "sejong/3/1/1///"
let gong = "gong/1/1/1///"
let mans = [ie, pe, ol, sejong, gong]
}
The error:
Col 15: cannot use instance member 'ie' within property initializer;
property initializers run before 'self' is available
How can I debug this?
Instance variables cannot be used upon non-lazy initialization of each other.
Consider your code taking into account the following thing: it doesn't matter in which order you define and initialize a variable. From your (developer) perspective, they will all get initialized simultaneously (they are, of course, not from low-level perspective).
It means that when you write:
let mans = [ie,pe,ol,sejong,gong]
You basically tell compiler to make up an array of something not yet initialized. None of the constituents of your array are existent when you make this assignment.
Common solution is to make your initialization - that which relies on other instance variables - lazy:
class man {
var ie = "ie/1/3/1///"
let pe = "pe/1/3/3///"
let ol = "ol/1/1/1///"
let sejong = "sejong/3/1/1///"
let gong = "gong/1/1/1///"
lazy var mans : [String] = {
[ie,pe,ol,sejong,gong]
}()
}
Unlike ordinary, lazy variable obtains its value on first use of this variable, but not instantly once an object has been created. You tell compiler: I don't mean to make up an array right away, but make me one when I firstly use this variable, after the object has already been created:
let theMan = man()
On this stage, theMan.mans property is not yet initialized. However, suffice it to perform even basic operation, like printing:
print(theMan.mans)
that this property is initialized. This is called lazy initialization and this is the way you can make up an array consisting of other instance variables upon initialization. Of course, you should remember that any dependent data may be modified and affect the init.

Difference between declaration of object in Swift [duplicate]

This question already has answers here:
Ways to Create Instance
(2 answers)
Closed 5 years ago.
I apologize in advance for a possible duplicate but since I do not know the names of these declarations I was not able to find any answers to simular questions.
I would appreciate if anyone could explain the difference between these to object declarations to me:
var objectname: Classname!
var objectname = Classname()
Both are an instance of the class Classname right? So when do I use the first declaration and when the second? And why?
var objectname: Classname!
This declares an object of type Classname but does not give it a value. If you were to try to access this value, it would be nil. Because having no value in Swift is not allowed, the ! tells the compiler that the variable will have a value when it is accessed. For iOS development, I would not recommend using the first declaration because it is unsafe. I would use var objectname: Classname? which creates the same variable but does not assume that it has a value. You could use this type like this:
var objectname: Classname?
if let obj = objectname {
// do something with obj (the unwrapped value of objectname)
}
If objectname has a value, then the if statement executes, otherwise it doesn't.
var objectname: Classname()
This declares a variable of type Classname and initializes it at the same time. So while the first statement is nil, the second statement represents an object of type Classname. You should use this statement when creating an instance variable.

What is difference between create object with init and () in Swift [duplicate]

This question already has answers here:
In Swift, what's the difference between calling UINavigationController() vs UINavigationController.init()?
(3 answers)
Closed 5 years ago.
class A {
private var value: Int
init(value: Int) {
self.value = value
}
}
We have class A and what is the difference between I create this object by using A.init(value: 5) and A(value: 5)? Thanks
There is no functional difference between the two. Both styles will call the same initializer and produce the same value.
Most style guides that I've seen prefer to leave out the explicit .init-part in favor of the shorter A(value:) syntax — that also resembles the constructor syntax in many other languages.
That said, there are some scenarios where it's useful to be able to explicitly reference the initializer. For example:
when the type can be inferred and the act of initialization is more important than the type being initialized. Being able to call return .init(/* ... */) rather than return SomeComplicatedType(/* ... */) or let array: [SomeComplicatedType] = [.init(/* ... */), .init(/* ... */)]
when passing the initializer to a higher order function, being able to pass "something".map(String.init) rather than "something".map({ String($0) })
Again, it's a matter of style.

What is the difference between "let" and "static let"? [duplicate]

This question already has answers here:
Differences between "static var" and "var" in Swift
(3 answers)
Closed 6 years ago.
class Foo {
let fooValue = 1
}
print(Foo.fooValue) // not work
class Bar {
static let barValue = 1
}
print(Bar.barValue) // work; print "1"
Why? I expected that Foo example to work, because the value of fooValue is constant, value and memory address known in compilation time. But I need use keyword static to work.
fooValue is an instance property. There's one separate fooValue per every instance (object) of the Foo class.
barValue is a static property. There's one shared barValue that belongs to the class.
Here's a more concrete example. Suppose I had this class:
class Human {
static let numberOfLimbs = 4
let name: String
}
What would you expect to happen if I asked you what the name of a Human is? I.e. Human.name. Well, you wouldn't be able to answer me, because there's no one single name of all humans. Each human would have a separate name. You could however, tell me the number of limbs humans have, (Human.numberOfLimbs), which is (almost) always 4.
you don't have to instantiate your class to access static properties
if you wanted to access it in your first class use
Foo().fooValue
generally you want to use static for properties that you want to access without having to instantiate the object every time