Skip to content

Swift crash course for C# developers. Should help evaluate the language. Some notes I compiled why embarked on this journey.

Notifications You must be signed in to change notification settings

shinylightdev/swift-for-cs-devs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 

Repository files navigation

Swift for the C# Developer

Highlights

Top level highlights of developing with .NET vs iOS.

  • Swift is a replacement for Objective-C.
  • Swift came out in 2014 and currently in version 5 as of 3/25/2019. You need latest version of macOS (Mojave) to run.
  • Swift can use the following UI Frameworks:
    • Cocoa for macOS
    • Cocoa Touch for iOS
  • Null is Nil
  • Semicolons are optional and generally not used
  • Rather than always checking for nulls, ? and ?? symbols are used
  • Parameter names are by default required when calling a function, unless using the _ symbol - upon declaration
  • There’re no namespace keywords for organizing classes, but several design patterns to - simulate the same thing, one is have a class inside a class.
  • There’s no new keyword when creating an object. Just called its constructor method.
  • There’s no intermediate compilation as IL that runs in the .NET framework. The Swift - compiler turns it into an executable binary that runs natively by the OS. This generally - translates to faster performance.
  • Xcode nowhere as robust as Visual Studio.
    • Auto Complete Not even close
    • Has as many quirks as Visual Studio, especially in the Interface Builder
  • Lots of Swift code 1.0, 2.0, 3.0 in the wild that is not compatible with 4.0.
  • To develop iOS apps, know the following:
    • Xcode
    • Swift
    • Cocoa Touch (combination of Foundation and UIKit)
    • SQLite
    • MVC
  • Package Managers:

Logo

picture 2

Comparing Terminology

Swift vs C#

Not all terms are exactly equivalent. Some are in the vicinity.

Syntax Description
Swift C#
Paragraph Text
Swift C#
Closure Lambda
Protocol Interface
Class Class
Nil Null
No new keyword new keyword used when creating object
Type Inference Type Inference
No LINQ equivalent, but functionality can be emulated via the functions filter(), match(), and closures Also, this: https://github.com/mythz/swift-linq-examples
Access Control Access Modifiers

Other Swift terminology

iOS and .NET Terminology

Not all terms are exactly equivalent. Some are in the vicinity. Programming for the iPhone closer resembles programming a desktop app than web app.

iOS Development .NET Development
CocoaPods, Carthage, Swift Package Manager Nuget
XCode Visual Studio
Cocoa Touch + UIKit WPF
XIB XAML
Controller Action / Outlet Controller Action / Property
Swift Intermediate Language Intermediate Language
LLVM IR
https://swift.org/compiler-stdlib/
JIT compiled via .NET Runtime
Storyboard (in XIB) View (in XAML)
Xcode Project File Visual Studio Project File
Xcode Workspace
More info about workspaces: https://developer.apple.com/library/archive/featuredarticles/XcodeConcepts/Concept-Workspace.html
Visual Studio Solution
CoreData, SQLite, Realm
Comparison: https://rollout.io/blog/ios-databases-sqllite-core-data-realm/
Entity Framework, SQL Server Express, Local DB

iOS and macOS Architectures

picture 3

https://medium.com/@anuradhs/ios-architecture-a2169dad8067

For Comparison, here’s the macOS Architecture

http://www.knowstack.com/cocoa-layered-architecture-for-mac-osx/

picture 4

More details here: https://en.wikipedia.org/wiki/Architecture_of_macOS

Basics

Commenting

Commenting out the printing of “Hello World.”

// print("Hello World")
/* 
Hi there.
*/

Declaring a variable

var n: Int

var firstName: String? // Optional
var lastName: String = "" // Not optional, but set to Empty String

