Introduce
Hello everyone Swift is a new programming language developed by Apple Inc. for the purpose of supporting developers in developing applications that run on iOS, OSX, and watchOS. Swift is based on the inheritance of the C and Objective-C languages.
Today I would like to share some tips to improve iOS-Swift code.
Begin
Subscripts:
Class, struct and enum can define subscript. Subscripts can be used to quickly access collections, lists, or sequences. You can use subscripts to set and retrieve data with the index, but not through other methods. For example, you access elements in an array through someArray [index] The following are two examples for using subscript to make it clearer:
Do not use subscripts:
struct Matrix { let rows: Int, columns: Int var grid: [Double] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns self.grid = Array(repeatElement(0.0, count: rows * columns)) } func getValue(row: Int, column: Int) -> Double{ return grid[(row * columns) + column] } mutating func setValue(row: Int, column: Int, value: Double){ grid[(row * columns) + column] = value } } var matrix = Matrix(rows: 2, columns: 2) matrix.setValue(row: 0, column: 0, value: 1.0) matrix.setValue(row: 0, column: 1, value: 2.0) matrix.setValue(row: 1, column: 0, value: 3.0) matrix.setValue(row: 1, column: 1, value: 4.0) print(matrix.getValue(row: 0, column: 0)) //prints "1.0" print(matrix.getValue(row: 0, column: 1)) //prints "2.0" print(matrix.getValue(row: 1, column: 0)) //prints "3.0" print(matrix.getValue(row: 1, column: 1)) //prints "4.0" |
Use subscript
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 | struct Matrix { let rows: Int, columns: Int var grid: [Double] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns self.grid = Array(repeatElement(0.0, count: rows * columns)) } subscript(row: Int, column: Int) -> Double { get { return grid[(row * columns) + column] } set { grid[(row * columns) + column] = newValue } } } var matrix = Matrix(rows: 2, columns: 2) matrix[0,0] = 1.0 matrix[0,1] = 2.0 matrix[1,0] = 3.0 matrix[1,1] = 4.0 print(matrix[0,0]) //prints "1.0" print(matrix[0,1]) //prints "2.0" print(matrix[1,0]) //prints "3.0" print(matrix[1,1]) //prints "4.0" |
Function vs Computed Property
Function (or Code)
Here we will take a simple example of two functions to calculate radius for diameter and vice versa
1 2 3 4 5 6 7 8 9 10 11 12 | func getDiameter(radius: Double) -> Double { return radius * 2 } func getRadius(diameter: Double) -> Double { return diameter / 2 } print(getDiameter(radius: 100)) //prints "200" print(getRadius(diameter: 100)) //prints "50" |
Computed Property (or Code)
Computed Property offers GET and SET. I will do the above example using the computed property
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var radius: Double = 100 var diameter: Double { get { return radius * 2 } set { radius = newValue / 2 } } print(diameter) //prints "200.0" diameter = 100 print(radius) //prints "50.0" |
Extension
Extension is used to add new functions to the class, struct, enum or protocol. We can extend the types without having to access the original source code. Here is an example of extention for Double to provide basic types of spacing
Use extension
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | extension Double { var m: Double { return self } var km: Double { return self * 1000.0 } var cm: Double { return self / 100.0 } var mm: Double { return self / 1000.0 } } let thousandCentimeter = 1000.cm print("Thousand centimeter is \(thousandCentimeter) meters") // Prints "Thousand centimeter is 10.0 meters" let threeKilometer = 3.km print("Three km is \(threeKilometer) meters") // Prints "Three km is 3000.0 meters" |
Do not use extension (bad code)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | func centimeterToMeter(value: Double) -> Double{ return value / 100.0 } func kilometerToMeter(value: Double) -> Double{ return value * 1000.0; } let thousandCentimeter = 1000.0 print("Thousand centimeter is \(centimeterToMeter(value: thousandCentimeter)) meters") // Prints "Thousand centimeter is 10.0 meters" let threeKilometer = 3.0 print("Three km is \(kilometerToMeter(value: threeKilometer)) meters") // Prints "Three km is 3000.0 meters" |
Ternary conditional
This operator is a special type consisting of 3 parts with a pattern
question ? answer1 : answer2
. This is the shortcut used to assess 1 2 courtesy based formula question
is true
or false
. Here is an example to change the value of rowHeight
based on whether header
or not.Use Ternary conditional
1 2 3 4 5 6 7 8 | let contentHeight = 40 let hasHeader = true let rowHeight = contentHeight + (hasHeader ? 50 : 20) print(rowHeight) //prints "90" |
Do not use Ternary conditional (or Code)
1 2 3 4 5 6 7 8 9 10 11 | let contentHeight = 40 let hasHeader = true var rowHeight: Int if hasHeader == true { rowHeight = contentHeight + 50 } else { rowHeight = contentHeight + 20 } print(rowHeight) //prints "90" |
Nil coalescing
The nil coalescing operator has the form
a ?? b
. It will unwraps an optional a if a is valid and if a is nil then the default value returned is b. Said it seems difficult to understand, so I will give an example: Assign the value colorNameToUse
as userDefinedColorName
if userDefinedColorName
valid. If it userDefinedColorName
is nil then the value will be set defaultColorName
Use Nil coalescing (or Code)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | var userDefinedColorName: String? // defaults to nil var colorNameToUse = userDefinedColorName ?? defaultColorName print(colorNameToUse) //prints "red" // userDefinedColorName is nil, so colorNameToUse is set to the default of "red" userDefinedColorName = "green" colorNameToUse = userDefinedColorName ?? defaultColorName print(colorNameToUse) //prints "green" // Now userDefinedColorName is "green", so colorNameToUse is set to the value of userDefinedColorName of "green" |
Do not use Nil coalescing (or Code)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | let defaultColorName = "red" var userDefinedColorName: String? // defaults to nil var colorNameToUse: String! if let color = userDefinedColorName { colorNameToUse = color } else { colorNameToUse = defaultColorName } print(colorNameToUse) //prints "green" //userDefinedColorName is "green", so colorNameToUse is set to the value of userDefinedColorName of "green" |
Optional Unwrapping (if let vs guard let)
Both boys
if let
and guard let
girls can unwrap optional. However, let's guard better when we need to check nested conditions. It will come out if you meet a conditioner that does not meet. Further guard let
making its source code easier to read and easily maintain later. Here is an example to create a new user:1 2 3 4 5 6 7 8 9 10 | let emailField = UITextField() emailField.text = "abcd@mail.com" let usernameField = UITextField() usernameField.text = "vineet" let passwordField = UITextField() passwordField.text = "123456" let conifrmPasswordField = UITextField() conifrmPasswordField.text = "123456" |
Use if let (or Bad Code)
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 | func loginIfLet(){ if let email = emailField.text { if let username = usernameField.text { if let password = passwordField.text { if let conifrmPassword = conifrmPasswordField.text { if password == conifrmPassword { print("Email - \(email)") print("Username - \(username)") print("Password - \(password)") } else { print("Password didn't match with conifrm password.") } } else { print("Conifrm password is empty.") } } else { print("Password is empty.") } } else { print("Username is empty.") } } else { print("Email is empty.") } } loginIfLet() |
Sử dụng guard let (or Awesome Code)
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 | func loginGuardLet(){ guard let email = emailField.text else { print("Email is empty.") return } guard let username = usernameField.text else { print("Username is empty.") return } guard let password = passwordField.text else { print("Password is empty.") return } guard let conifrmPassword = conifrmPasswordField.text else { print("Conifrm password is empty.") return } if password == conifrmPassword { print("Email - \(email)") print("Username - \(username)") print("Password - \(password)") } else { print("Password didn't match with conifrm password.") } } loginGuardLet() |
Generics
Generics are one of Swift's powerful features. Allows us to write flexible and easy reusable functions of any kind. Here is an example of how to write a function to swap two integers and two characters. Normally, we will write two functions for the two functions:
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 | func swapTwoInts(_ a: inout Int, _ b: inout Int) { let temporaryA = a a = b b = temporaryA } func swapTwoStrings(_ a: inout String, _ b: inout String) { let temporaryA = a a = b b = temporaryA } var someInt = 3 var anotherInt = 107 swapTwoInts(&someInt, &anotherInt) print("someInt = \(someInt)") print("anotherInt = \(anotherInt)") /* prints someInt = 107 anotherInt = 3 */ var someString = "hello" var anotherString = "world" swapTwoStrings(&someString, &anotherString) print("someString = \(someString)") print("anotherString = \(anotherString)") /* prints someString = world anotherString = hello */ |
Use Generics (or Code)
We only need to create a single function with any type of data
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 | func swapTwoValues<T>(_ a: inout T, _ b: inout T) { let temporaryA = a a = b b = temporaryA } var someInt = 3 var anotherInt = 107 swapTwoValues(&someInt, &anotherInt) print("someInt = \(someInt)") print("anotherInt = \(anotherInt)") /* prints someInt = 107 anotherInt = 3 */ var someString = "hello" var anotherString = "world" swapTwoValues(&someString, &anotherString) print("someString = \(someString)") print("anotherString = \(anotherString)") /* prints someString = world anotherString = hello */ |
Type safe using Enum
Enum defines a generic type for a set of related values and allows us to work on it securely.
Do not use Enum
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | let directionToHead = "east" switch directionToHead { case "north": print("Lots of planets have a north") case "south": print("Watch out for penguins") case "east": print("Where the sun rises") case "west": print("Where the skies are blue") default: print("Unknown direction") } //prints "Where the sun rises" |
Sử dụng enum(or Code)
Using the enum makes the code clearer and clearer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | enum CompassPoint { case north, south, east, west } let direction: CompassPoint = .east switch direction { case .north: print("Lots of planets have a north") case .south: print("Watch out for penguins") case .east: print("Where the sun rises") case .west: print("Where the skies are blue") }Tổng kết |
So we went through some TIPs to improve our skills. Doing as many wrongs as possible will draw experience. No one but yourself pro. So everyone who shares more can leave behind comments so that those who do not know can know more. Thanks everyone.
No comments:
Post a Comment