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)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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]() |
Để 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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Khuyên dùng: | |
var names: [String] = [] | |
var lookup: [String: Int] = [:] | |
Không nên dùng: | |
var names = [String]() | |
var lookup = [String: Int]() |
Một số cú pháp khai báo biến khác được ưa dùng.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | |
} |
Control Flow
Thường sử dụng for-in hơn là dùng for khi sử dụng vòng lặp.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
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ụ:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
} |
Và sử dụng nó:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Khuyên dùng | |
imageView.setImageWithURL(url, type: .person) | |
Không nên dùng | |
imageView.setImageWithURL(url, type: AsyncImageView.Type.person) |
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ụ:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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).") | |
} | |
} |
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ụ:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.") | |
} | |
} |
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.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} |
Khoảng cách của dấu : khi khai báo cái gì đó.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] | |
} |
Không nên dùng ; sau khi kết thúc một dòng code nào đó.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Khuyên dùng: | |
let swift = "not a scripting language" | |
Không nên dùng: | |
let swift = "not a scripting language"; |
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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)") | |
} |
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.
HXV
Hướng dẫn về style và quy ước code trong Swift(Phần 1) - Cách đặt tên, cấu trúc project và tổ chức code...
Hướng dẫn về style và quy ước code trong Swift(Phần 2) - Cách mô tả Struct,Class,Method,Closures...
Hướng dẫn về style và quy ước code trong Swift(Phần cuối) - Cách mô tả các Type data, Access control, Control Flow, Manager memory...
Bài viết liên quan:
Hướng dẫn tự học Swift từ A tới Z cho người mới bắt đầu và người muốn ôn lại kiến thức
Hướng dẫn về style và quy ước code trong Swift(Phần 2) - Cách mô tả Struct,Class,Method,Closures...
Hướng dẫn về style và quy ước code trong Swift(Phần cuối) - Cách mô tả các Type data, Access control, Control Flow, Manager memory...
0 Comments