• Home
  • VMware QuickDocs
    • Getting Started with VMware Cloud Foundation
    • VMware General
    • vSphere
    • vSAN
    • Horizon
    • NSX
    • vRealize Suite (renamed to Aria Suite)
    • Aria Suite
      • Aria Automation
      • Aria Operations
      • Aria Operations for Logs
      • Aria Automation Orchestrator
    • Podcasts
  • Home Lab
  • VMware Stickers
  • mac OS Tips
  • About Me
    • Privacy Policy
    • Cookie policy
Cybersylum

Cybersylum

  • Home
  • VMware QuickDocs
    • Getting Started with VMware Cloud Foundation
    • VMware General
    • vSphere
    • vSAN
    • Horizon
    • NSX
    • vRealize Suite (renamed to Aria Suite)
    • Aria Suite
      • Aria Automation
      • Aria Operations
      • Aria Operations for Logs
      • Aria Automation Orchestrator
    • Podcasts
  • Home Lab
  • VMware Stickers
  • mac OS Tips
  • About Me
    • Privacy Policy
    • Cookie policy

My Notes – Introduction to Swift

byArron King 02.21.2024 Swift Tech Learning

Once in a while I find it useful to stretch myself in a new direction.  Usually this is to scratch an itch for a pet project that I am interested in.  I also think this can help break the rut we can all to easily fall into.  To that end, I spent my 3 day weekend learning the Swift programming language.  I used a Pluralsight course called Swift Fundamentals.

Full Disclosure
Pluralsight did not sponsor this post. I do get access to Pluralsight through their participation in the VMware vExpert program. I have been selected to be a vExpert for many years and they have been a constant supporter of that program and many others. I have found their content very helpful as I keep my skills up-to-date. They have a very wide variety of training topics. I found their Swift Fundamentals course extremely engaging. If you want to grow your skills – I highly recommend that you check them out.

What this page is – and isn’t

This page is a collection of notes that I took while going through the course. My intention is to review what I have learned about Swift when I have the time to write a real app.

This page is not a tutorial or guide.  While I hope it contains enough illustrative snippets to be a reference, it will probably not serve as a tool to teach someone who has never programmed before.

Getting Started

Xcode is the best tool to use when learning Swift.   It is free to download and use.  It has a very useful feature called the Xcode Playground.  This is an area where you can type and execute code iVisual of Swift Playground with code and results on same screenn iterative steps to try out complex logic or new programming techniques before using them in a larger program.  I found this tremendously useful as I went through the course.  I am a hands-on learner and I frequently paused the training so I could type out the code in my Playground to make sure I had the syntax down.  You can actually take the notes below and paste them into an Xcode playground on your own computer.

Shoutout to a great Teacher - Mr. Mike Freese
There are many people who influence our lives.  They don’t often get the recognition they deserve.  I have been fortunate to have many great teachers and individuals who have helped shape the person I am.  One of those individuals is Mike Freese.

While taking this course and using the Playground, I was reminded of a notetaking style he taught when I was a student.  Mr. Freese inspired curiosity and was a great teacher.

My Notes – Introduction to Swift

This code is also available on GitHub.

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
//variables (mutable)- Swift is strongly typed
 
//inferred type
var greeting = "Hello, playground"
var age = 21
var activeMembership = true
 
//Type Annotation - explicit type
var fooBar: String
 
// let makes constant (ummutable)
let maxAge = 5
let newAge = maxAge + age
let bar: String
bar = "this is a test" // can initialize constants this one time
//bar = "this should break" - this will generate an error
 
//Optional variables
var middleName: String? //optional value - has value of Nil (keyword) - Nil is not equal to Null
middleName = "Ryan"
middleName = nil // can assign optional variable the value of Nil
var lastName = "Doe"
//check fo Nil
if middleName == nil {
     
}
 
if middleName != nil {
    //forced unwrap - must check for value first -doing this with a Nil value will cause runtime error
    var foo = middleName!
    print(foo)
}
//more concise method of checking - optional binding
if let myMiddleName = middleName {
    print (myMiddleName)
} else {
    // theres no value
}
age = age + maxAge
 
//data type conversion- must explicitly write code to do it-no automatic conversion of data types - for safer code
 
var score=1
var highScore=100.0
 
var newHighScore = Double(score)
 
// Arrays
// - Array - numerical index (0 based)
// - Dictionary - key-value pair
// - Set - unordered collection
// there are more complex datastructures - these 3 are built into the language
 
