Treehouse Intermediate Course Part 2 (properties)
So a decent start yesterday with the first Treehouse Intermediate course. Just to recap it was about properties - stored, computed and typed. I get the difference between these and am getting more used to the syntax of get/set. My concern with this Treehouse course is that there seem to be no practical Xcode projects. This isn't necessarily a bad thing; it could be useful to explore some key concepts at greater depth before I resume with a Udemy course - mostly likely Angela's.
Anyway, just to reiterate my plan - I am to cover approx 3 hours per week. Yesterday was around an hour so half an hour today maximum. Here we go!
Reading Modes
This is the code that Pasan has created which I've just copied and pasted:
Anyway, just to reiterate my plan - I am to cover approx 3 hours per week. Yesterday was around an hour so half an hour today maximum. Here we go!
Reading Modes
This is the code that Pasan has created which I've just copied and pasted:
mport UIKit
enum ReadingMode {
case day
case evening
case night
var statusBarStyle: UIStatusBarStyle {
switch self {
case .day, .evening: return .default
case .night: return .lightContent
}
}
var headlineColor: UIColor {
switch self {
case .night: return UIColor(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
case .day, .evening: return UIColor(red: 16/255.0, green: 16/255.0, blue: 16/255.0, alpha: 1.0)
}
}
var dateColor: UIColor {
switch self {
case .day, .evening: return UIColor(red: 132/255.0, green: 132/255.0, blue: 132/255.0, alpha: 1.0)
case .night: return UIColor(red: 151/255.0, green: 151/255.0, blue: 151/255.0, alpha: 1.0)
}
}
var bodyTextColor: UIColor {
switch self {
case .day, .evening: return UIColor(red: 1, green: 1, blue: 1, alpha: 1)
case .night: return UIColor(red: 151/255.0, green: 151/255.0, blue: 151/255.0, alpha: 1.0)
}
}
var linkColor: UIColor {
switch self {
case .day, .evening: return UIColor(red: 132/255.0, green: 132/255.0, blue: 132/255.0, alpha: 1.0)
case .night: return UIColor(red: 161/255.0, green: 161/255.0, blue: 161/255.0, alpha: 1.0)
}
}
}
let titleLabel = UILabel()
func setupDisplay(with mode: ReadingMode) {
titleLabel.textColor = mode.headlineColor
}
setupDisplay(with: .night)
setupDisplay(with: .day)
Another thing - someone else agrees with me that the computed properties challenge should have been after this video! Not sure how well put together this course is....
So I don't really get the point of this. Computed Properties with enums makes sense, but again I've done that now with the last challenge which was impossible at the time!
Quiz - Type and Computed Properties
Got all questions right except for one - that computed properties can compute as well as store a value. So this is false - this must mean that they are only for computing a value.
Lazy Stored Properties
The downside with CP is that they CANNOT stored values. That confirms the above.
OK, so if we want a stored property that depended on init? New kind of property - lazy stored!
Lazy SP is one whose initial value is not calculated until the first time we call it on an instance - that we use it.
class ReadLater {
lazy var session: URLSession(configuration: .default)
}
So what is the point? Well init of some objects is complex and uses memory. We don't want to create it until we really use it. So it is good for not wasting computational power. OK.
Like a computed property, it needs to be a variable. So it's for saving resources the whole point of lazy.
Property Observers
Property observers allow us to observe and respond to changes in property values.
Here is Pasan's code:
import PlaygroundSupport
import UIKit
class ViewController: UIViewController {
let slider = UISlider()
var value: Double = 0.0 {
willSet {
print("Old value: \(value)")
}
didSet {
view.alpha = CGFloat(value)
print("New value: \(value)")
}
}
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor(red: 30/255.0, green: 36/255.0, blue: 40/255.0, alpha: 1.0)
// Add target-action pattern for value changed event
slider.addTarget(self, action: #selector(viewController.slide(sender:)), for: .valueChanged)
}
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
// Programmatically add constraints to setup layout
view.addSubview(slider)
slider.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
slider.centerXAnchor.constraint(equalTo: view.centerXAnchor),
slider.centerYAnchor.constraint(equalTo: view.centerYAnchor),
slider.heightAnchor.constraint(equalToConstant: 30),
slider.widthAnchor.constraint(equalToConstant: 400)
])
}
// Method for target-action
@objc func slide(sender: UISlider) {
value = Double(sender.value)
}
}
let viewController = ViewController()
PlaygroundPage.current.liveView = viewController.view
He uses the PlaygroundSupport Foundation. This allows us display views.
*The assistant editor bit is not showing the same thing as Pasan. Oh well, I will continue anyway.
The property observers we have are didSet and willSet.
DidSet - called immediately after we assign a value to the stored property. It is executed every time after the value has been assigned.
WillSet - called before we change the underlying value.
PO allow us to write code that is dependent on a property being changed.
You can add PO to any stored property apart from lazy SPs and Computed Properties.
Challenge
In the editor, I've created a UIViewController subclass,
TemperatureController
that contains a single property - temperature
.
Your task is to add a
didSet
property observer to temperature and set the view's background color depending on value of the temperature.
For example, if the temperature is greater than 80, set the view's background color to
UIColor.red
. Similarly if the temperature is less than 40, set it to blue color, otherwise set it to green color.
Note: For changing the view's background color, there's example code in
viewDidLoad()
Here's what I've got:
willSet {
view.backgroundColor = .green
}
didSet {
if temperature > 80 {
view.backgroundColor = .red
} else if temperature < 40 {
view.backgroundColor = .blue
} else { view.backgroundColor = .green
}
}
}
WOOHOO! Did this without any help at all! First I had a switch statement in, but switched self, which may have caused the problem. I changed that to if and it's worked! I actually forgot about including willSet, which was implied but not stated in the instructions!
Cool, just the quiz to go...
All correct - great!
Well, next time it's all about initialization. Before that, I'm going to do as promised and read up more on properties. Brainwave - the eBook that Ray included with his course was actually pretty good. So let's see what it says about properties...
OK a couple of clarifications...
Computed Properties - these do not actually hold any memory until they are calculated.
“You can assign values to properties as long as they’re defined as variables (and the instance is stored in a variable as well). When Grace married, she changed her last name:
person.fullName = "Grace Hopper"
let grace = person.fullName // Grace Hopper
If you’d like to prevent a value from changing, you can define a property as a constant instead using let:
struct Contact {
var fullName: String
let emailAddress: String
}
// Error: cannot assign to a constant
person.emailAddress = "grace@gmail.com”
Excerpt From: By Ray Wenderlich. “iOS 11 and Swift 4 for Beginners.” iBooks.
OK, so another couple of key points about assigning values to properties (as long as they're not lets).
Default Values - this is giving an actual value to a var/let - most times you won't do this but could happen. Again the value can be changed AS LONG AS IT'S A let!
“The computed property you wrote in the previous section is a called a read-only computed property. It has a block of code to compute the value of the property, called the getter. It’s also possible to create a read-write computed property with two blocks of code: a getter and a setter. This setter works differently than you might expect. As the computed property has no place to store a value, the setter usually sets one or more related stored properties indirectly:”
Excerpt From: By Ray Wenderlich. “iOS 11 and Swift 4 for Beginners.” iBooks.
So the whole get/set thing - set is like a default value, if when creating an instance you don't want to use the computed property. Get is read-only. newValue is a default value that's used, unless a special let constant is created.
Type properties - yep, these are ones that cannot be accessed via the instance but on the type itself. Static is used. So you can still retrieve it but not like a stored property.
Property Observers - willSet - property about to be changed; didSet - after property has been changed. You only do this with stored properties, which are var. They are not called on init, only once you have an instance that is already initialised.
Lazy - for when you don't want memory to be used. Don't know when to actually use these.
A summary from Ray for properties:
- “Properties are variables and constants that are part of a named type.
- Stored properties allocate memory to store a value.
- Computed properties are calculated each time your code requests them and aren’t stored as a value in memory.
- The static keyword marks a type property that’s universal to all instances of a particular type.
- The lazy keyword prevents a value of a stored property from being calculated until your code uses it for the first time. You’ll want to use lazy initialization when a property’s initial value is computationally intensive or when you won’t know the initial value of a property until after you’ve initialized the object.
”
Excerpt From: By Ray Wenderlich. “iOS 11 and Swift 4 for Beginners.” iBooks.
So that's helped to clarify things! Next time, I'm going to have this eBook, along with the Swift main eBook open as well. Good stuff today!
*One point I can't ignore - I predicted half an hour's worth and I've gone for 1 hour and 20....good in a way but when I'm properly back at work that won't be tenable! Anyway, next time - initialisation!
Comments
Post a Comment