Tiếp theo phần trước chúng ta sẽ tiếp tục tìm hiểu một số style và quy ước code của một số kiểu dữ liệu sau đây.


Kiểu tự suy luận(type inference)
Khuyên dùng:
let message = "Click the button"
let currentBounds = computeViewBounds()
var names = ["Mic", "Sam", "Christine"]
let maximumWidth: CGFloat = 106.5
Không nên dùng:
let message: String = "Click the button"
let currentBounds: CGRect = computeViewBounds()
let names = [String]()
view raw sampleInferen hosted with ❤ by GitHub


Để khởi tạo một số mảng rỗng hay dictionary rỗng chúng ta thường khái báo như sau:
Khuyên dùng:
var names: [String] = []
var lookup: [String: Int] = [:]
Không nên dùng:
var names = [String]()
var lookup = [String: Int]()
view raw sampleArray hosted with ❤ by GitHub


Một số cú pháp khai báo biến khác được ưa dùng.
Khuyên dùng:
var deviceModels: [String]
var employees: [Int: String]
var faxNumber: Int?
Không nên dùng:
var deviceModels: Array<String>
var employees: Dictionary<Int, String>
var faxNumber: Optional<Int>
Access control
Là nhưng từ khóa như: public, private, privatefile….
Thông thường để cho phép truy xuất toàn quyền vào một biến hay class nào đó chúng ta sẽ dùng open, public, internal.
Khuyên dùng:
private let message = "Great Scott!"
class TimeMachine {
fileprivate dynamic lazy var fluxCapacitor = FluxCapacitor()
}
Không nên dùng:
fileprivate let message = "Great Scott!"
class TimeMachine {
lazy dynamic fileprivate var fluxCapacitor = FluxCapacitor()
}
view raw sampleAccess hosted with ❤ by GitHub


Control Flow
Thường sử dụng for-in hơn là dùng for khi sử dụng vòng lặp.
Khuyên dùng:
for _ in 0..<3 {
print("Hello three times")
}
for (index, person) in attendeeList.enumerated() {
print("\(person) is at position #\(index)")
}
for index in stride(from: 0, to: items.count, by: 2) {
print(index)
}
for index in (0...3).reversed() {
print(index)
}
Không nên dùng:
var i = 0
while i < 3 {
print("Hello three times")
i += 1
}
var i = 0
while i < attendeeList.count {
let person = attendeeList[i]
print("\(person) is at position #\(i)")
i += 1
}
view raw gistfile1.txt hosted with ❤ by GitHub


Bắt lỗi(Error handling)
Giả sử bạn có hàm getNameOfUser và nó sẽ trả về kiểu String, tuy nhiên một ngày đẹp trời nào đó nó bị lỗi và không thể lấy được tên.Thông thường để dễ bắt lỗi chúng ta sẽ dùng String? Là kiểu trả về cho hàm, khi đó hàm có thể trả về nil và ta có thể kiểm tra điều này.


Ví dụ:
func readFile(named filename: String) -> String? {
guard let file = openFile(named: filename) else {
return nil
}
let fileContents = file.read()
file.close()
return fileContents
}
func printSomeFile() {
let filename = "somefile.txt"
guard let fileContents = readFile(named: filename) else {
print("Unable to open file \(filename).")
return
}
print(fileContents)
}
Thay vào đó chúng ta cũng có thể nên dùng try/ catch để bắt lỗi cũng được.


Chúng ta có thể tạo một struct quản lý lỗi như sau:
struct Error: Swift.Error {
public let file: StaticString
public let function: StaticString
public let line: UInt
public let message: String
public init(message: String, file: StaticString = #file, function: StaticString = #function, line: UInt = #line) {
self.file = file
self.function = function
self.line = line
self.message = message
}
}
view raw sampleStruct hosted with ❤ by GitHub


Và sử dụng nó:
func readFile(named filename: String) throws -> String {
guard let file = openFile(named: filename) else {
throw Error(message: "Unable to open file named \(filename).")
}
let fileContents = file.read()
file.close()
return fileContents
}
func printSomeFile() {
do {
let fileContents = try readFile(named: filename)
print(fileContents)
} catch {
print(error)
}
}
Nhờ vậy mà khi có lỗi chúng ta sẽ dễ dàng biết được chi tiết lỗi hơn, khỏi sợ lỗi mà không rõ nguyên nhân.


Khuyên dùng
imageView.setImageWithURL(url, type: .person)
Không nên dùng
imageView.setImageWithURL(url, type: AsyncImageView.Type.person)
view raw sampleEnum hosted with ❤ by GitHub


Nên dùng kết hợp Switch với enum khi sử lý một vấn đề nào đó mà sẽ có nhiều trường hợp xảy ra. Vì enum hỗ trợ chúng ta cơ chế associated value khá hay bạn có thể tìm hiểu chi tiết ở bài này.
Ví dụ:
enum Problem {
case attitude
case hair
case hunger(hungerLevel: Int)
}
func handleProblem(problem: Problem) {
switch problem {
case .attitude:
print("At least I don't have a hair problem.")
case .hair:
print("Your barber didn't know when to stop.")
case .hunger(let hungerLevel):
print("The hunger level is \(hungerLevel).")
}
}
view raw sampleHandle hosted with ❤ by GitHub


