Lynda Course - Swift 5 Essential Thinking (Part 7)
Last part of the course! I'm going spend around half an hour now on this and the rest tomorrow, if/when needed. Let's do this!
Start time - 21:00
Enumerations
All of the declaring and creating no problems. I want to see the use of assigning values etc. That bit I'm not so sure about.
Start time - 21:00
Enumerations
All of the declaring and creating no problems. I want to see the use of assigning values etc. That bit I'm not so sure about.
// Declaring an enum
enum GameState {
case Completed, Initialzing, LoadingData
}
// Storing and switching on an enum value
var currentState = GameState.Completed
switch currentState {
case .Completed:
print("All tasks complete")
case .Initialzing:
print("Init in process")
case .LoadingData:
print("Data is loading")
}
Raw and Associated Values
You can do this -
enum NonPlayableCharacters: String {
case Villager
case Blacksmith
case Trader
}
But no other info - quite limited. Can be accessed with using .rawValue.
*Paused for 10 minutes
enum NonPlayableCharacters: String {
case Villager = "Focused on gathering resources"
case Blacksmith = "Prepares weapons"
case Trader = "Trades goods"
}
// Associated values
enum PlayerState {
case Alive
case Unconscious(level: Int)
case Expired(debugError: String)
func evaluateCase() {
switch self {
case .Alive:
print("Still alive!")
case .Unconscious(let restartLevel):
print("Restart at \(restartLevel)level")
case .Expired(let message):
print(message)
}
}
}
PlayerState.Unconscious(level: 4).evaluateCase()
OK some good stuff there! A couple of key things - the argument label and type. And a switch statement within a function.
You can add a type with the the case and with the
Have to stop now. But will do more tomorrow.
Stopped at 21:28 (18 minutes so far)
Restarted 2 days later at 12:53
OK I'm back! And ready to complete this course! At that point, I will look to see whether I should go with this subscription, or look more into Reinder's course... Anyway, last bit!
Introducing Protocols
I get the point of these - blueprints for behaviour; a contract that then something else has to fill...but have always wanted more practice. So here we go!
Protocols can be adopted by a class or struct independently.
The benefit of protocols has always been unclear to me. But I'm starting to see it... you can have different classes inheriting different aspects of behaviour, rather than having them all in the same class/subclass.
Using Extensions
Extending the Collectable protocol...
Restarted 2 days later at 12:53
OK I'm back! And ready to complete this course! At that point, I will look to see whether I should go with this subscription, or look more into Reinder's course... Anyway, last bit!
Introducing Protocols
I get the point of these - blueprints for behaviour; a contract that then something else has to fill...but have always wanted more practice. So here we go!
Protocols can be adopted by a class or struct independently.
// Declare a protocol
protocol Collectable {
var name: String { get }
var price: Int { get set }
init(withName: String, startingPrice: Int)
func collect() -> Bool
}
// Protocol adoption
class Item: Collectable {
var name: String
var price: Int
required init(withName: String, startingPrice: Int) {
self.name = withName
self.price = startingPrice
}
func collect() -> Bool {
print("Item collected!")
return true
}
}
let potion = Item(withName: "Mead", startingPrice: 33)
potion.collect()
The benefit of protocols has always been unclear to me. But I'm starting to see it... you can have different classes inheriting different aspects of behaviour, rather than having them all in the same class/subclass.
Using Extensions
Extending the Collectable protocol...
extension Collectable {
var priceIncrease: Int {
return self.price * 10
}
init(name: String) {
self.init(withName: name, startingPrice: 100)
}
func collect() -> Bool {
print("Could not be collected")
return false
}
}
So this could have been done earlier but the difference is all the implementation is done, which can't be done with the protocol blueprint.
extension String {
func fancyDebug() {
print("This string has \(self.count) characters")
}
}
antidote.name.fancyDebug()
Native types can be extended too. They can be extended with functions, computed properties and initialisers.
Throwing Errors
// Error enum
enum DataError: Error {
case EmptyPath
case InvalidPath
}
// Throwing functions
func loadData(path: String) throws {
guard path.contains("/") else {
throw DataError.InvalidPath
}
guard !path.isEmpty else {
throw DataError.EmptyPath
}
}
There we go! The difference between throwing and handling errors is delegation - who does it and where. The above is using a specific function with a specific enum created to contain the errors following the error protocol.
Error Handling
// Do-Catch statements
do {
try loadData(path: playerDataPath)
print("Data successful!")
} catch is DataError {
print("Invalid or empty path")
} catch {
print("Unknown error")
}
So in error handling we have the do/try/catch, rather than the throws keyword. But we need to use the function that has already been made (loadData)
if let dataLoaded = try? loadData(path: playerDataPath) {
print("Data fetch went well")
}
// Propagating errors
func propogateDataError() throws {
try loadData(path: playerDataPath)
}
do {
try propogateDataError()
print("Data successful")
} catch DataError.EmptyPath {
print("Empty path detected")
} catch DataError.InvalidPath {
print("Invalid path detected")
} catch {
print("Unknown error")
}
There we have it! Several different ways to handle errors. I am going to do the challenge in a bit, then before doing anything else, review this entire course. Practise certain aspects so that I can then be confident that I'm au fait with this confident
Stopped at 13:31 (38 minutes; total of 56)
Comments
Post a Comment