var myNames = ["John", "Jane", "Mary"]
var myAges = [1,2,3,4]
print (myNames[1])
myNames[2] = "Iron Man"
myNames.count
myNames.append("Flash")
myNames.remove(at: 3) //also removeall,removefirst, removelast
 
var myCars: [String] = []   //array of strings - initialized as empty
myCars.append("Mustang")
 
print(age - 5)
print ("foo")
print ("foo",terminator: "")
print ("foo",terminator: "-")
 
 
// operators
 
// standard operations work as expected  + - * = /
// icrement/decrement not supported -- ++
// Special operators  ?? ... ..< -> ! ? ===
 
// program control
var myscore = 100
if myscore > 10 {
    //true
} else {
    //false
}
 
/* conditon must be true or false - zero or not zero does not work in swift
 a==b
 a!=b
 a>b  < <= >=
 logical AND
 a==b &&  c!=d
 logical OR
 a> b || a>c
 can use parens for complex situations
*/
 
// switch statements
 
var shoeSize: Int
shoeSize = 8
switch shoeSize  {
case 1,2,3:    //list
    print("between 1 and 3")
case 15...20:  //range
    print("case between 15 and 20")
case  5:
    print("five")
case 4:
    print ("four")
case _ where shoeSize > 6: //found on Internet
    print ("more than 6")
default:
    print("something else")
}
 
 
//range operators
// 1...10 - 1-10    closed range
// 1..<10 - 1-9     half open - zero based arrays
// range always goes up
// single step increments
// stride - function to increment in jumps - ie 16 at a time - 3 parameters - can move in reverse
/*
    from - start
    through - end
    by - increment
 */
 
 
//loops - 3 ways
/*
    while
    repeat/while (replaces do-while)
    for/in
 */
var items=3
 
while items < 10 {
    print("something")
    items += 1
}
 
repeat {
    print ("something")
    items += 1
} while items < 10
 
let myColors = ["red","blue","green"]
 
for thisColor in myColors {
    print (thisColor)
}
 
//string interpolation (ie: hacking up strings)
var trackName = "Hail to the King"
var artistName = "Avenge Sevenfold"
var duration = 228
let message = "Now Playing \(trackName) by \(artistName) which is \(duration / 60)m  \(duration % 60)s long"
 
//functions & methods
 
func showMessage(firstName: String, lastName: String) -> String {
    //parens are for params and required - even if no params
    //params are immutable (constant)
    print("hello \(firstName) \(lastName)")
     
    return "all done"
}
 
var myResult = showMessage(firstName: "Bob", lastName: "King")
 
 
// function with "-> Void" returns nothing (optional should revist module 4 section3 to learn more)
 
//call function but don't care about return value
_ = showMessage(firstName: "Jane", lastName: "Doe")
 
//un-named input params - underscore with space - cannot use param name when calling
//not common or in swift mindset (clarity)
func showMessage2(_ firstName: String, lastName: String) -> String {
    //parens are for params and required - even if no params
    //params are immutable (constant)
    print("hello \(firstName) \(lastName)")
     
    return "all done"
}
 
//different param name on function call vs inside function (from to:type)
func showMessage3(firstName givenName : String, lastName surName: String) -> String {
    //parens are for params and required - even if no params
    //params are immutable (constant)
    print("hello \(givenName) \(surName)")
     
    return "all done"
}
 
var myResult3 = showMessage3(firstName: "John", lastName: "Doe")
 
 
// Deeper Dive on data types
 
//enumerations - data types begin with Upper Case letter
enum MediaType {
    case book
    case movie
    case music
    case game
    // or case book, movie, music, game
}
 
var itemType: MediaType
itemType = MediaType.game
 
//shorthand
var newItemType: MediaType
newItemType = .book
 
switch newItemType {
case .movie:
    print ("movie")
case .game:
    print ("game")
default:
    print ("book, or music")
}
 
// raw value
//      define as a string, can access as .rawValue
// associated values
//      different data types defined in enum declaration
 
enum newMediaType {
    case movie(String)
    case music(Int)
    case book(String)
}
 
var firstItem: newMediaType = .movie("Comedy")
var secondItem: newMediaType = .music(120)
 
switch firstItem {
case .movie(let genre):
    print("It's a \(genre) movie")
case .music (let bpm):
    print("The music is \(bpm) beats per minute")
case .book (let author):
    print("It's by \(author)")
}
 
 
// Structures (struct)
 
