Swift3 sẽ xuất hiện vào cuối năm này, và đem lại sự thay đổi lớn về code cho các lập trình viên Swift.
Nếu bạn chưa từng theo dõi sát sao dự án Swift Evolution, có thể bạn sẽ thắc mắc những thay đổi là gì, và chúng sẽ tác động thế nào đến cách code của mình, và khi nào bạn nên chuyển sang sử dụng Swift 3. Bài viết này sẽ giúp bạn giải đáp các thắc mắc trên.
Bài viết này sẽ nêu bật các thay đổi quan trọng trong Swift 3 mà có tác động đến code của bạn.
Mở đầu
Swift 3 preview có sẵn trong Xcode 8 beta đã được phát hành. Trong khi sự nâng cấp Swift 3 đang giảm bớt đi, vẫn có thể sẽ có một vài thay đổi được chấp nhận trong vài tháng tới. Các tính năng sẽ được cố định khi Xcode đạt tới bản hoàn thiện (Gold master) vào cuối năm 2016, do đó bạn sẽ phải chờ đợi một thời gian trước khi có thể đưa các ứng dụng bằng Swift 3 lên App Store.
Để các developer (dev) có thể chuyển sang Swift 3 theo thời gian của chính mình, Apple đã đưa Swift 2.3 như một bản cập nhật nhỏ kèm theo vào Xcode8. Đối với các bạn developer, Swift 2.3 cũng giống như bản Swift 2.2 nhưng hỗ trợ cho nhiều tính năng mới của SDKs và Xcode mà đã được thông báo ở tại hội nghị Apple developer toàn cầu (WWDC). Khi phiên bản Xcode 8 thoát khỏi phiên bản beta, bạn vẫn có thể đăng ứng dụng sử dụng Swift 2.3 nếu vẫn chưa chuyển sang Swift 3.
Người viết khuyến khích việc thử nghiệm các tính năng thảo luận ở đây trên playground và có thể thậm chí chạy Migration Assistant trên một trong nhứng dự án của bạn, để bạn có thể trả nghiệm những thứ đang thay đổi. Nhưng do bạn chưa thể đưa ứng dụng lên App Store cho tới khi Xcode 8 hết beta, có thể bạn sẽ muốn cân nhắc chờ chuyển code sang Swift 3 khi mọi thứ ổn định.
Chuyển sang Swift 3
Khi chuyển sang Swift 3, bạn sẽ chú ý thấy tất cả các file cần thay đổi. Đây là sự thay đổi lớn do tất cả tên Cocoa API đã thay đổi. Hay chính xác hơn, API vẫn thế, nhưng có một tên phù hợp cho Objective-C và một tên phù hợp cho Swift. Swift 3 sẽ khiến cho việc viết Swift tự nhiên hơn nhiều trong những năm tới.
Apple cũng tích hợp Migration Assistant với Xcode 8 để có thể khiến phần lớn các thay đổi diễn ra nhanh chóng. Có một số các đoạn mã bộ chuyển này sẽ không tự động xử lý, bạn sẽ phải tự mình điều chỉnh.
Bạn có thể chuyển sang Swift 2.3 hoặc Swift 3 ngay lập tức. Nếu lúc nào bạn cần sao lưu, bạn luôn có thể điều hướng trong Xcode tới Edit > Convert > To Current Swift Syntax… May mắn là trình biên dịch cũng khá thông minh như Migration Assistant. Nếu bạn vô tình sử dụng API cũ khi gọi phương thức, trình biên dịch sẽ đề xuất tùy chọn Fix-it để giúp bạn sử dụng chuẩn API hiện tại.
Tin tuyệt nhất là Swift 3 dự định là phiên bản cuối cùng có thay đổi lớn về source. Do đó, trong tương lai, bạn có thể giữ được code Swift của mình qua các phiên bản khác nhau. Mặc dù nhóm core Swift không thể dự đoán đươc tương lai, họ đã hứa rằng nếu cần phải phá vỡ tính tương thích của nguồn, họ sẽ đề xuất chu kỳ chuyển đổi hoàn toàn dài hơn. Điều đó có nghĩa là ngôn ngữ này sẽ đạt được độ ổn định về source, điều này sẽ khuyến khích nhiều công ty truyền thống áp dụng hơn.
Nhìn chung, mục tiêu đạt được sự ổn định nhị phân vẫn chưa đạt được. Bạn sẽ thấy nhiều tác động của nó ở cuối bài viêt này.
Thực hiện các đề xuất phát triển Swift
Các thành viên của cộng đồng đã gửi hơn 100 bản đề xuất về thay đổi Swift kể từ khi ngôn ngữ này chuyển thành mã nguồn mở. Phần lớn trong số đề xuất này (tính đến nay khoảng 70) đã được chấp nhận sau khi thảo luận và chỉnh sửa. Những bản bị loại ra cũng đã dấy lên một số thảo luận căng thẳng. Tuy nhiên, đến cuối cùng, team Swift cũng đã đi đến quyết định cuối cùng cho tất cả các đề xuất.
Sự hợp tác làm việc giữa core team và cộng đồng rộng lớn thật sự ấn tượng. Trên thực tế, Swift thu hút nhiều lượt xem, quan tâm trên Github. Một số đề xuất mới được gửi đến hàng tuần, hết tuần này đến tuần khác. Thậm chí khi muốn thực hiện các thay đổi, các kỹ sư Apple viết luôn các đề xuất trên kho lưu trữ mở của Github (open Github repository).
Trong những phần dưới, bạn sẽ thấy các linked tags, vd như [SE-0001]. Đó là các số của đề xuất phát triển Swift. Các số đề xuất được bao gồm ở đây sẽ được chấp nhận và thực hiện trong thời gian tới trong bản Swift 3 cuối cùng. Các đường dẫn (link) tới mỗi đề xuất cũng được đính kèm nên bạn có thể tự khám phá đầy đủ chi tiết mỗi thay đổi cụ thể.
Thay đổi API
Sự nâng cấp lớn nhất trong Swift 3 bao gồm việc các thư viện chuẩn áp dụng đặt tên nhất quán các quy ước giữa các thư viện. Hướng dẫn API Design Guidelines bao gồm các quy tắc mà team Swift quyết định chọn khi họ xây dựng Swift 3, chú trọng đến tính dễ đọc và tiếp cận đến Swift của các lập trình viên mới. Team Swift hoạt động dựa trên nguyên tắc: “Một thiết kế API tốt thì luôn bao gồm nhắc tới cách thức gọi tới”. Họ đã cố gắng để đem đến sự rõ rang cho việc sử dụng. Không có gì thêm nữa, đây chính là những thay đổi sẽ tác động đến bạn nhất.
Nhãn tham số đầu tiên
Hãy bắt đầu với sự thay đổi trực tiếp với cách thức mà bạn vẫn làm hàng ngày trên Swift.
Tham số đầu tiên trong các hàm và phương thức bây giờ luôn có nhãn, trừ khi bạn yêu cầu khác đi. Lúc trước khi bạn gọi đến 1 hàm hoặc phương thức, bạn bỏ qua nhãn của phương thức đầu tiên.
// old way, Swift 2, followed by new way, Swift 3
"RW".writeToFile("filename", atomically: true, encoding: NSUTF8StringEncoding)
"RW".write(toFile: "filename", atomically: true, encoding: NSUTF8StringEncoding)
SKAction.rotateByAngle(CGFloat(M_PI_2), duration: 10)
SKAction.rotate(byAngle: CGFloat(M_PI_2), duration: 10)
UIFont.preferredFontForTextStyle(UIFontTextStyleSubheadline)
UIFont.preferredFont(forTextStyle: UIFontTextStyleSubheadline)
override func numberOfSectionsInTableView(tableView: UITableView) -> Int
override func numberOfSections(in tableView: UITableView) -> Int
func viewForZoomingInScrollView(scrollView: UIScrollView) -> UIView?
func viewForZooming(in scrollView: UIScrollView) -> UIView?
NSTimer.scheduledTimerWithTimeInterval(0.35, target: self, selector: #selector(reset), userInfo: nil, repeats: true)
NSTimer.scheduledTimer(timeInterval: 0.35, target: self, selector: #selector(reset), userInfo: nil, repeats: true)
Hãy để ý đến cách mà các định nghĩa phương thức sử dụng các giới từ như “of”, “to”, “with”, “in” cho phần tên mở rộng. Đây là một phần của nỗ lực tối ưu hóa tính dễ đọc của code.
Nếu việc gọi một phương thức có thể được đọc dễ dàng mà không cần giới từ và không cần nhãn, bạn nên loại bỏ rõ rang tên của tham số đầu tiên với gạch dưới “_”:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { ... }
override func didMoveToView(_ view: SKView) { ... }
Trong nhiều ngôn ngữ lập trình, các phương thức có thể trùng tên với những tên tham số khác nhau. Swift cũng không phải ngoại lệ, và giờ bạn sẽ gặp nhiều tên phương thức nạp chồng (overloaded method) hơn do các API đã được dịch để trở nên trực tiếp hơn. Đây là hai dạng của index():
let names = ["Anna", "Barbara"]
if let annaIndex = names.index(of: "Anna") {
print("Barbara's position: \(names.index(after: annaIndex))")
}
Cùng với nhau, các thay đổi về tên tham số khiến việc đặt tên phương thức nhất quán và dễ học hơn.
Bỏ qua các từ không cần thiết
Ở các vòng lặp trước đây trong các thư viện Apple, các phương thức bao gồm tên biểu thị giá trị trả về. Bởi do trình biên dịch Swift đã kiểm tra kiểu, điều này là không cần thiết. Team Swift đã cẩn thận tìm hiểu làm cách nào để lọc tất cả thứ không cần thiết để chỉ còn giữ lại tín hiệu và do đó rất nhiều từ lặp lại đã bị bỏ đi.
API cũng trở nên thông minh hơn về cách các thư viện Objective-C được chuyển thể sang Swift
// old way, Swift 2, followed by new way, Swift 3
let blue = UIColor.blueColor()
let blue = UIColor.blue()
let min = numbers.minElement()
let min = numbers.min()
attributedString.appendAttributedString(anotherString)
attributedString.append(anotherString)
names.insert("Jane", atIndex: 0)
names.insert("Jane", at: 0)
UIDevice.currentDevice()
UIDevice.current()
Hiện đại hóa GCD và Core Graphics
Liên quan đến việc các API không nhận, GCD và Core Graphics đều nhận được nhiều thay đổi cần thiết.
Grand Central Dispatch được sử dụng cho các nhiệm vụ đa luồng ví dụ như các tính toán dài hoặc để giao tiếp với server. Bằng việc di chuyển hoạt động tới luồng khác, bạn ngăn được việc khóa lại giao diện người dùng (user interface). Thư viện libdispatch được viết trong ngôn ngữ lập trình C và luôn được sử dụng kiểu API của C. API này bây giờ được viết lại bằng Swift nguyên bản.
// old way, Swift 2
let queue = dispatch_queue_create("com.test.myqueue", nil)
dispatch_async(queue) {
print("Hello World")
}
// new way, Swift 3
let queue = DispatchQueue(label: "com.test.myqueue")
queue.async {
print("Hello World")
}
Tương tự, Core Graphics được viết trong C và từng sử dụng hàm gọi bất tiện. Sau đây là cách dùng mới:
// old way, Swift 2
let ctx = UIGraphicsGetCurrentContext()
let rectangle = CGRect(x: 0, y: 0, width: 512, height: 512)
CGContextSetFillColorWithColor(ctx, UIColor.blueColor().CGColor)
CGContextSetStrokeColorWithColor(ctx, UIColor.whiteColor().CGColor)
CGContextSetLineWidth(ctx, 10)
CGContextAddRect(ctx, rectangle)
CGContextDrawPath(ctx, .FillStroke)
UIGraphicsEndImageContext()
// new way, Swift 3
if let ctx = UIGraphicsGetCurrentContext() {
let rectangle = CGRect(x: 0, y: 0, width: 512, height: 512)
ctx.setFillColor(UIColor.blue().cgColor)
ctx.setStrokeColor(UIColor.white().cgColor)
ctx.setLineWidth(10)
ctx.addRect(rectangle)
ctx.drawPath(using: .fillStroke)
UIGraphicsEndImageContext()
}
Viết hoa đối với các case trong kiểu Enum
Một sự thay đổi khác với cách mà bạn đã từng code trong Swift là lowerCamelCase bây giờ thay thế cho các enumeration cases. Điều này khiến chúng thống nhất hơn với các thuộc tính hoặc giá trị khác.
// old way, Swift 2, followed by new way, Swift 3
UIInterfaceOrientationMask.Landscape
UIInterfaceOrientationMask.landscape
NSTextAlignment.Right
NSTextAlignment.right
SKBlendMode.Multiply
SKBlendMode.multiply
UpperCamelCase bây giờ được dùng riêng cho tên các kiểu và protocols. Mặc dù điều này có thể tốn một thời gian để làm quen, team Swift có lý do chính đáng trong nỗ lực của mình nhằm hướng tới sự nhất quán.
Các phương thức trả về hoặc chỉnh sửa
Thư viện chuyển cũng đang trở nên nhất quán trong việc đặt tên phương thức với các động từ và danh từ. Bạn chọn một tên dựa trên các tác động và hành động thực hiện. Một lệ bất thành văn là nếu nó bao gồm hậu tố như “-ed” hoặc “-ing” thì phương thức được hiểu như là danh từ. Một phương thức dạng danh từ sẽ trả về giá trị. Nếu nó không có hậu tố, thì nó rất có khả năng là động từ mệnh lệnh (imperative verb). Những phương thức dạng “động từ” này thực hiện hành động trong bộ nhớ tham chiếu. Điều này cũng được gọi là sửa đổi tại chỗ. Có một vài cặp phương thức theo quy ước danh từ/ động từ này. Sau đây là một vài ví dụ:
customArray.enumerate()
customArray.enumerated()
customArray.reverse()
customArray.reversed()
customArray.sort() // changed from .sortInPlace()
customArray.sorted()
Sau đây là một đoạn sử dụng cụ thể:
var ages = [21, 10, 2] // variable, not constant, so you can modify it
ages.sort() // modified in place, value now [2, 10, 21]
for (index, age) in ages.enumerated() { // "-ed" noun returns a copy
print("\(index). \(age)") // 1. 2 \n 2. 10 \n 3. 21
}
Các loại hàm
Các khai báo hàm và gọi hàm luôn yêu cầu dấu ngoặc quanh các tham số
func f(a: Int) { ... }
f(5)
Tuy nhiên khi bạn sử dụng kiểu hàm như là một tham số của chính nó, bạn có thể viết như thế này:
func g(a: Int -> Int) -> Int -> Int { ... } // old way, Swift 2
Bạn có thể thấy rằng nó tương đối khó đọc (hiểu). Chỗ nào các tham số kết thúc và chỗ nào là kiểu trả về? Với Swift 3, cách chính xác để định nghĩa hàm này là như sau:
func g(a: (Int) -> Int) -> (Int) -> Int { ... } // new way, Swift 3
Bây giờ, danh sách các tham số được bao quanh bởi dấu ngoặc đơn và sau đó là kiểu trả về. Mọi thứ trông rõ ràng hơn, và do đó, kiểu hàm được nhận ra dễ dàng hơn. Sau đây là một so sánh rõ ràng khác:
// old way, Swift 2
Int -> Float
String -> Int
T -> U
Int -> Float -> String
// new way, Swift 3
(Int) -> Float
(String) -> Int
(T) -> U
(Int) -> (Float) -> String
Bổ sung API
Trong khi nâng cấp lớn nhất đối với Swift 3 là hiện đại hóa các API hiện tại, cộng đồng Swift cũng chăm chỉ thực hiện – bao gồm các bổ sung hữu ích cho Swift API.
Tiếp cận kiểu bao gồm (Containing Type)
Khi bạn định nghĩa thuộc tính tĩnh hoặc phương thức, bạn luôn phải gọi chúng trên kiểu trực tiếp:
CustomStruct.staticMethod()
Nếu bạn đang viết code trong nội dung của một kiểu, bạn vẫn cần phải bao gồm tên của kiểu để gọi một phương thức tĩnh trên kiểu này. Để làm rõ hơn, bây giờ bạn có thể gọi “self” để lấy ra loại kiểu bao gồm (containing type). Chữ ‘S’ viết hoa ám chỉ kiểu của self, trong khi chữ ‘s’ viết thường ám chỉ biến instance của self.
Ví dụ cụ thể về hoạt động của nó:
struct CustomStruct {
static func staticMethod() { ... }
func instanceMethod() {
Self.staticMethod() // in the body of the type
}
}
let customStruct = CustomStruct()
customStruct.Self.staticMethod() // on an instance of the type
Các chuỗi nội tuyến (Inline Sequences)
sequence(first:next:) và sequence(state:next:)là các hàm global trả về các chuỗi vô hạn. Bạn cho chúng một giá trị ban đầu hoặc mutable state, chúng sẽ tự kết thúc chuỗi. [SE-0094]:
for view in sequence(first: someView, next: { $0.superview }) {
// someView, someView.superview, someView.superview.superview, ...
}
Bạn có thể hạn chế chuỗi bằng cách sử dụng prefix [SE-0045]:
for x in sequence(first: 0.1, next: { $0 * 2 }).prefix(while: { $0 < 4 }) {
// 0.1, 0.2, 0.4, 0.8, 1.6, 3.2
}
Những thay đổi khác
- #keyPath() hoạt động giống như #selector() và giúp bạn vượt qua các lỗi chính tả trong các API kiểu chuỗi dài
- Bây giờ bạn có thể gọi số pi trên kiểu mà bạn định sử dụng như: Float.pi, CGFloat.pi. Và phần lớn thời gian trình duyệt có thể tự suy luận kiểu, vd: let circumference = 2 * .pi * raidus [SE-0067]
- Tiền tố NS đã được bỏ đi ở các kiểu foundation, bây giờ bạn có thể sử dụng Calendar, Date thay vì NSCalendar và NSDate
Cải thiện công cụ
Swift là một ngôn ngữ, và một phần lớn việc viết nó liên quan đến sử dụng môi trường lập trình – vd đối với các lập trình viên Apple thì nó Xcode. Các thay đổi tiếp diễn cùng với công cụ sẽ ảnh hưởng cách bạn viết code Swift hàng ngày.
Swift 3 sửa lỗi trong các tính năng của IDE và trình biên dịch. Nó cũng cải thiện độ chính xác của các tin báo lỗi và cảnh báo. Và như bạn mong đợi, với mỗi lần ra mắt, Swift trở nên nhanh hơn trong việc chạy và biên dịch:
- Bằng việc cải thiện string hashing, dictionaries của strings tăng tốc gấp 3 lần
- Việc di chuyển objects từ heap tới stack, nâng tốc độ lên 24 lần ( trong một số trường hợp)
- Trình biên dịch bây giờ lưu bộ nhớ đệm (caches) nhiều file cùng lúc (khi thực hiện tối ưu toàn bộ module)
- Tối ưu hóa kích cỡ code đã làm giảm kích cỡ biên dịch của Swift code. Bản demo của Apple: Demobots đã làm giảm kích thước biên dịch xuống tới 77% bản gốc
Xcode cũng đang học cách nghĩ bằng Swift:
- Khi bạn click chuột phải vào phương thức API, vd như sort() và chọn “jump to its definition”, bạn thường được dẫn tới một file tiêu đề khó hiểu. Bây giờ, trong Xcode 8, bạn sẽ thấy sort() là phần mở rộng của Array
- Swift Snapshots giống như là các bản ra ngay trước Swift Evolution. Chúng tạo cơ hội để làm việc với cú pháp mới trước khi được đưa vào toàn bộ trong Xcode. Xcode 8 có thể tải và chạy Swift Snapshots trong playgrounds
Swift Package Manager
Swift nguồn mở thực tế là một họ các kho bao gồm ngôn ngữ, các thư viện core, và gói quản lý (the package manager). Cùng với nhau, chúng tạo thành thứ mà chúng ta nghĩ tới Swift. Swift Package Manager định nghĩa cấu trúc thư mục đơn giản cho bất kỳ Swift code nào mà bạn muốn share và import vào các projects.
Tương tự như các package managers bạn từng sử dụng như Cocoapods hay Carthage, bộ gói quản lý của Swift sẽ tải các phụ thuộc (dependencies), biên dịch chúng, và liên kết chúng cùng với nhau để tạo ra các thư viện và các file thực thi. Swift 3 là bản đầu tiên bao gồm Swift Package Manager. Có hơn 1000 thư viện đã hỗ trợ nó, và trong những tháng tới, bạn sẽ bắt đầu thấy nhiều định dạng cho nó.
Các tính năng dự định trong tương lai
Trước đây đã đề cập rằng Swift 3 hướng tới cho phép bạn lưu giữ code qua các phiên bản khác nhau trong tương lai bằng cách cố gắng tránh các thay đổi quan trọng. Mặc dù điều này là đúng, có mục tiêu liên quan chưa đạt được trong phiên bản lần này, đó là các bổ sung generics và độ ổn định của Application Binary Interface (ABI)
Các bổ sung generics sẽ bao gồm các giới hạn giao thức đệ quy và khả năng tạo ra một mở rộng hạn chế phù hợp với giao thức mới (như một mảng của các phần tử Equatable thì Equatable). Trước khi tính năng này được hoàn thiện, Swift chưa thể tuyên bố tính ổn định của ABI.
Ổn định hóa ABI sẽ cho phép các ứng dụng và thư viện được biên dịch với các phiên bản khác nhau của Swift để có thể kết nối và tương tác với nhau. Đây là một bước quan trọng cho các thư viện bên thứ ba để chuyển các frameworks tới mà không phải cung cấp mã nguồn do các phiên bản mới của Swift không chỉ yêu cầu chúng phải nâng cấp code mà còn phải xây lại các frameworks.
Thêm vào đó, sự ổn định của ABI sẽ xóa đi việc cần thiết đem thư viện chuẩn Swift cùng với các tệp nhị phân, như các trường hợp hiện tại với các ứng dụng iOS và macOS được tạo ra bẳng Xcode. Hiện tại, các tệp nhị phân được gói lại với thêm 2MB kích thước file nhằm đảm bảo rằng chúng sẽ chạy được trong các hệ điều hành tương lai.
Tóm lại, bây giờ bạn có thể giữ mã nguồn qua các phiên bản, nhưng sự tương thích mã nhị phân được biên dịch giữa các phiên bản vẫn chưa đạt được.
Tương lai
Swift tiếp tục phát triển do cộng đồng vẫn hướng tới sự tốt nhất. Mặc dù vẫn đang trong giai đoạn sơ khai, ngôn ngữ này có nhiều đà phát triển và tương lai rộng mở. Swift đã chạy trên Linux, và bạn sẽ có thể thấy nó chạy trên các máy chủ bên cạnh các thiết bị trong các năm tới đây.Việc thiết kế một ngôn ngữ bắt đầu từ đầu chắc chắn có những lợi thế riêng do cơ hội để phá vỡ sự ổn định ABI một khi nó được chốt lại là hiếm xảy ra. Đây là cơ hội duy nhất để có một ngôn ngữ chuẩn xác mà không phải hối lại.
Swift cũng đang mở rộng tầm với. Apple đang sử dụng chính sản phẩm của mình. Các nhóm phát triển ở Apple sử dụng Swift trên các ứng dụng Music, Console, picture-in-picture trong Sierra, xem Xcode Documentation, và ứng dụng Swift Playground mới cho iPad.
Nói về những điều đó, có một sự thúc đẩy lớn để những người không phải lập trình viên học Swift, cả trên iPad và qua các sang kiến giáo dục.
Swift vẫn tiếp tục cải tiến: mã code đọc rõ ràng hơn và bạn có các công cụ để chuyển sang. Nếu bạn được truyền cảm hứng để đào sâu hơn vấn đề, bạn có thể xem các video WWDC session videos.
Chắn chắn sẽ có nhiều điều nữa đến cho tới khi Swift được chính thức hoàn thiện vào cuối năm 2016. Chúng tôi sẽ tiếp tục cập nhật các nâng cấp tại đây, vì vậy hãy để mắt tới các hướng dẫn, các thông báo sách và videos.
Những phần nào của Swift 3 mà bạn quan tâm nhất? Bạn muốn chúng tôi viết kỹ về phần nào trước? Hãy comment ở phía dưới nhé.
Khóa học lập trình di động tại Techmaster:
Để cài đặt MacOSX lên phần cứng không phải Apple liên hệ chuyên gia cài Hackintosh:
- Nguyễn Minh Sơn: 01287065634
- Huỳnh Minh Sơn: 0936225565
- Website: caidatmacos.com
Bình luận