Swift has many similarities to languages like C#, or Java, but as one would expect of an Apple product, it also has its special way of doing things. Still, for the experienced C#  Java developer learning Swift is quite easy. Here is a brief comparison of C#/Swift:

Defining variables

In Swift, variables must be declared prefixed with either var for mutable values, and let for non mutable values ( like constants values):
C#

int qty = 500;
const double Pi = 3.14159;

Swift 3

var qty:Int = 500;
let Pi:Double = 3.14159;

The only restrictions that let will impose on us are the following:

  • The variable must be initialized the moment it is declared
  • Once the variable is set it cannot be modified

So this is not possible:

let myConst:Int
// more code
myConst = 3.14 // declare myconst as var!!

let arrayInt:[Int] = []
arrayInt.append(3) // Nay

But this is OK:

// we can do this!!!
let currentUser = UserManager.getCurrentUser()
let customer = Customer()
customer.name = "Jane"

Swift variables are typed

Like in C# swift variables are typed: once you set the type of a variable it can not be changed, but unlike C# the type of the variable can be inferred. This means that you can define a variable without indicating explicitly the type.

var name = "James" 

var customers:[Customer] = [] 

For the variable name we don´t need to specify the type since we initialize it with a String value, and the compiler can infer its type.
For customers we need to specify that it is an array of objects Customer: being initialized as an empty array [] the compiler cannot know its type unless we explicitly tell it.

There can be more than one syntax to specify the type of a variable

var arrayDoubles: [Double] = []
var arrayDoublesToo: Array = Array()

Swift basic operators

Swift basic operators are what you would expect:

  • operations: +,-,*,/,%
  • Comparison operators:==, !=, >, =, <=
  • Logical operators: !, &&, ||
  • Ternary : (a ? b : c)
  • Coalescing: ??

Semicolons not required

In C# you are required to write a “;” at the end of every sentence like this:

int mybar = 35;

In swift, semicolons are not required (but not forbidden), you can do both thus:

mybar:Int = 35;
myfoo:Int = 35

Conditionals

Conditionals in Swift are identical to C# conditionals except for one detail: you need to wrap between brackets even one line statements.
C#

if (i > MAX_ELEMS)
	Console.WriteLine("Limit reached.");
else
    Console.WriteLine("Limit not reached yet.");

Swift 3:

if (i > MAX_ELEMS)
{
	print("Limit reached.");
}
else
{
    print("Limit not reached yet.");
}

Remember that Swift operators perform short-circuit evaluation.

Looping

Loops are more or less what you would expect:

A simple way to iterate an array

let items = ["Brush", "Hammer", "Picture", "Pencil"]
for item in items {
    print(name)
}

Our usual while loop:

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

Switch

An important thing to remember is that in Swift switch statements don’t fall through. You can write break statements if you wish, but as shown in the next example they are not required.

enum PaymentMethod {
	case card
	case paypal
	case cash
}

switch paymentType {
	case card:
    	   print("card payment")
	case paypal:
    	   print("paypal payment")
	default:
    	   print("Some other method")
}

Given that by default switch statements do not fall through, if you need that particular behavior you need to explicitly indicate by means of the keyword fallthrough:

switch numberBetweenOneAndFive {
case 5:
    print("greater than 4")
	fallthrough
case 4:
    print("greater than 3")
	fallthrough
case 3:
    print("greater than 2")
	fallthrough
case 2:
    print("greater than 1")
	fallthrough
default:
    print(numberBetweenOneAndFive)
}

Swift does not allow empty cases, the following example is incorrect:

switch paymentType {
     case card:
     case paypal:
    	print("Digital payment")
     default:
    	print("Other type of payment")
}

It should be rewritten as follows:

switch paymentType {
     case card, paypal:
    	print("Digital payment")
     default:
    	print("Other type of payment")
}

Notice also that the default case can be omitted if, and only if, the switch is exhaustive (all the possible values of the evaluated type are covered by the case statements).

Functions

Functions in Swift are described with the keyword func, and when returning a value they indicate it by adding at the end of the function -> type returned. Compare the C#, and Swift examples:
C#

public int calculateFinalPrice(int price, int tax)
{
    int total = price + tax;
    return total;
}

Swift 3

func calculateFinalPrice(price:Int, tax:Int) -> Int
{
    let total = price + tax;
    return total;
}

If the function does not return a result you can omit the -> type in the definition, or just define it as returning -> Void.

Now, here starts the weirdness, when calling the function in Swift you must remember to specify the names of the parameters too:

let myPrice = calculateFinalPrice(price:100, tax:22)

Try/ Catch

Try/catch statements are handled a bit differently in Swift: you need to wrap your code block in a do {} statement, and then prefix every statement in your code that can throw a statement with the try keyword:

C#

try {
    cart = addItemToShoppingCar(item)
    buyItem(Customer,cart)
 }
catch (Rejected e)
        {
            Console.WriteLine("{0} exception caught.", e);
        }
catch (IncompleteBillingData e)
        {
            Console.WriteLine("{0} exception caught.", e);
        }
catch (Exception e)
        {
            Console.WriteLine("{0} exception caught.", e);
        }

Swift 3:

enum PaymentError: Error {
   case rejected
   case incompleteBillingData
}

do {
    let cart = try addItemToShoppingCar(item:item)
    try buyItem(customer: customer, cart: cart)
} catch PaymentError.rejected {
    print("rejected.")
} catch PaymentError.incompleteBillingData {
    print("Incorrect billing information.")
} catch Error {
	print(error)
}

How to throw errors in Swift 3

A function must be marked with the keyword throws to indicate that it can propagate an error; to throw the error we use the statement throw:

func buyItem(customer: Customer, cart: Cart) throws -> Void
{
// do stuff
throw PaymentError.rejected("Payment was rejected!!")
// ...
}

try/catch does not trap runtime exceptions

Something that developers coming from C#, or other languages should remember is that surrounding a block of code with a try/catch with a generic exception will not catch any type of error that occurs inside that code on execution.

Trying, for example, to prevent an “index out of range” exception by using try/catch will not work at all, the application will crash regardless of how many try/catch we use. The same applies if we try to access a property of a null object. Some other languages allow us to trap these kind of errors as exceptions: not Swift. If we want to prevent our application from crashing we must check if the value is null, or check if an index is inside an array range:

This approach is futile:

 do {
        //myNullObject is null
	var a: String? = myNullObject.name
    } catch {
        print("Something unexpected happened ...")
    }

instead do this:

 do {
        //myNullObject is null
	var a: String?
        if myNullObject != nil {
          a = myNullObject!.name
        }
    } catch {
        print("Something unexpected happened ...")
    }
Advertisements