struct Movie {
    // properties
    var title: String
    var director: String
    var releaseYear: Int
    var genre: String
     
    //methods   
    func summary() -> String {
       return "The movie \(title) was directed by \(director).  It is an \(genre) movie and was released in \(releaseYear)."
    }
}
 
var favMovie = Movie(title: "Diamonds Are Forever", director: "Guy Hamilton", releaseYear: 1970, genre: "Action")
 
print (favMovie.title)
favMovie.releaseYear = 1971    //actual release year ;-)
 
print(favMovie.summary())
 
 
//Dictionaries - group of key-value pairs - in other languages could be Map, Symbol Table, Associative Array, or Dictionary
// keys and values have distinct (and potentially differnt types)
 
var airlines = ["SWA": "Southwest Airlines",
                "BAW": "British Airways",
                "DEL": "Delta Airlines"]
 
 
var employees = [101: "John Doe",
                 20313: "Jane Doe",
                 23234: "Tony Stark"]
 
if let result = airlines["SWA"]  { //returns optional value as no guarantee of match
    print(result)
} else {
    print("No Match Found")
}
 
//add or change - if no match found - add
airlines["DVA"] = "Discovery Airlines"
 
airlines["DVA"] = nil  //removes key value pair
 
for (code, airline) in airlines {   //syntax is called a tuple
    print("\(code) - \(airline)")
}
print("done")
 
 
// tuple means several elements gathered together - quintuple, sextuple, etc
 
let cameraType = "Canon"
let photoMode = true
let shutterSpeed = 60
let iso = 640
let aperture = "f1.4"
 
var basicTuple = (aperture, iso, cameraType)
print(basicTuple)
 
//useful to return multiple values from a function
 
func tupleExample() -> (name: String, age: Int) {
    return ("test string", 4)
}
 
let tupleResult = tupleExample()
print(tupleResult)
print(tupleResult.0)
print(tupleResult.name)
let (returnValueOne, returnValueTwo) = tupleResult
print(returnValueTwo)
 
//Closures
// take lines of code and group it together to use somewhere else in our program
// block of code in {} has no name
// do not call it - you pass it
// a function is a closure with a name
//
// a bit challenging - very concise way of writing code
 
struct Book {
    var title: String
    var authorLastName: String
    var authorFirstName: String
    var readingAge: Int
    var pageCount: Int
}
 
let book1 = Book.init(title: "The Hobbit", authorLastName: "Tokien", authorFirstName: "J.R.R", readingAge: 12, pageCount: 300)
let book2 = Book.init(title: "Centaur Isle", authorLastName: "Anthony", authorFirstName: "Piers", readingAge: 9, pageCount: 320)
let book3 = Book.init(title: "Enchanter's End Game", authorLastName: "Eddings", authorFirstName: "David", readingAge: 14, pageCount: 275)
let book4 = Book.init(title: "Ender's Game", authorLastName: "Card", authorFirstName: "Orson Scott", readingAge: 19, pageCount: 300)
 
let allBooks = [book1, book2, book3, book4]
 
// some functions requires closures
 
//going to sort - using SortedBy
 
/*  - very verbose closure - helpful to learn basics but not used in practice
 func compareTwoBooks (firstBook: Book, secondBook: Book) -> Bool {
    if firstBook.readingAge <= secondBook.readingAge {
        return true
    } else {
        return false
    }
}
 
 
let ageSortedBooks = allBooks.sorted(by: compareTwoBooks)
ageSortedBooks
  
 */
 
 
//more normal closure - closure code in braces - inside of .sorted call
// still very verbose - gets much more simplified in practice
/*
let ageSortedBooks = allBooks.sorted(by: {
    (firstBook: Book, secondBook: Book) -> Bool
    in
    if firstBook.readingAge <= secondBook.readingAge {
        return true
    } else {
        return false
    }
})
ageSortedBooks
  
*/
// trailing closure - used when closure is only or last argument -
//removes much redundant syntax - return
 
let ageSortedBooks = allBooks.sorted { $0.readingAge <= $1.readingAge }
ageSortedBooks
 
let booksForUnder14s = allBooks.filter { $0.readingAge < 14}
booksForUnder14s
 
 
// Classes and Objects
class Appliance {
    //properties
  // can initialize at declaration -   var manufacturer: String = ""
    var manufacturer: String
    var model: String
    var voltage: Int
    var capacity: Int?
     