Declaring an optional (we say this is wrapped) variable (“nullable” in C# terms)

var n1: Int?

Declaring an optional variable and assigning to 2600

var n3: Int? = 2600

Declaring an optional variable and assigning to nil (null)

var total: Int? = nil

Declaring a Constant

let magic = 2600

Coalescing 3 variables (wrapped)

var n1: Int?
var n2: Int?
var n3: Int? = 2600

var total = n1 ?? n2 ?? n3
print(total)

Which prints out in the console:

Optional(2600)

Guard Keyword

Helpful when inside a function – used when setting a constant or variable; if the attempt to set goes awry, then it lets you break out early. Imagine the following inside a function:

guard let jsonData = data else { return }

So if jsonData was not able to be set, then it returns (breaks out of the function).

To learn more:

Type Casting

https://medium.com/@abhimuralidharan/typecastinginswift-1bafacd39c99

Conditional downcasting (as?).

Forced downcasting (as!).

let animalObj = livingBeingArray[0] as! Animal // forced downcasting to Animal
let humanObj = livingBeingArray[1] as! Human // forced downcasting to Human

Print to Screen

To print out the actual value, you have to unwrap the variable total with the symbol !

print(total!)

Read from the Console

var firstName: String? // Optional
var lastName: String = "" // Not optional, but set to Empty String

print ("What's your first name?")
firstName = readLine()

print ("What's your last name?")
lastName = readLine() ?? ""

print("Your info:")
print( (firstName ?? "") + " " + lastName)

Arrays

Declaring

var array1 = ["peter", "parker", "spider-man"]

var array2 = [String]()
array2.append("eddie")
array2.append("brock")
array2.append("venom")

print(array2[1])

Conditions

No parenthesis is needed (optional) around condition.

var array1 = ["peter", "parker", "spider"]
if array1.contains("man") || array1.count < 3 {
  print("contains man")
}
else{
  print("doesn't contain man")
}

The same symbols for comparison can be used in Swift: ==, !=, <=, >=, >, <, !

Classes & Generics

Creating a class with a constructor. You use the reserved init() method

class BankAccount {
  var firstName: String  
  init(fn: String) {
    self.firstName = fn
  }
}

Let’s create an array of BankAccounts

var arrayOfBankAccounts = [BankAccount]()

Generics

Here’s another way. Let’s use the class as part of a Generic

var list = Array<BankAccount>()
list.append(BankAccount(firstName: "Parker"))
print(list[0].firstName)

Creating and calling it inline:

class BankAccount{
  var Total: Int?
  init(total: Int?) {
    self.Total = total!
  }
}

print((BankAccount).init(total: 50).Total!)

Another example of Generics

class BankAccount {
  var firstName: String
  
  init(firstName: String) {
    self.firstName = firstName
  }
}

class Person<T> {
  var BA: T?
  var serialNumber = 2600
  
  init(ba: T) {
    self.BA = ba
  }
}

var smBankAccount = BankAccount(firstName: "Peter")
var o = Person<BankAccount>(ba: smBankAccount)

print(o.BA!.firstName)

Inheritance

class SomeSubclass: SomeSuperclass {
  // subclass definition goes here
}

Overriding Method

class Train: Vehicle {
  override func makeNoise() {
    print("Choo Choo")
  }
}

Looping

Various examples:

for i in 0..<10 {
  print(i)
}

var i = 1
while i <= 10 {
  print(i)
  i = i + 1
}

for i in 1...10 {
  print(i)
}

// Don’t need to have iteration variable, 
for _ in 1..<n {
  returnValue += String(total!) + " "
}

Loop through array of words (splits string into array)

var wordsAsString = "Peter Parker Likes Spider-Man"
var wordsAsArray = wordsAsString.split(separator: " ", maxSplits: 999, omittingEmptySubsequences: true)

for word in wordsAsArray {
  print(word)
}

Functions

Let’s add two numbers and return its sum:

func addtwo(n1: Int, n2: Int) -> Int {
  return n1+n2
}

print(addtwo(n1: 50, n2: 60))

Pass an array and print it out to screen

func print_first_index(numbers: [Int], index: Int) {  
  if(index < numbers.count) {
    print(numbers[index])
  }
  else {
    print("index out of range")
  }  
}

print_first_index(numbers: [334,564,24], index: 2)

Let’s make a function that accepts an array of Strings and foreaches names. TAKE NOTE: there’s no parenthesis after the for keyword.

func showNames(names: [String]) {
  for name in names {
    print(name)
  }
}

Anonymous Functions

Passing an anonymous function and running that inside a function.

// Let's pass in a function and immediately
// run that function.
func runIt(myFunction:()-> Void) {
  myFunction()
}

runIt(myFunction: ({
  print("I'm Batman")
}))

Passing an Anonymous function into a Function that accepts a function

func appendTitle(prefix: String, lastName: String, getLastName:(_ lastName: String)-> String) {
  let returnValue = prefix + " " + getLastName(lastName)
  print(returnValue)
}

appendTitle(prefix: "Mr.", lastName: "Parker", getLastName: { (lastName) in return lastName  })

Passing a function name as parameter

// Let's pass in a function and immediately
// run that function.
func appendTitle(prefix: String, lastName: String, getLastName:(_ lastName: String)-> String) {
  let returnValue = prefix + " " + getLastName(lastName)
  print(returnValue)
}


func GetLastName(lastName: String) -> String {
  return lastName
}

appendTitle(prefix: "Mr.", lastName: "Parker", getLastName: GetLastName)
// This accepts function that returns a string
func RunIt(f: () -> String) {
  print(f())
}

// Pass an anonymous function that has no parameter
// but returns a string
RunIt(f: {
  () in return "Yay this worked"}
)

Now let’s create functions and parameters that have parameters:

// This accepts function that returns a string
func RunIt(f: (_ firstName: String, _ lastName: String) -> String) {
  let firstName = "Peter"
  let lastName = "Parker"
  let fullNameWithTitle = "Mr. " + f(firstName, lastName)
  print(fullNameWithTitle)
}

// Pass an anonymous function that has no parameter
// but returns a string
RunIt(f: {
  (firstName, lastName) in
    var fullName: String
    fullName = firstName + " " + lastName
    return fullName
})

Another example:

var list = [12,54,32,234]

var filteredList = list.filter { (x) -> Bool in
  return x > 50

}

var doesItContain = list.contains{ (x) -> Bool in
  return x == 14
}

// No parenthesis around x
var doesItContain = list.contains{ x -> Bool in
  return x == 14
}


// Returns False
print(doesItContain)

Access Control

public class BankAccount{
  var Total: Int?
  init(total: Int?) {
    self.Total = total!
  }
  
  private func showNTimes(n: Int, total: Int?) -> String {
    var returnValue = ""
    for _ in 1..<(n+1) {
      returnValue += String(total!) + " "
    }
    return returnValue
  }
  
  public func showTotal(n: Int) {
    print(ba.showNTimes(n: n, total: self.Total!))
  }
}

var ba = BankAccount(total: 2600)
ba.showTotal(n: 1)

Xcode

This is the official Mac IDE to develop software in: C/C++/Objective-C and Swift for macOS, AppleTV, AppleWatch, iPhone and iPad.

Here’s a screenshot of the IDE while working on an app:

picture 9

Parts of Xcode

Here’s an overview of what some of the panels mean, and how they compare to Visual Studio (VS):

Solution Explorer This would be VS’s solution explorer. The blue icon Project-v1 would be the project file, the orange folder would be the source code directory. The blue folder Assets.xcassets is a packaged file that houses all images (in most cases).

The Products folder that has the .app file would be the /bin folder.

image here 1

Properties When you have the project file selected, you can see its properties. This would be like in VS right-clicking on the project file and inspecting properties.

picture 11

XIB Hierarchy This view is a visual hierarchy of what the XAML would like like. In this case, it’s XIB (XML Interface Builder) markup.

picture 12

Assets This view lets you inspect what is in the Assets directory.

picture 13

Storyboard Here’s the Interface Builder’s toolbox, that has all fields you can drag and drop on your storyboard.

picture 14

Second Tab The second tab for the project properties. It defines what capabilities your app will have – depending on what you choose, for example, it’ll prompt you if you want to allow geolocation services.

picture 15

XIB Markup Code The actual markup code of the XIB file.

picture 16

Xcode Tips

Will give you hints:

picture 5

Shortcut Keys

In the Storyboard Builder: ALT+D = Duplicate any form element

How to trigger an image literal:

File System

Check if a directory exists

import Foundation

let f = FileManager()

if f.currentDirectoryPath == "/Users/daniel.ropbmffkbvctadgdqbonzjls/Build" {
  print("file exists")
}
else {
  print("doesn't exist")
}

Read File Contents

import Foundation

let fileNamePath = "/Users/daniel.romero/Library/Developer/Xcode/DerivedData/HelloThere-hjkkkipbmffkbvctadgdqbonzjls/Build/Products/Debug/Names.txt"
let urlToFile = URL(fileURLWithPath: fileNamePath)

var contents = ""

do {
  contents = try String(contentsOf: urlToFile)
}
catch {
  print("Failed reading from URL: \(fileNamePath), Error: " + error.localizedDescription)
}

print(contents)

Strings

Error Handling

More info:

Storyboards & UI Builder

Whatever UI is built from the UI Builder, can be done through pure code as well. Here are the benefits and drawbacks:

Storyboards vs Code

Storyboard vs Code SpeedRun - Which is Faster? (iOS Swift 4)

But a lot can stem from Xcode being buggy with drag-dropping objects.

Constraints

Every form field has constraints associated to it. For the most part, best practice is to give each constraint 4 properties (x/y, w/h). The following are a MUST WATCH:

Text Fields

Styling a text field: https://medium.com/nyc-design/swift-4-add-icon-to-uitextfield-48f5ebf60aa1

ID Types

What are the differences between Restoration ID and identifier to a UITableViewCell that set in storyboard?

Restoration IDs are used for state restoration, i.e. making your view look like it did when you quit the app-often used for re-creating objects. Storyboard IDs, on the other hand, simply identify objects on the storyboard-these are often used for creating objects.

A restoration identifier is a string that you need to assign to any view controller or view that you want preserved and restored. During state preservation any view controllers or views in the view hierarchy that have a restoration identifier will be saved to disk.

The Identity in the Identity Inspector, are used to instantiate objects from Storyboard.

More details about the Reuse Identifier: https://stackoverflow.com/questions/30473833/what-is-the-purpose-of-the-reuseidentifier

Table View

Best tutorial on the Table View: https://www.youtube.com/watch?v=kCIQM7L-w4Y

Typical boilerplate for implementing a Table View:

import UIKit

class ViewController: UIViewController, UITableViewDataSource {

  @IBOutlet weak var danTableView: UITableView!      
  private var data: [String] = []      
  
  override func viewDidLoad() {
    super.viewDidLoad()

    for i in 0...100 {
      data.append("\(i)")
    }        
    danTableView.dataSource = self;
  }

  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return data.count
  }
  
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell")!        
    let text = data[indexPath.row]        
    cell.textLabel?.text = text        
    return cell
  }
}

