Swift - why can't lazy properties be readily made read only - ios

Can anyone please explain this comment re lazy properties by neuburg in iOS 9 swift fundamentals book ...
"There are some minor holes in the language: lazy instance properties can’t have setter observers, and there’s no lazy let (so you can’t readily make a lazy instance property read-only)" .... Particularly about no lazy let preventing ability for read only

From Apple documentation:
You must always declare a lazy property as a variable (with the var keyword), because its initial value might not be retrieved until after instance initialization completes. Constant properties must always have a value before initialization completes, and therefore cannot be declared as lazy.
But if you want do get a value lazy from a class/struct and want to be sure that nobody can write back to that value then simply use a func with a return value. Or like milos said - a private(set) on a lazy property. (which is not the same thing) So somehow everything is possible. :)

Related

Swift instance members & functions calls, could someone please clarify?

I'm practicing functions in an Xcode project (not playground, if that matters) and when I set the constant's function name to the above function's name, Xcode won't let me call it.
In other functions I've done the same thing I haven't had this error, I don't know why it's being triggered. I've tried putting the "let fun" constant into it's own struct but that just throws up a different error.
Your let fun = playstation(... is code. It is an executable command. Code consisting of an executable command cannot just live anywhere. It cannot exist just free-floating the way you have it. It must live in a method. For example you could put it inside your viewDidLoad method.
I am sure you know this, but I would like to say that learning the basics/fundamentals of the Swift language is really good if you use playgrounds for that or any other online IDEs which support Swift language.
Swift Playgrounds Experience is very, very different than what an iOS dev has to do later, i.e. when it actually comes to building an app.
Of course in app making, the Swift language is used, and one uses the knowledge he practiced using playgrounds. BUT!
When it comes to storyboards, ViewControllers, etc., one has to understand that this time, it is all about OOP (classes and structs).
It is about managing views, loading them, displaying UIView objects, implementing logic, saving/loading data...
So as people mentioned above, here you are creating an instance method and trying to use it as a regular function inside that Class.
To be able to use this function as you expect, you have to create an object/instance of this class, then you can call this function.
In this picture, you may see that using a static keyword also might be a solution. static func(){} means that this function belongs to the class itself. You access that func by using the full name of the type/class.
You cannot call an instance method to initialize this same exact instance property, so you will need to convert to a lazy var like so:
lazy var fun = playStation(game: "Monsters")
This way, the playStation(game: "Monsters") call will be triggered lazily, in the exact moment when the fun property will be called for the first time. This can be very useful, especially when performing more intensive tasks. The quirk with using lazy keyword is that it can only be used with var, which means the property can be mutated or set again - we lose immutability of let constants.
But maybe you do not want to store the fun value as an instance property and only want to get it once? You could then move it into the viewDidLoad implementation, so the fun is no longer an instance property but a local one, available only within the viewDidLoad method scope.
override func viewDidLoad() {
super.viewDidLoad()
let fun = playStation(game: "Monsters")
// do what you want with the `fun` value.
// maybe set it as text to some label?
myLabel.text = fun
}
You can read more about Lazy Initialization in this blogpost, also make sure to read the official documentation.

Swift - Capturing closures - Apple's swift programming guide snippet

In Apple's Swift programming guide, "Automatic Reference Counting" section, at "Resolving Strong Reference Cycles for Closures",
This snippet is mentioned:
lazy var someClosure: () -> String = {
[unowned self, weak delegate = self.delegate!] in
// closure body goes here
}
What is the point of the exclamation mark in the assignment "weak delegate = self.delegate!"?
I mean, why do you care if there is a value or not? In either ways, you will be receiving an optional delegate inside the closure body since delegate is declared weak, which must be optional, and you will have to access it as an optional.
On the other hand, if you know for sure there 'self.delegate' wont be nil when you access it, why not declaring it as unowned?
Therefore, why is the force unwrapping necessary here?
Can someone shed some light on this?
As there is not really any more context in the text around this example the only person who can know for sure is the author or maintainer of the Swift programming guide.
But here are some possible reasons that I can think of (in no particular order)
The author made a mistake (it happens)
It was required in an older version of Swift and the documentation has not been updated (keeping documentation up to date is hard)
The author wanted to make it obvious to others that creating the block if the delegate does not exist is a bug
The author wants to make it easier to track cases when a delegate was deallocated between creating the block and calling it (maybe for analytics purposes?)

Swift: why does inheriting from NSManagedObject ruin my properties?

I'm a total Swift/IOS newbie and there's something about CoreData that I simply can't understand.
I have a class with some non-optional properties that are initialized by a designated initializer. Then, if I set that class to inherit from NSManagedObject, then suddenly I get the error
Stored property X requires an initial value or should be #NSManaged.
Why does Swift suddenly think my properties are not initialized, even though they clearly are?
Also, I read that #NSManaged "tells the compiler that the storage and implementation of the properties will be handled by CoreData", but what does that even mean?
Any answers would be appreciated..
I was actually just reading about this yesterday.
Yes, it kinda really acts like #dynamic -- technically it might be
identical even. Semantically there is a slight difference:
#dynamic says 'compiler, don't check if my properties are also
implemented. There might be no code you can see but I guarantee it
will work at runtime'
#NSManaged now says 'compiler, don't check those properties as I have
Core Data to take care of the implementation - it will be there at
runtime'
so you could even say: #NSManaged is syntactic sugar that is a more
narrow version of dynamic :)
taken from this question
The big push with swift was to make the language extremely safe, as in this case, checking if the properties are implemented at compile time. If I understand correctly, CoreData doesn't quite conform to these compile time checks, thus adding in #NSManaged lets the compilers know that the variables will be taken care of.
From Apple:
You use the #NSManaged attribute to inform the Swift compiler that
Core Data provides the storage and implementation of a declaration at
runtime.

