01. Sử dụng if và switch như biểu thức
Đến mãi Swift 5.9, thì từ khoá if và switch chỉ được sử dụng như các câu lệnh!
Điều này có nghĩa là không thể gán trực tiếp kết quả của if hoặc switch vào một biến hoặc truyền nó như một tham số
let bullet =
isRoot && (count == 0 || !willExpand) ? ""
: count == 0 ? "- "
: maxDepth <= 0 ? ">" : "<"
Hiện tại ở Swift 5.9 này, if và switch có thể được sử dụng như một biểu thức!
Các biểu thức bậc ba loằng ngoằng nhìn rối mắt bây giờ có thể thay thế bằng điều kiện if giúp chúng ta có thể dễ đọc hơn nhiều:
let bullet =
if isRoot && (count == 0 || !willExpand) { "" }
else if count == 0 { "- " }
else if maxDepth <= 0 { ">" }
else { "<" }
Không những thế, chúng ta có thể sử dụng chức năng mới này với if let hoặc guard let để unwrap biến optionals:
let attributedName =
if let displayName, !displayName.isEmpty {
AttributedString(markdown: displayName)
} else {
"Untitled"
}
02. Parameter Packs
Nếu bạn đã từng phải viết những đoạn code cần xử lý nhiều loại generic không xác định, và Swift không trợ cho việc đa dạng generics
Và cách duy nhất bạn có thể làm là triển khai tất cả các generics vào một function:
struct Request<Result> { ... }
struct RequestEvalutor {
func evalute<Result>(_:) -> (Result)
func evalute<R1, R2>(_:,_:) -> (R1, R2)
func evalute<R1, R2, R3>(_:,_:,_:) -> (R1, R2, R3)
func evalute<R1, R2, R3, R4>(_:,_:,_:,_:) -> (R1, R2, R3, R4)
func evalute<R1, R2, R3, R4, R5>(_:,_:,_:,_:,_:) -> (R1, R2, R3, R4, R5)
}
let request = RequestEvalutor()
let result = request.evaluate(r1, r2, r3, r4, r5)
Mặc dù cách làm như trên có vẻ như không được tốt lắm nhưng các framework như SwiftUI và Combine cũng dựa vào cách làm như trên
Nhưng không may một điều là cách làm như trên sẽ gặp một nhược điểm lớn vì bạn không thể triển khai một số lượng đối số chồng chất vô hạn, vì vậy luôn có một giới hạn về số lượng đối số mà hàm của bạn có thể xử lý:
let result = request.evaluate(r1, r2, r3, r4, r5, r6, r7)
// This code will be error: Extra argrument in call
Một ví dụ thực tế là khi bạn cố gắng implement thật nhiều child view vào 1 VStack hoặc HStack thì SwiftUI chỉ có thể thêm được tối đa 10 child view.
Nhưng nếu bạn sử dụng Xcode 15 và thử thêm 11 child view thì một điều tuyệt vời là không còn warning giới hạn nào ở đây nữa. Có thể thêm bao nhiêu tuỳ thích !
Vì trong Swift 5.9 này có một tính năng mới gọi là Parameter Packs:
Sử dụng từ khoá each, để khai báo một Parameter Pack.
Và sau đó, thông qua từ khoá repeat, chúng ta có thể sử dụng Parameter Pack này, chẳng hạn để khai báo các đối số của hàm hoặc xác định một tuple type.
Swift 5.9:
func zip<each T>(_ input: repeat each T) -> (A, B, C, D) {
return (repeat each input)
}
//Example
func pairUp<each T, each U>(firstPeople: repeat each T,
secondPeople: repeat each U)
-> (repeat (first: each T, second: each U)) {
return (repeat (each firstPeople, each secondPeople))
}
let result = pairUp(firstPeople: johnny, derek,
secondPeople: kate, kevin)
Trước đây:
func zip<T₁, T₂,‥․, Tₙ>(_ i₁: T₁, _ i₂:T₂,‥․,_ iₙ: Tₙ) -> (T₁, T₂,‥․,Tₙ) {
return (i₁, i₂,‥․, iₙ)
}
03. Macros
Ở Swift 5.9, ngôn ngữ swift đã cho ra mắt tính năng Macros, không kém gì các plugin có khả năng generating code
Dưới đây là đoạn code điển hình mà macro có thể tạo cho bạn: xác định một thuộc tính sau khi tính toán cho từng case trong một enum
enum Path {
case relative(String)
case absolute(String)
}
let absPaths = paths.filter { $0.isAbsolute }
extension Path {
var isAbsolute:Bool {
if case .absolute = self { true }
else { false }
}
}
extension Path {
var isRelative:Bool {
if case .relative = self { true }
else { false }
}
}
Ở Swift 5.9 bạn có thể xoá đoạn code trên và thay vào đó, bạn chỉ cần thêm @CaseDetection enum của bạn :
@CaseDetction
enum Path {
case relative(String)
case absolute(String)
}
let absPaths = paths.filter { $0.isAbsolute }
Tại thời điểm biên dịch, macro này sau đó sẽ được trình biên dịch Swift generate đoạn code trên giúp bạn:
@CaseDetction
enum Path {
case relative(String)
case absolute(String)
@CaseDection will generate this code
** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* var isAbsolute:Bool { *
* if case .absolute = self { true } *
* else { false } *
* } *
* *
* var isRelative:Bool { *
* if case .relative = self { true } *
* else { false } *
* } *
* *
** * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
}
let absPaths = paths.filter { $0.isAbsolute }
Và đó là 3 tính năng mới của Swift 5.9 mà mình muốn giới thiệu cho các bạn !!!
Hi vong các bạn sẽ apply các tính năng này vào dự án của mình 🙌