Scroll View

Tables Cells

Segues

This is one method of navigating from View to View. You can create a segue through the Interface builder and control the flow through code:

let storyboard = UIStoryboard(name: "Main", bundle: nil)

let secondVC = storyboard.instantiateViewController(withIdentifier: "SecondViewController") as! SecondViewController

self.navigationController?.pushViewController(secondVC, animated: true)

To learn more, watch:

Navigation Controller

Object that surrounds your views and gives them navigation capabilities:

Related to this is also the UI Tab Bar (also using new storyboards to organize tab bars):

Navigation Bar Controller

Databases

iOS apps typically don’t connect directly to external databases like SQL Server. For security purposes, they communicate with databases through endpoints on some server via JSON/XML. This doesn’t mean that they don’t use a database though. When the app is closed or the iPhone is reset, data must be persisted. Natively, iOS uses SQLite. While Swift can access SQL Lite, connecting to it can be cumbersome through a C interface.

To make things easier, Apple made an ORM that runs on top of SQL Lite called Core Data.

Core Data

More info on Core Data

Safari Books Online : video - What is Core Data?

Core Data Best Practices • https://davedelong.com/blog/2018/05/09/the-laws-of-core-data/

Code Snippets

Dismiss Keyboard When tapping anywhere https://freakycoder.com/ios-notes-31-how-to-hide-keyboard-by-touching-anywhere-cdf4f0c5151c