    //initializer
    init() {
    //specializer method - called automatically when instantiated
    //takes no parameters
        self.manufacturer = "default manufacturer"
        self.model = "default model"
        self.voltage = 120
    }
    //can have addtional initializers as long as they have different parameter signatures
     
     
    //deinitializer
    deinit {
        // not needed most of the time.  can be used to do clean up.  only allowed in a class - not in a struct
        //swift uses Arc - Automatic Reference Coutning to automatically cleanup and deallocating memory - deinit called at this time
    }
     
    //methods
    func getDetails() -> String {
        var message = "This is the \(self.model) from \(self.manufacturer)."
        if self.voltage >= 220 {
            message += "This model is for European usage."
        }
        return message
    }
     
     
}
 
var kettle = Appliance()
kettle.manufacturer = "Samsung"
//kettle.model = "TeaMaster 5000"
kettle.voltage = 120
print(kettle.getDetails())
 
 
/* difference between structs and classes
  
    with structs, if value is assigned to a new variable (or constant) or passed into a function - the value is copied
    will classes, those values are not copied - they are passed as a reference
  
  
    the === (identity operator) can help verify if two different instances(variables) are pointing to the same thing
  
*/
  
  
class Toaster: Appliance {
    //note case of class name and : (: indicates inheritance)
    //this is a subclass of superclass Appliance
 
    // new properties
    var slices: Int
     
    override init() {
        //inherited classes could already have an init method and must user override - original init still called (first) thne this init
        self.slices = 2
        // super. can be used to over ride the original init
        // keyword final can be used in super class to prevent changes by subclasses
 
    }
     
    //new method
    func toast() {
        print("Irradiating now...")
    }
     
}
 
 
var myToaster = Toaster()
myToaster.manufacturer = "AcmeCorp"
myToaster.model = "Carbonizer"
myToaster.getDetails()
myToaster.toast()
 
 
// Extensions
 
//strings
 
extension String {
    func removeSpaces() -> String {
        let filteredCharacters = self.filter {$0 != " "}
        return String(filteredCharacters)
    }
}
 
let album = "Decks and drums and rock and roll"
let phrase = "Love is now here"
 
print(album.removeSpaces())
print(phrase.removeSpaces())
 
 
// Stored Properties - Computed Properties
class Player {
    // stored properties
    var name: String
    var livesRemaining: Int
    var enemiesDestroyed: Int
    var penalty: Int
    var bonus: Int
     
    //computed property
    var score: Int {
        get {
         return (enemiesDestroyed * 1000) + bonus + (livesRemaining * 5000) - penalty
        }
        //can also have set {} to set this property - not useful in this specific case
        // if no get{} or set {} - swift assumes get - very concise
    }
 
    //initialize
    init(name: String) {
        self.name = name
        self.livesRemaining = 3
        self.enemiesDestroyed = 0
        self.penalty = 0
        self.bonus = 0
    }
}
 
let newPlayer = Player(name: "Ava")
newPlayer.enemiesDestroyed = 327
newPlayer.penalty = 872
newPlayer.bonus = 48000
print("The final score for \(newPlayer.name) is \(newPlayer.score)")
 
 
 
 
// Protocols
/* swift is a protocol-oriented programming lanuage
 inheritance can be done; but not common - more common to write extensions
  
 protocol here is more about Standard operating procedure in the language or frameworks vs https/tcp/etc
 
protocols are adopted - this is done on class declaration line.  can adopt multiple protocols
  
 */
 
class Player2: CustomStringConvertible {  //adopting the protocol
    // stored properties
    var name: String
    var livesRemaining: Int
    var enemiesDestroyed: Int
    var penalty: Int
    var bonus: Int
     
     
    //required byt his specific protocol - this "conforms" to the protocol
    var description: String {
        return "Player \(self.name) has a score of \(self.score) and \(self.livesRemaining) lives remaining."
    }
     
    //computed property
    var score: Int {
        get {
         return (enemiesDestroyed * 1000) + bonus + (livesRemaining * 5000) - penalty
        }
        //can also have set {} to set this property - not useful in this specific case
        // if no get{} or set {} - swift assumes get - very concise
    }
 
    //initialize
    init(name: String) {
        self.name = name
        self.livesRemaining = 3
        self.enemiesDestroyed = 0
        self.penalty = 0
        self.bonus = 0
    }
}
 