Swift Lazy and Optional properties

What is the difference between a Lazy or Optional property in Swift?
For example, if someone is building a navigation bar that comes in from the side, I think that should all be within one UIViewController. The user might never open the menu but sometimes they will.
var menu: NavigationBar?
lazy var menu: NavigationBar = NavigationBar.initialize()
Both of the optional I think are good code, because they don't create the view unless its needed. I understand Optional means there might be a value it might be nil. I also understand Lazy means don't worry about it until I need it.
Specific Question
My question is are their performance patterns (safety and speed) that say optionals are faster and safer or vise versa?
OK, this is an interesting question, and I don't want to imply that the existing answers aren't good, but I thought I'd offer my take on things.
lazy variables are great for things that need to be setup once, then never re-set. It's a variable, so you could change it to be something else, but that kind of defeats the purpose of a lazy variable (which is to set itself up upon demand).
Optionals are more for things that might go away (and might come back again). They need to be set up each time.
So let's look at two scenarios for your side menu: one where it stays around while it's not visible, and another for when it is deallocated.
lazy var sideMenu = SideMenu()
So the first time the sideMenu property is accessed, SideMenu() is called and it is assigned to the property. The instance stays around forever, even when you're not using it.
Now let's see another approach.
var _sideMenu: SideMenu?
var sideMenu: SideMenu! {
get {
if let sm = _sideMenu {
return sm
} else {
let sm = SideMenu()
_sideMenu = sm
return sm
}
}
set(newValue) {
_sideMenu = newValue
}
}
(Note this only works for classes, not structs.)
OK so what does this do? Well it behaves very similarly to the lazy var, but it let's you re-set it to nil. So if you try to access sideMenu, you are guaranteed to get an instance (either the one that was stored in _sideMenu or a new one). This is a similar pattern in that it lazily loads SideMenu() but this one can create many SideMenu() instances, where the previous example can only create one once.
Now, most view controllers are small enough that you should probably just use lazy from earlier.
So two different approaches to the same problem. Both have benefits and drawbacks, and work better or worse in different situations.
They're actually pretty different.
Optional means that the value could possibly be nil, and the user isn't guaranteeing that it won't be. In your example, var menu: NavigationBar? could be nil for the entire lifetime of the class, unless something explicitly assigns it.
Lazy on the other hand means that the assignment will not be called until it is first accessed, meaning that somewhere in code someone tries to use your object. Note however that it is STILL promised to not be nil if you declare it like you have here lazy var menu: NavigationBar = NavigationBar.initialize(), so no need to do optional chaining.
And actually, a variable can be BOTH Lazy AND Optional, which means that it's value will be loaded when it is first accessed, and that value might be nil at the point it's initialized or at any future point. For example:
lazy var menu: NavigationBar? = NavigationBar.initialize()
That NavigationBar.initialize() is now allowed to return nil, or someone in the future could set the menu to be nil without the compiler/runtime throwing errors!
Does that make the difference clear?
Edit:
As to which is BETTER that's really a case by case thing. Lazy variables take a performance hit on first initialization, so the first access will be a slow one if the initialization process is long. Otherwise, they're nearly identical in terms of safety/performance. Optional variables you have to unwrap before using and so there is a very minor performance cost with that (one machine instruction, not worth the time to think about)
Optional and lazy properties are not the same
An optional property is used when there are chances that the value might not be available(i.e can be nil). But in your scenario, the navigation bar will always be available, its just that the user might not open it.
So using a lazy property serves your purpose. The NavigationBar will only be initialised if the user taps on it.
I do not see any performance issues except that if you use an optional, there is an additional overhead of checking if the value is nil each time before accessing it.

What must be accomplished in the implementation of an initializer?

What must be accomplished in the implementation of an initializer?
a. All properties need to be initialized with a value
b. All properties need to be explicitly assigned a value.
c. All non-Optional properties need to be initialized.
Sorry, that's incorrect.
Optionals need to be initialized as well.
d. The object needs to be created
What answer is correct and why?
In my opinion that is very confusingly stated question. Because what you as the developer have to do is Option c.
Take a look at this simple code example and the minimum init to be compilable
class SomeClass {
var a : AnyObject
var b : AnyObject?
var c : AnyObject!
var d = ":)"
init() {
a = ""
print("initialized")
}
}
The swift docu states
Classes and structures must set all of their stored properties to an appropriate initial value by the time an instance of that class or structure is created. Stored properties cannot be left in an indeterminate state.
You can set an initial value for a stored property within an initializer, or by assigning a default property value as part of the property’s definition. These actions are described in the following sections.
Option d. is imho non-sense since the object creation is handled by the underlying runtime environment and not via the initializer.
Now b. and a. remain with the tiny difference in wording explicitly assigned vs. initialized. I would therefore discard Option b because the b and c variable do not need any explicit value, the implicit nil is perfectly fine for the time (reading c will not work yet though)
Therefore my answer choice would be Option a. After the init method all properties need to have some specific value. Some of them explicitly in the init function, some of them implicitly.
tl;dr:
my final answer is Option a.

Resources