Accessing a JSON Web Service

// This GOES INSIDE ViewController
import UIKit

// https://www.letsbuildthatapp.com/course_video?id=1562
struct Course: Decodable {
    let id: Int?
    let name: String?
    let link: String?
    let imageUrl: String?
}

class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    
    let jsonUrlString = "https://api.letsbuildthatapp.com/jsondecodable/courses_missing_fields"
    guard let url = URL(string: jsonUrlString) else { return }
    
    URLSession.shared.dataTask(with: url) { (data, response, err) in
      guard let jsonData = data else { return }
    
      do {
        let courses = try JSONDecoder().decode([Course].self, from: jsonData)
        courses.forEach( {
          w in print(w.imageUrl ?? "<not found>")
        })
          
      } catch let jsonErr {
          print("Error serializing json:", jsonErr)
      }
    }.resume()
  }
}

Annoyances

Compiler complains that class does not exist. Unknown class in Interface Builder file: https://stackoverflow.com/questions/24924966/xcode-6-bug-unknown-class-in-interface-builder-file

Resources

General

Best Practices

Authentication

Firebase

Tutorials

Basics

Package Managers

Swift

Cocoa

Changing Keys on XCode and Mac as a Whole

Structs in Swift for Newbies

Generics

Extensions + Helpful Libraries

Best Practices + Guidelines

Swift Code Highlighter (for this document)

Free App Icons

Non-related Productivity Tools

Books

Book Description
picture 7 https://www.amazon.com/Swift-Pocket-Reference-Programming-iOS/dp/1491940077
image here 1 https://www.amazon.com/iOS-12-Programming-Fundamentals-Swift/dp/1492044555

About

Swift crash course for C# developers. Should help evaluate the language. Some notes I compiled why embarked on this journey.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published