let mynewPlayer = Player2(name: "Joey")
mynewPlayer.enemiesDestroyed = 327
mynewPlayer.penalty = 872
mynewPlayer.bonus = 48000
print("The final score for \(mynewPlayer.name) is \(mynewPlayer.score)")
 
//print the instance of Player2 - to invoke the desscription property - required by the CustomStringConvertible protocol
print(mynewPlayer)
 
//Define a protocol
protocol MyProtocol {
    //what methods are required
    func showMessages()
     
    //what properties
    var name: String {get set} //get-read set-write
}
 
 
//handling errors in swift - adopting that protocol
 
//dealing with recoverable errors
/*
 define error - waht is it
 throw it - where and when will it happen
 handle it - recover
  
swift does not provide a built-in error class
 */
 
 
enum ServerError: Error {      // define the error
    case noConnection
    case serverNotFound
    case authenticationRefused
     
    //no parameters or methods to conform
     
}
 
func checkStatus(serverNumber: Int) throws -> String { // note the keyword throws
     
    switch serverNumber {
    case 1:
        print("You have no connoection.")
        throw ServerError.noConnection
    case 2:
        print("Authentication failed.")
        throw ServerError.authenticationRefused
    case 3:
        print("Server is up and running.")
    default:
        print("Can't find that server.")
        throw ServerError.serverNotFound
    }
    return "Success!"
}
 
// normal function call - but since it can throw an error must handle differently
//let result = checkStatus(serverNumber: 1)
//print(result)
 
do {
    let result = try checkStatus(serverNumber: 4)
    print(result)
} catch ServerError.noConnection {
    //no connection
    print("No Connection")
} catch ServerError.authenticationRefused {
    //authentication error
    print("Your password is wrong.")
} catch {
    print("The problem is : \(error)")
}
 
// if error isn't super important you can make it optional
 
let result2: String?
 
/* long form
  
 do {
    result2 = try checkStatus(serverNumber: 3)
} catch {
    result2=nil
}
  
 
 
if result2 != nil {
    print(result2!)
}
 */
 
if let result3 = try? checkStatus(serverNumber: 1) {
    print(result3)     //will return nil if no error
}
 
 
// Guard and Defer - control flow statements
 
//Guard - close in spirit to if/else
 
 
func processTrack(trackName: String?, artist: String?, duration: Int?) {
     
    //need to check if the params are nil.  can do with multiple nested if statements (pyramid of doom) but clunky
     
    guard true else {
        //what we do if this isn't true
        //need to have hard exit - return /throw / break
    }
     
     
    /*
     guard let unwrappedname = trackName else { return } - exits if trackName == nil
     */
 
     
// Defer
    /*
    func processCart (myCart: ShoppingCart) {
         
        //open the resource
        myCart.open()
        defer {
        //this block of code will always be called before this funciton exits
            myCart.close()
        }
        other lines of code
    }
    */
}

Share this:

  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on LinkedIn (Opens in new window) LinkedIn

Hybrid vSphere SSL Certificate Replacement

Leave a Reply Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Search

Disclaimer

The content and opinions on this site belong to me - not my employer.

You are welcome to use any ideas or code from this site. You have the responsiblity to test these before using in a production environment.

Upcoming Events

  • Wed
    22
    Oct
    2025

    Cincinnati VMware VMUG UserCON

    Save The Date!

    The VMware VMUG UserCON returns to Cincinnati in October 2025

Categories

Aria Automation Aria Operations for Logs Before I Forget Certificates Education Home Lab Horizon View Importing vSphere Networks into Aria Automation Linux MacOS Networking PowerCLI Professional Development Scripting Swift TechBITS Tech Learning Update Manager VCSA VMUG VMware VMware Cloud on AWS VMware Portal VMware Tools VMworld vSphere vToolBelt Windows 10

Archives

Category

Aria Automation Aria Operations for Logs Before I Forget Certificates Education Home Lab Horizon View Importing vSphere Networks into Aria Automation Linux MacOS Networking PowerCLI Professional Development Scripting Swift TechBITS Tech Learning Update Manager VCSA VMUG VMware VMware Cloud on AWS VMware Portal VMware Tools VMworld vSphere vToolBelt Windows 10
Proudly powered by WordPress | Theme: Showme by NEThemes.
 

Loading Comments...