Khi dùng Switch chúng ta có thể dùng kèm theo với throw để bắt lỗi một cách dễ dàng hơn.
Ví dụ:
func handleDigit(_ digit: Int) throws {
switch digit {
case 0, 1, 2, 3, 4, 5, 6, 7, 8, 9:
print("Yes, \(digit) is a digit!")
default:
throw Error(message: "The given number was not a digit.")
}
}
view raw sampleSwitch hosted with ❤ by GitHub
Quản lý bộ nhớ.
Chắc bạn cũng biết thế nào là retain cycle(Tham khảo bài này). Nó là một hiện tượng khá nguy hiểm trong Swift. Để tránh nó người ta thường sử dụng [weak self] và guard let strongSelf = self else { return } Có nghĩa là sẽ ưu tiên dùng  [weak self] hơn là [unowned self] Thông thường được dùng nhiều trong clouse.
Khuyên dùng:
resource.request().onComplete { [weak self] response in
guard let strongSelf = self else {
return
}
let model = strongSelf.updateModel(response)
strongSelf.updateUI(model)
}
Không nên dùng:
// might crash if self is released before response returns
resource.request().onComplete { [unowned self] response in
let model = self.updateModel(response)
self.updateUI(model)
}
Hoặc không nên dùng:
// deallocate could happen between updating the model and updating UI
resource.request().onComplete { [weak self] response in
let model = self?.updateModel(response)
self?.updateUI(model)
}


Dấu ngoặc nhọn thường được sử dung như sau:
Khuyên dùng:
Khuyên dùng:
if user.isHappy {
// Do something
} else {
// Do something else
}
Không khuyên dùng:
if user.isHappy
{
// Do something
}
else {
// Do something else
}
view raw sample_14 hosted with ❤ by GitHub

Khoảng cách của dấu : khi khai báo cái gì đó.
Khuyên dùng:
class TestDatabase: Database {
var data: [String: CGFloat] = ["A": 1.2, "B": 3.2]
}
Không nên dùng:
class TestDatabase : Database {
var data :[String:CGFloat] = ["A" : 1.2, "B":3.2]
}
view raw Sample_15 hosted with ❤ by GitHub



Không nên dùng ; sau khi kết thúc một dòng code nào đó.
Khuyên dùng:
let swift = "not a scripting language"
Không nên dùng:
let swift = "not a scripting language";
view raw sample_16 hosted with ❤ by GitHub


Nếu trong một dòng có nhiều phần chúng ta nên dùng dấu ngoặc tròn để chia nhỏ các phần để dễ hiểu và code rõ ràng hơn.

let playerMark = (player == current ? "X" : "O")


Có một thu thuật như thế nào, chúng ta có thể bôi đen toàn bộ code trong 1 file và nhấn Control-I , Xcode sẽ tự format canh chỉnh indent cho dòng code của chúng ta một cách hợp lý nhất.


Một số ví dụ code tham khảo:
extension UIColor {
static var myAppRed: UIColor {
return UIColor(red: 1, green: 0.1, blue: 0.1, alpha: 1)
}
static var myAppGreen: UIColor {
return UIColor(red: 0, green: 1, blue: 0, alpha: 1)
}
static var myAppBlue: UIColor {
return UIColor(red: 0, green: 0.2, blue: 0.9, alpha: 1)
}
}
extension UIFont {
static var myAppTitle: UIFont {
return UIFont.systemFont(ofSize: 17)
}
static var myAppBody: UIFont {
return UIFont.systemFont(ofSize: 14)
}
}
var i: Int = 11
func checkNumber() {
guard i > 10 else {
return
}
print("i is greater than 10")
}
checkNumber() // function call will print "i is greater than 10"
// Switch statement with multiple values
let number: Int = 1
switch number {
case 1, 3, 5, 7, 9:
print("\(number) is an odd number")
case 2, 4, 6, 8, 10:
print("\(number) is an even number")
default:
print("\(number) is not an odd or an even number")
}
// This switch statement will print: "1 is an odd number"
// Correct and preferred
for multiplier in 1...10 {
print("\(multiplier) times 2 is \(multiplier * 5)")
}
view raw sample_17 hosted with ❤ by GitHub
Ngoài các phần chúng ta đã tìm hiểu qua 2 phần trước chúng ta có thể tham khảo các tài liệu của Apple:

Phần cuối này chúng ta đã tìm hiểu chi tiết hơn và tập trung vào style,convention code trong quản lý bộ nhớ, các kiểu dữ liệu, cách đóng mở ngoặc nhọn, ngoặc tròn, ... và một số tài liệu tiếng anh của Apple cho các bạn nghiên cứu và tìm hiểu thêm… để góp phần nâng cao và hoàn thiện kỹ năng code của bạn khi phát triển ứng dụng iOS.

Hy vọng các bạn thích và học được nhiều kiến thức từ bài viết này. Mong các bạn chia sẽ nó để mọi người cùng học và cùng trao đổi. Mọi thắc mắc hay trao đổi về bài viết, các bạn có thể để lại bình luận bên dưới mình sẽ hỗ trợ sớm nhất.
Chân thành cảm ơn các bạn đã theo dõi.